加載到進程地址空間的每一個可執行文件或者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); }