如何获得当前运行模块在进程地址空间的位置
(w)WinMain的hInstanceExe参数实际值是一个内存基地址;系统将可执行文件的映像加载到进程地址空间中的这个位置。例如,系统打开可执行文件,并将它加载到地址0x00400000,则(w)WinMain的hInstanceExe参数值为0x00400000.
为了知道一个可执行文件或DLL文件被加载到进程地址空间的什么位置,可以使用GetModuleHandle函数来返回一个句柄/基地址
HMODULE GetModuleHandle(PCTSTR pszModule)
调用这个函数是,要传递一个以0为终止字符的字符串,它指定了已在主调进程的地址空间中加载的一个可执行文件或DLL文件的名称。如果系统找到了可执行文件或DLL文件名称,GetModuleHandle就会返回可执行文件/DLL文件映像加载到基地址。如果没有找到文件,系统将返回NULL。
GetModuleHandle的另一个用法是为pszModule参数传入NULL,这样就可以返回主调进程模块的基地址。如果我们的代码在一个DLL中,那么可利用两种方法来了解代码正在什么模块中运行。第一个办法是利用链接器提供的伪变量__ImageBase,它指向当前正在运行的模块的基地址。这是C语言运行库启动代码在调用我们的(w)WinMain函数时所做的事情。
第二种方法是调用GetMoudleHandleEx,将GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS作为它的第一个参数,将当前函数的地址作为第二个参数。最后一个参数是一个指向HMODULE的指针,GetModuleHandleEx会用传入函数(即第二个参数)所在DLL的基地址来填写该指针。以下代码对这几种方法进行演示。
extern "C" const IMAGE_DOS_HEADER __ImageBase;
void DumpModule()
{
HMODULE hMoudle = GetModuleHandle(NULL);
_tprintf(TEXT("with GetModuleHandle(NULL) = 0x%x\r\n"),hMoudle);
_tprintf(TEXT("with _ImageBase = 0x%x\r\n"),(HINSTANCE)&__ImageBase);
hMoudle = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(PCTSTR)DumpModule,
&hMoudle);
_tprintf(TEXT("with GetModuleHandleEx = 0x%x\r\n"),hMoudle);
}
int _tmain(int argc, _TCHAR* argv[])
{
DumpModule();
return 0;
}
上一篇: Oracle SQL精妙SQL语句讲解
推荐阅读