2014-12-06 67 views
0

編輯:EnumProcessModulesEx和CreateToolHelp32Snapshot函數失敗 - 無論32位或64位

這個問題的答案就在這裏:

https://stackoverflow.com/a/27317947/996540

當你在MSVC裏創建一個項目,選項/ DYNAMICBASE是默認啓用 現在。由於ASLR(地址空間佈局隨機化,自Windows Vista以來), 每次運行一個exe時,它的加載地址都是隨機的。

我最近在做DLL注入工作,所以我在google上做了一些關於 的研究,並且讀過一些項目。獲取 exe的加載地址(基址)很重要。

看起來有兩個簡單的API來執行此操作:EnumProcessModulesEx和 CreateToolhelp32Snapshot。但我從來沒有成功。

所以這是代碼示例:

void TestEnumProcessModulesEx(const char* app) 
{ 
    std::cout << "Begin TestEnumProcessModulesEx(" << mybit() << ")" << std::endl; 

    STARTUPINFOA startupInfo = {0}; 
    startupInfo.cb = sizeof(startupInfo); 
    PROCESS_INFORMATION processInformation = {0}; 

    if (CreateProcessA(app, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation)) 
    { 
     std::vector<HMODULE> buf(128); 
     DWORD needed = 0; 
     for (;;) { 
      if (EnumProcessModulesEx(processInformation.hProcess, &buf[0], DWORD(buf.size()*sizeof(HMODULE)), &needed, LIST_MODULES_ALL) == FALSE) { 
       DWORD ec = GetLastError(); 
       std::cout << "GetLastError() = " << ec << std::endl; 
       break; 
      } 
      else if (needed <= buf.size() * sizeof(HMODULE)) { 
       break; 
      } 
      else { 
       const size_t oldSize = buf.size(); 
       buf.resize(oldSize * 2); 
      } 
     } 
     ResumeThread(processInformation.hThread); 
     WaitForSingleObject(processInformation.hProcess, INFINITE); 
    } 

    std::cout << "End TestEnumProcessModulesEx(" << mybit() << ")" << std::endl; 
} 

爲了減少這個問題,完整代碼的長度 - 包括 CreateToolHelp32Snapshot函數的測試代碼 - 這裏沒有列出,但你可以從它 :

https://dl.dropboxusercontent.com/u/235920/enum_proc_mods_sample.7zhttps://www.mediafire.com/?cry3pnra8392099

「如果這個函數是從3稱爲在WOW64上運行的2位應用程序,它可以 只枚舉32位進程的模塊。如果這個過程是一個64位 過程中,此函數失敗,最後錯誤代碼是ERROR_PARTIAL_COPY (299)「 - 從MSDN

這是一個博客帖子這個問題: http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/

不幸的是,這並沒有讓SENCE,因爲無論指定 過程爲32位或64位時,出現299;無論主叫過程 32位或64位時,出現299

這是輸出我的樣品:

Begin TestEnumProcessModulesEx(32bit) 
GetLastError() = 299 
hello world 32bit 
End TestEnumProcessModulesEx(32bit) 

Begin TestEnumProcessModulesEx(32bit) 
GetLastError() = 299 
hello world 64bit 
End TestEnumProcessModulesEx(32bit) 

Begin TestEnumProcessModulesEx(64bit) 
GetLastError() = 299 
hello world 32bit 
End TestEnumProcessModulesEx(64bit) 

Begin TestEnumProcessModulesEx(64bit) 
GetLastError() = 299 
hello world 64bit 
End TestEnumProcessModulesEx(64bit) 

如您所見,任何組合都失敗。

我的操作系統是Windows 7 64位專業版,我的編譯器是VS2013。

那麼,我該怎麼辦?

+1

「如果在目標進程模塊列表中被損壞或尚未初始化... EnumProcessModulesEx可能失敗或返回不正確的信息」 - 也許是因爲過程中已創建在暫停狀態下,它一直沒有運行,所以它的模塊列表是「尚未初始化」? – 2014-12-06 11:19:18

+0

@JonathanPotter所以我已刪除CREATE_SUSPENDED,讓運行的過程,但它仍然失敗,299 – amanjiang 2014-12-06 11:21:19

+0

@JonathanPotter你是對的。今天,我再次測試程序,沒有CREATE_SUSPENDED標誌,保持運行一段子過程,它的工作原理。 – amanjiang 2014-12-08 03:54:15

回答

0

我不知道EnumProcessModulesEx和 CreateToolhelp32Snapshot的失敗,讓我們把這個問題留給專家。

我的目標是讓子進程的加載地址(基址),發現 切入點和打補丁 - 修補入口點的原因是在這裏: https://opcode0x90.wordpress.com/2011/01/15/injecting-dll-into-process-on-load/

由於DLL注入我的主要目的,我不得不重新考慮這個 的問題。我會使用「遠程線程&調用LoadLibrary技術」 http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_2 做DLL注入(其實ASLR是不是這個技術的方式護欄管), 雖然有DllMain中 http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971%28v=vs.85%29.aspx 這麼多的限制,但做了小小的作品是OK的:使用 GetModuleHandleA(NULL)查找exe的基地址,將HMODULE保存返回到共享內存中,接下來,調用者進程讀取共享內存並獲取HMODULE。 當然需要同步機制。

所以,答案是IPC。 (不是每個IPC機制是安全的DllMain中的方式)