假设我没有导入.lib库 我希望通过手工编写原始的一切 调用(如汇编或纯c)
GetProcAdress LoadLibrary是winapi dll的一部分 一般来说,加载dll并获取指针 功能我需要调用那两个,但作为我 不知道我可以用它来获取它们吗?
这有点像悖论,可能它可以通过其他一些机制来解决,但在这里我缺乏知识表明,我不知道这种机制是什么,有人可以解释一下吗?
答案 0 :(得分:6)
以下工作假设从kernel32.dll内部调用mainCRTStartup()。 它使用返回地址来定位模块的开头,并从那里搜索其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 );
}
答案 1 :(得分:5)
我之前已经设法做到了这一点。这确实是可能的。解决方案是基本上手动实施LdrGetDllHandle
并使用它来搜索LdrLoadDll
内的LdrUnloadDll
/ LdrGetProcedureAddress
和NTDLL
通过PEB_LDR_DATA
指向进程NtCurrentPeb
数据结构的指针,这是一个读取FS或GS CPU寄存器的宏。
一旦有了这三个函数的指针,就可以使用它们来加载你需要的其他DLL。
我不打算为你发布代码,但如果你看看ReactOS的源代码,你应该能够逐步弄清楚如何实现这个 - 我认为这些应该是足够的指针(没有双关语)意图)让你开始。 :)