DLL文件都被赋予了一个独一无二的实例句柄。可执行文件的实例被当作WinMain函数的第一个参数hInstance传入。该参数实际值是一个内存基地址:系统将可执行文件的映像加载到进程地址空间中的这个位置。可执行文件的映像具体加载到哪一个基地址,是有连接器决定的。使用VC连接器的/BASE:address连接器开关,可以更改要将应用程序加载到哪个地址。
DLL加载到进程地址空间的什么位置,可以使用GetModuleHandle函数,函数的原型如下:
HANDLE GetModuleHandle(PCTSTR pszModule);
,将参数设置为可执行文件或者DLL文件的名称,如果系统找到了可执行文件或者DLL文件的名称,就会返回该可执行文件或者DLL的文件被加载到的进程地址空间的基地址,如果没找到(可能是因为DLL没有被加载到进程地址空间中),就会返回NULL。
NULL,就会返回进程地址空间中的可执行文件的基地址。注意:即使调用该函数的代码存在于DLL文件,返回值也是可执行文件的基地址,而不是DLL文件的基地址。
DLL文件中,那么可利用两种方法来获取该DLL模块在进程地址空间中的基地址:
一、利用连接器提供的伪变量__ImageBase
代码如下:
extern “C” const IMAGE_DOS_HEADER __ImageBase //连接器定义的伪变量
void demo()
{
printf(“%x\r\n”, __ImageBase);
}
二、使用GetModuleHandleEx函数
代码如下:
void demo()
{
HANDLE hModule = NULL; //DLL模块的基地址
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(PCTSTR)DumpModule,
&hModule);
}