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:
|
v1.60, 22 to 24 November, 2012:
|
||||||
alternative method to obtain LLW for 64->32 injection;
|
alternative method to obtain LLW for 64->32 injection;
|
||||||
support for VC6 (remove section pragma, rename isdigit to is_digit).
|
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"
|
#include "ansicon.h"
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
write the date if appending to the log.
|
write the date if appending to the log.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PDATE L"24 November, 2012"
|
#define PDATE L"14 February, 2013"
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
142
injdll32.c
142
injdll32.c
@ -32,96 +32,9 @@ TWow64SetThreadContext Wow64SetThreadContext;
|
|||||||
#define GetThreadContext Wow64GetThreadContext
|
#define GetThreadContext Wow64GetThreadContext
|
||||||
#define SetThreadContext Wow64SetThreadContext
|
#define SetThreadContext Wow64SetThreadContext
|
||||||
|
|
||||||
#define MakeVA( cast, offset ) (cast)((DWORD_PTR)base + (DWORD)(offset))
|
extern
|
||||||
|
|
||||||
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;
|
|
||||||
#endif
|
#endif
|
||||||
|
DWORD LLW32;
|
||||||
|
|
||||||
|
|
||||||
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
||||||
@ -138,6 +51,22 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
|||||||
PDWORD pL;
|
PDWORD pL;
|
||||||
} ip;
|
} 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);
|
len = TSIZE(lstrlen( dll ) + 1);
|
||||||
if (len > TSIZE(MAX_PATH))
|
if (len > TSIZE(MAX_PATH))
|
||||||
return;
|
return;
|
||||||
@ -145,28 +74,29 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
|
|||||||
if (LLW32 == 0)
|
if (LLW32 == 0)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#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;
|
return;
|
||||||
|
}
|
||||||
|
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||||
|
GetExitCodeProcess( pi.hProcess, &LLW32 );
|
||||||
|
CloseHandle( pi.hProcess );
|
||||||
|
CloseHandle( pi.hThread );
|
||||||
#else
|
#else
|
||||||
LLW32 = (DWORD)GetProcAddress( GetModuleHandleA( "kernel32.dll" ),
|
LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
|
||||||
"LoadLibraryW" );
|
"LoadLibraryW" );
|
||||||
#endif
|
#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 );
|
CopyMemory( code + CODESIZE, dll, len );
|
||||||
len += CODESIZE;
|
len += CODESIZE;
|
||||||
|
5
makefile
5
makefile
@ -36,7 +36,7 @@ all: ansicon32 ansicon64
|
|||||||
|
|
||||||
ansicon32: x86 x86/ansicon.exe x86/ANSI32.dll
|
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:
|
x86:
|
||||||
cmd /c "mkdir 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
|
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
|
$(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/ansicon.o: version.h
|
||||||
x86/ANSI.o: version.h
|
x86/ANSI.o: version.h
|
||||||
x64/ansicon.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)
|
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
|
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
|
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
|
$(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.c: ansicon.h version.h
|
||||||
ansicon.rc: version.h
|
ansicon.rc: version.h
|
||||||
ANSI.c: ansicon.h version.h
|
ANSI.c: ansicon.h version.h
|
||||||
|
10
version.h
10
version.h
@ -2,8 +2,8 @@
|
|||||||
version.h - Version defines.
|
version.h - Version defines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PVERS L"1.60" // wide string
|
#define PVERS L"1.61" // wide string
|
||||||
#define PVERSA "1.60" // ANSI string (windres 2.16.91 didn't like L)
|
#define PVERSA "1.61" // ANSI string (windres 2.16.91 didn't like L)
|
||||||
#define PVERE L"160" // wide environment string
|
#define PVERE L"161" // wide environment string
|
||||||
#define PVEREA "160" // ANSI environment string
|
#define PVEREA "161" // ANSI environment string
|
||||||
#define PVERB 1,6,0,0 // binary (resource)
|
#define PVERB 1,6,1,0 // binary (resource)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user