加载到进程地址空间的每一个可执行文件或者DLL文件都被赋予了一个独一无二的实例句柄。可执行文件的实例被当作WinMain函数的第一个参数hInstance传入。该参数实际值是一个内存基地址:系统将可执行文件的映像加载到进程地址空间中的这个位置。可执行文件的映像具体加载到哪一个基地址,是有连接器决定的。使用VC连接器的/BASEaddress连接器开关,可以更改要将应用程序加载到哪个地址。

  获取可执行文件或者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);

}