没有它们如何获取 GetProcAdress 和 LoadLibrary?
How to obtain GetProcAdress and LoadLibrary without them?
假设我没有导入 .lib 库
我希望一切都以原始方式进行,通过手动编写
调用(如汇编或纯 c)
GetProcAdress LoadLibrary 是 winapi dll 的一部分
通常加载 dll 并获取指针
对于我需要调用这两个函数的函数,但是因为我
没有得到它们我可以用什么来获得它们?
这有点像悖论,可能可以通过一些其他机制来解决,但是在这里我缺乏知识,我不知道这个机制是什么,有人可以解释一下吗?
我以前确实做到过。确实有可能。解决方案基本上是手动实现 LdrGetDllHandle
并使用它在 [=14= 中搜索 LdrLoadDll
/LdrUnloadDll
和 LdrGetProcedureAddress
] 通过 NtCurrentPeb
获取指向进程 PEB_LDR_DATA
数据结构的指针,这是一个读取 FS 或 GS CPU 寄存器的宏。
一旦您获得了这三个函数的指针,您就可以使用它们来加载您需要的其他 DLL。
我不会 post 代码给你,但是如果你看一下 ReactOS 的源代码,你应该能够逐渐弄清楚如何实现这个 -- 我认为这些应该足够的指导(没有双关语意)让你开始。 :)
以下假设从内部调用 mainCRTStartup() kernel32.dll。
它使用 return 地址定位模块的开始,并从那里搜索其 EAT 以获取 GetProcAddress()。
#include <windows.h>
static HMODULE findModuleBase( void *ptr )
{
ULONG_PTR addr = (ULONG_PTR)ptr;
addr &= ~0xffff;
const UINT32 *mod = (const UINT32*)addr;
while( mod[0]!=0x00905a4d ) // MZ.. header
mod -= 0x4000; // 0x10000/4
return( (HMODULE)mod );
}
#define REL_PTR( base,ofs ) ( ((PBYTE)base)+ofs )
static void *findGetProcAddress( HMODULE mod )
{
PIMAGE_DOS_HEADER idh = (PIMAGE_DOS_HEADER)mod;
PIMAGE_NT_HEADERS inh = (PIMAGE_NT_HEADERS)REL_PTR( idh,idh->e_lfanew );
PIMAGE_EXPORT_DIRECTORY ied =
(PIMAGE_EXPORT_DIRECTORY)REL_PTR( idh,inh->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress );
DWORD *names = (DWORD*)REL_PTR( idh,ied->AddressOfNames );
unsigned int i;
for( i=0; i<ied->NumberOfNames; i++ )
{
const UINT32 *name32 = (const UINT32*)REL_PTR( idh,names[i] );
const UINT16 *name16 = (const UINT16*)name32;
const UINT8 *name8 = (const UINT8*)name32;
if( name32[0]!=0x50746547 || // GetP
name32[1]!=0x41636f72 || // rocA
name32[2]!=0x65726464 || // ddre
name16[6]!=0x7373 || // ss
name8[14]!=0x00 )
continue;
WORD *ordinals = (WORD*)REL_PTR( idh,ied->AddressOfNameOrdinals );
DWORD *funcs = (DWORD*)REL_PTR( idh,ied->AddressOfFunctions );
return( REL_PTR(idh,funcs[ordinals[i]]) );
}
return( NULL );
}
#ifdef __MINGW32__
#define RETURN_ADDRESS() __builtin_return_address(0)
#else
#define RETURN_ADDRESS() _ReturnAddress()
#endif
void mainCRTStartup( void )
{
HMODULE kernel = findModuleBase( RETURN_ADDRESS() );
typedef LPVOID WINAPI func_GetProcAddress( HMODULE,LPCSTR );
func_GetProcAddress *fGetProcAddress = findGetProcAddress( kernel );
typedef HMODULE WINAPI func_LoadLibraryA( LPCSTR );
typedef VOID WINAPI func_ExitProcess( UINT );
func_LoadLibraryA *fLoadLibraryA = fGetProcAddress( kernel,"LoadLibraryA" );
func_ExitProcess *fExitProcess = fGetProcAddress( kernel,"ExitProcess" );
typedef int func_printf( const char*,... );
HMODULE msvcrt = fLoadLibraryA( "msvcrt.dll" );
func_printf *f_printf = fGetProcAddress( msvcrt,"printf" );
f_printf( "is this working?\n" );
fExitProcess( 1 );
}
假设我没有导入 .lib 库 我希望一切都以原始方式进行,通过手动编写 调用(如汇编或纯 c)
GetProcAdress LoadLibrary 是 winapi dll 的一部分 通常加载 dll 并获取指针 对于我需要调用这两个函数的函数,但是因为我 没有得到它们我可以用什么来获得它们?
这有点像悖论,可能可以通过一些其他机制来解决,但是在这里我缺乏知识,我不知道这个机制是什么,有人可以解释一下吗?
我以前确实做到过。确实有可能。解决方案基本上是手动实现 LdrGetDllHandle
并使用它在 [=14= 中搜索 LdrLoadDll
/LdrUnloadDll
和 LdrGetProcedureAddress
] 通过 NtCurrentPeb
获取指向进程 PEB_LDR_DATA
数据结构的指针,这是一个读取 FS 或 GS CPU 寄存器的宏。
一旦您获得了这三个函数的指针,您就可以使用它们来加载您需要的其他 DLL。
我不会 post 代码给你,但是如果你看一下 ReactOS 的源代码,你应该能够逐渐弄清楚如何实现这个 -- 我认为这些应该足够的指导(没有双关语意)让你开始。 :)
以下假设从内部调用 mainCRTStartup() kernel32.dll。 它使用 return 地址定位模块的开始,并从那里搜索其 EAT 以获取 GetProcAddress()。
#include <windows.h>
static HMODULE findModuleBase( void *ptr )
{
ULONG_PTR addr = (ULONG_PTR)ptr;
addr &= ~0xffff;
const UINT32 *mod = (const UINT32*)addr;
while( mod[0]!=0x00905a4d ) // MZ.. header
mod -= 0x4000; // 0x10000/4
return( (HMODULE)mod );
}
#define REL_PTR( base,ofs ) ( ((PBYTE)base)+ofs )
static void *findGetProcAddress( HMODULE mod )
{
PIMAGE_DOS_HEADER idh = (PIMAGE_DOS_HEADER)mod;
PIMAGE_NT_HEADERS inh = (PIMAGE_NT_HEADERS)REL_PTR( idh,idh->e_lfanew );
PIMAGE_EXPORT_DIRECTORY ied =
(PIMAGE_EXPORT_DIRECTORY)REL_PTR( idh,inh->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress );
DWORD *names = (DWORD*)REL_PTR( idh,ied->AddressOfNames );
unsigned int i;
for( i=0; i<ied->NumberOfNames; i++ )
{
const UINT32 *name32 = (const UINT32*)REL_PTR( idh,names[i] );
const UINT16 *name16 = (const UINT16*)name32;
const UINT8 *name8 = (const UINT8*)name32;
if( name32[0]!=0x50746547 || // GetP
name32[1]!=0x41636f72 || // rocA
name32[2]!=0x65726464 || // ddre
name16[6]!=0x7373 || // ss
name8[14]!=0x00 )
continue;
WORD *ordinals = (WORD*)REL_PTR( idh,ied->AddressOfNameOrdinals );
DWORD *funcs = (DWORD*)REL_PTR( idh,ied->AddressOfFunctions );
return( REL_PTR(idh,funcs[ordinals[i]]) );
}
return( NULL );
}
#ifdef __MINGW32__
#define RETURN_ADDRESS() __builtin_return_address(0)
#else
#define RETURN_ADDRESS() _ReturnAddress()
#endif
void mainCRTStartup( void )
{
HMODULE kernel = findModuleBase( RETURN_ADDRESS() );
typedef LPVOID WINAPI func_GetProcAddress( HMODULE,LPCSTR );
func_GetProcAddress *fGetProcAddress = findGetProcAddress( kernel );
typedef HMODULE WINAPI func_LoadLibraryA( LPCSTR );
typedef VOID WINAPI func_ExitProcess( UINT );
func_LoadLibraryA *fLoadLibraryA = fGetProcAddress( kernel,"LoadLibraryA" );
func_ExitProcess *fExitProcess = fGetProcAddress( kernel,"ExitProcess" );
typedef int func_printf( const char*,... );
HMODULE msvcrt = fLoadLibraryA( "msvcrt.dll" );
func_printf *f_printf = fGetProcAddress( msvcrt,"printf" );
f_printf( "is this working?\n" );
fExitProcess( 1 );
}