Go back to using ANSI-LLW.exe.
This commit is contained in:
parent
a52a46c9c1
commit
c5cb4788c2
23
ANSI-LLW.asm
Normal file
23
ANSI-LLW.asm
Normal file
@ -0,0 +1,23 @@
|
||||
; ANSI-LLW.asm - Output the 32-bit address of LoadLibraryW.
|
||||
;
|
||||
; Jason Hood, 1 February, 2013.
|
||||
;
|
||||
; A FASM (flatassembler.net) version of the C code, which virus scanners didn't
|
||||
; like for some reason.
|
||||
|
||||
|
||||
format PE Console 4.0
|
||||
|
||||
include 'win32a.inc'
|
||||
|
||||
mov eax, [LoadLibraryW]
|
||||
ret
|
||||
|
||||
data import
|
||||
|
||||
library kernel32,'KERNEL32.DLL'
|
||||
|
||||
import kernel32,\
|
||||
LoadLibraryW,'LoadLibraryW'
|
||||
|
||||
end data
|
22
ANSI-LLW.c
Normal file
22
ANSI-LLW.c
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ANSI-LLW.c - Output the 32-bit address of LoadLibraryW.
|
||||
|
||||
Jason Hood, 13 November, 2010 (LLA version 5 September, 2010).
|
||||
|
||||
I don't know of a method to retrieve the 32-bit address of a function in
|
||||
64-bit code, so this is a simple workaround.
|
||||
|
||||
18 December, 2010: Initially I used GetProcAddress, but then I thought that
|
||||
was silly, why don't I just return LoadLibraryW directly? That worked fine
|
||||
for TDM64 and VC, but MinGW32 would return the address of the jump to the
|
||||
function, not the function itself. Not so silly after all.
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
int main( void )
|
||||
{
|
||||
return (DWORD)GetProcAddress( GetModuleHandle( "kernel32.dll" ),
|
||||
"LoadLibraryW" );
|
||||
}
|
3
ANSI.c
3
ANSI.c
@ -95,6 +95,9 @@
|
||||
v1.60, 22 to 24 November, 2012:
|
||||
alternative method to obtain LLW for 64->32 injection;
|
||||
support for VC6 (remove section pragma, rename isdigit to is_digit).
|
||||
|
||||
v1.61, 14 February, 2013:
|
||||
go back to using ANSI-LLW.exe for 64->32 injection.
|
||||
*/
|
||||
|
||||
#include "ansicon.h"
|
||||
|
@ -71,7 +71,7 @@
|
||||
write the date if appending to the log.
|
||||
*/
|
||||
|
||||
#define PDATE L"24 November, 2012"
|
||||
#define PDATE L"14 February, 2013"
|
||||
|
||||
#include "ansicon.h"
|
||||
#include "version.h"
|
||||
|
142
injdll32.c
142
injdll32.c
@ -32,96 +32,9 @@ TWow64SetThreadContext Wow64SetThreadContext;
|
||||
#define GetThreadContext Wow64GetThreadContext
|
||||
#define SetThreadContext Wow64SetThreadContext
|
||||
|
||||
#define MakeVA( cast, offset ) (cast)((DWORD_PTR)base + (DWORD)(offset))
|
||||
|
||||
extern DWORD LLW32;
|
||||
LPVOID base;
|
||||
|
||||
int export_cmp( const void* a, const void* b )
|
||||
{
|
||||
return strcmp( (LPCSTR)a, MakeVA( LPCSTR, *(const PDWORD)b ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get the address of the 32-bit LoadLibraryW function from 64-bit code. This
|
||||
was originally done via executing a helper program (ANSI-LLW.exe), but for
|
||||
some reason, virus scanners really didn't like it (even when I rewrote it in
|
||||
assembly so it was 1024 bytes and literally two instructions, virustotal
|
||||
still had three scanners complaining). Now I do it the "hard" way - load the
|
||||
32-bit kernel32.dll directly and search the exports. Even worse, it seems
|
||||
Wow64 loads kernel32.dll at a different base address each boot (at least, I
|
||||
hope it only changes each boot). Fortunately, loading the DLL as an image in
|
||||
64-bit code seems to use the 32-bit address.
|
||||
*/
|
||||
BOOL get_LLW32( void )
|
||||
{
|
||||
HMODULE kernel32;
|
||||
TCHAR buf[MAX_PATH];
|
||||
UINT len;
|
||||
PIMAGE_DOS_HEADER pDosHeader;
|
||||
PIMAGE_NT_HEADERS32 pNTHeader;
|
||||
PIMAGE_EXPORT_DIRECTORY pExportDir;
|
||||
PDWORD fun_table, name_table;
|
||||
PWORD ord_table;
|
||||
PDWORD pLLW;
|
||||
|
||||
len = GetSystemWow64Directory( buf, MAX_PATH );
|
||||
wcscpy( buf + len, L"\\kernel32.dll" );
|
||||
// MinGW-w64 has a typo, calling it LINRARY.
|
||||
kernel32 = LoadLibraryEx( buf, NULL, 0x20/*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/ );
|
||||
if (kernel32 == NULL)
|
||||
{
|
||||
DEBUGSTR( 1, L"Unable to load 32-bit kernel32.dll!" );
|
||||
return FALSE;
|
||||
}
|
||||
// The handle uses low bits as flags, so strip 'em off.
|
||||
base = (LPVOID)((DWORD_PTR)kernel32 & 0xFFFF0000);
|
||||
|
||||
// Tests to make sure we're looking at a module image (the 'MZ' header)
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)base;
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
DEBUGSTR( 1, L"Image has no DOS header!" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The MZ header has a pointer to the PE header
|
||||
pNTHeader = MakeVA( PIMAGE_NT_HEADERS32, pDosHeader->e_lfanew );
|
||||
|
||||
// One more test to make sure we're looking at a "PE" image
|
||||
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
DEBUGSTR( 1, L"Image has no NT header!" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// We now have a valid pointer to the module's PE header.
|
||||
// Get a pointer to its exports section.
|
||||
pExportDir = MakeVA( PIMAGE_EXPORT_DIRECTORY,
|
||||
pNTHeader->OptionalHeader.
|
||||
DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].
|
||||
VirtualAddress );
|
||||
|
||||
fun_table = MakeVA( PDWORD, pExportDir->AddressOfFunctions );
|
||||
name_table = MakeVA( PDWORD, pExportDir->AddressOfNames );
|
||||
ord_table = MakeVA( PWORD, pExportDir->AddressOfNameOrdinals );
|
||||
|
||||
pLLW = bsearch( "LoadLibraryW", name_table, pExportDir->NumberOfNames,
|
||||
sizeof(DWORD), export_cmp );
|
||||
if (pLLW == NULL)
|
||||
{
|
||||
DEBUGSTR( 1, L"Could not find LoadLibraryW!" );
|
||||
return FALSE;
|
||||
}
|
||||
LLW32 = MakeVA( DWORD, fun_table[ord_table[pLLW - name_table]] );
|
||||
|
||||
FreeLibrary( kernel32 );
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
DWORD LLW32;
|
||||
extern
|
||||
#endif
|
||||
DWORD LLW32;
|
||||
|
||||
|
||||
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
||||
@ -138,6 +51,22 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
||||
PDWORD pL;
|
||||
} ip;
|
||||
|
||||
#ifdef IMPORT_WOW64
|
||||
if (Wow64GetThreadContext == 0)
|
||||
{
|
||||
#define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
|
||||
HMODULE hKernel = GetModuleHandle( L"kernel32.dll" );
|
||||
GETPROC( Wow64GetThreadContext );
|
||||
GETPROC( Wow64SetThreadContext );
|
||||
// Assume if one is defined, so is the other.
|
||||
if (Wow64GetThreadContext == 0)
|
||||
{
|
||||
DEBUGSTR( 1, L"Failed to get pointer to Wow64GetThreadContext." );
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
len = TSIZE(lstrlen( dll ) + 1);
|
||||
if (len > TSIZE(MAX_PATH))
|
||||
return;
|
||||
@ -145,28 +74,29 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
||||
if (LLW32 == 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
if (!get_LLW32())
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
// ...ANSI32.dll\0
|
||||
CopyMemory( code, dll, len - TSIZE(7) );
|
||||
// ...ANSI-LLW.exe\0
|
||||
CopyMemory( code + len - TSIZE(7), L"-LLW.exe", TSIZE(9) );
|
||||
if (!CreateProcess( (LPCTSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
|
||||
&si, &pi ))
|
||||
{
|
||||
DEBUGSTR( 1, L"Failed to execute \"%s\".", (LPCTSTR)code );
|
||||
return;
|
||||
}
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
GetExitCodeProcess( pi.hProcess, &LLW32 );
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
#else
|
||||
LLW32 = (DWORD)GetProcAddress( GetModuleHandleA( "kernel32.dll" ),
|
||||
LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
|
||||
"LoadLibraryW" );
|
||||
#endif
|
||||
}
|
||||
#ifdef IMPORT_WOW64
|
||||
if (Wow64GetThreadContext == 0)
|
||||
{
|
||||
#define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
|
||||
HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
|
||||
GETPROC( Wow64GetThreadContext );
|
||||
GETPROC( Wow64SetThreadContext );
|
||||
// Assume if one is defined, so is the other.
|
||||
if (Wow64GetThreadContext == 0)
|
||||
{
|
||||
DEBUGSTR( 1, L"Failed to get pointer to Wow64GetThreadContext.\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CopyMemory( code + CODESIZE, dll, len );
|
||||
len += CODESIZE;
|
||||
|
5
makefile
5
makefile
@ -36,7 +36,7 @@ all: ansicon32 ansicon64
|
||||
|
||||
ansicon32: x86 x86/ansicon.exe x86/ANSI32.dll
|
||||
|
||||
ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll
|
||||
ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll x64/ANSI-LLW.exe
|
||||
|
||||
x86:
|
||||
cmd /c "mkdir x86"
|
||||
@ -59,6 +59,9 @@ x64/ANSI64.dll: x64/ANSI.o $(X64OBJS) x64/ansiv.o
|
||||
x64/ANSI32.dll: x64/ANSI32.o x64/proctype32.o x86/injdll32.o x86/util.o x86/ansiv.o
|
||||
$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000
|
||||
|
||||
x64/ANSI-LLW.exe: ANSI-LLW.c
|
||||
$(CC) -m32 $(CFLAGS) $< -s -o $@
|
||||
|
||||
x86/ansicon.o: version.h
|
||||
x86/ANSI.o: version.h
|
||||
x64/ansicon.o: version.h
|
||||
|
@ -63,7 +63,7 @@ X64OBJS = x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\util.obj
|
||||
|
||||
all: ansicon$(BITS)
|
||||
|
||||
ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64\ANSI32.dll
|
||||
ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64 x64\ANSI32.dll x64\ANSI-LLW.exe
|
||||
|
||||
ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll
|
||||
|
||||
@ -88,6 +88,9 @@ x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res
|
||||
x64\ANSI32.dll: x64\ANSI32.obj x64\proctype32.obj x86\injdll32.obj x86\util.obj x86\ansi.res
|
||||
$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512
|
||||
|
||||
x64\ANSI-LLW.exe: ANSI-LLW.c
|
||||
$(CC) $(CFLAGS) /Fe$@ /Fo$*.obj $? $(LIBS64)
|
||||
|
||||
ansicon.c: ansicon.h version.h
|
||||
ansicon.rc: version.h
|
||||
ANSI.c: ansicon.h version.h
|
||||
|
10
version.h
10
version.h
@ -2,8 +2,8 @@
|
||||
version.h - Version defines.
|
||||
*/
|
||||
|
||||
#define PVERS L"1.60" // wide string
|
||||
#define PVERSA "1.60" // ANSI string (windres 2.16.91 didn't like L)
|
||||
#define PVERE L"160" // wide environment string
|
||||
#define PVEREA "160" // ANSI environment string
|
||||
#define PVERB 1,6,0,0 // binary (resource)
|
||||
#define PVERS L"1.61" // wide string
|
||||
#define PVERSA "1.61" // ANSI string (windres 2.16.91 didn't like L)
|
||||
#define PVERE L"161" // wide environment string
|
||||
#define PVEREA "161" // ANSI environment string
|
||||
#define PVERB 1,6,1,0 // binary (resource)
|
||||
|
Loading…
x
Reference in New Issue
Block a user