2014-10-20 21 views
0

此代碼在64位應用程序中運行。目標應用程序是32位。CreateToolhelp32Snapshot:INVALID_HANDLE_VALUE(ERROR_PARTIAL_COPY)

每次運行此代碼時,CreateToolhelp32Snapshot()返回INVALID_HANDLE_VALUE,然後GetLastError()返回ERROR_PARTIAL_COPY。所以它跳過循環並返回false。

BOOL HookInjector::InjectIntoProcess(DWORD pID) 
{ 
    //Get Handle to Remote Process 
    HANDLE Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); 
    .... 
    //Check to see if 64-bit or 32-bit application 
    IsWow64Process(Proc, &isWow64); 
    size_t szCurProc = sizeof(void*); //returns 8 
    if (isWow64) 
    { 
     __debugbreak(); 
     //Get list of all Modules associated with the Process 
     HANDLE hProc32Module; 
     do { 
      hProc32Module = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32, pID); 
     } 
     while ((hProc32Module == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_BAD_LENGTH)); 

    if (hProc32Module == INVALID_HANDLE_VALUE) { 
     __debugbreak(); 
     DWORD err = GetLastError(); //just to see the error code which is 0x12b 
     return false; 
    } 

     //Find the module for Kernel.dll and get the base address of it 
     MODULEENTRY32 entryModule; 
     entryModule.dwSize = sizeof(MODULEENTRY32); 
     BOOL isGetModuleSuccess = Module32First(hProc32Module, &entryModule); 
     DWORD errEndofList = GetLastError(); 
     BOOL isSuccessful = false; 
     while (errEndofList != ERROR_NO_MORE_FILES && isGetModuleSuccess) 
     { 
      if (_tcscmp(entryModule.szModule, KERNEL32_DLL)){ 
       isSuccessful = true; 
       break; 
      } 
      isGetModuleSuccess = Module32Next(hProc32Module, &entryModule); 
      errEndofList = GetLastError(); 
     } 

     if (!isSuccessful) 
     { 
      __debugbreak(); 
      CloseHandle(hProc32Module); 
      return false; 
     } 

     //Get handle for Kernel.dll module 
     hKernel32 = entryModule.hModule; 
     CloseHandle(hProc32Module); 
    } 
    else 
    { 
     .... 
+2

你知道哪個函數調用產生的錯誤?我們當然不會。你所有的錯誤檢查都是錯誤的,所以你可能不知道。你必須檢查返回值。你沒有。如果返回值指示失敗,並且文檔說上一個錯誤是有效的,則調用'GetLastError'。我強烈建議您修復錯誤檢查,然後再詢問一次。 – 2014-10-20 20:46:41

+0

@DavidHeffernan:Sry,回合。是的,我知道哪個函數會產生錯誤。 hProc32Module = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32,pID); hProc32Module在此行之後不應該爲INVALID_HANDLE_VALUE。但是,這意味着發生了錯誤,因爲如果發生錯誤,CreateToolhelp32Snapshot僅返回句柄或INVALID_HANDLE_VALUE。 – Informat 2014-10-20 21:02:29

+0

那麼,在這種情況下,我想你是處於最佳狀態的人。 – 2014-10-20 21:03:12

回答

0

按照documentationCreateToolhelp32Snapshot()只有失敗,ERROR_PARTIAL_COPYCreateToolhelp32Snapshot()由32位進程試圖訪問一個64位的過程被稱爲:

如果指定的進程是一個64位進程和調用者是32位進程,該函數失敗,最後一個錯誤代碼爲ERROR_PARTIAL_COPY(299)。

確保您的應用程序確實是爲64位編譯開始的。 TH32CS_SNAPMODULE32纔有意義使用時CreateToolhelp32Snapshot()被稱爲在一個64位的過程:從64調用時

TH32CS_SNAPMODULE32
0x00000010
包括在快照在th32ProcessID指定的進程的所有32位模塊bit process

您也沒有考慮到GetLastError()僅在API函數失敗時更新,除非另有說明。你的循環假設每個API調用後都會更新GetLastError(),這根本不是這樣。

嘗試一些更喜歡這個:

BOOL HookInjector::InjectIntoProcess(DWORD pID) 
{ 
    //Get Handle to Remote Process 
    HANDLE Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); 
    .... 

    DWORD dwFlag; 
    #ifdef _WIN64 
    //Check if Remote Process is a 32-bit application 
    BOOL isWow64 = FALSE; 
    IsWow64Process(Proc, &isWow64); 
    if (!isWow64) return false; 
    // TH32CS_SNAPMODULE32 includes 32bit modules when used by a 64bit process... 
    dwFlag = TH32CS_SNAPMODULE32; 
    #else 
    // TH32CS_SNAPMODULE includes 32bit modules when used by a 32bit process... 
    dwFlag = TH32CS_SNAPMODULE; 
    #endif 

    __debugbreak(); 

    //Get list of all Modules associated with the Process 

    HANDLE hProc32Module; 
    do { 
     hProc32Module = CreateToolhelp32Snapshot(dwFlag, pID); 
    } 
    while ((hProc32Module == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_BAD_LENGTH)); 

    if (hProc32Module == INVALID_HANDLE_VALUE) { 
     __debugbreak(); 
     return false; 
    } 

    //Find the module for Kernel.dll and get the base address of it 

    hKernel32 = NULL; 

    MODULEENTRY32 entryModule = {0}; 
    entryModule.dwSize = sizeof(MODULEENTRY32); 

    BOOL isGetModuleSuccess = Module32First(hProc32Module, &entryModule); 
    while (isGetModuleSuccess) { 
     if (_tcscmp(entryModule.szModule, KERNEL32_DLL)) { 
      hKernel32 = entryModule.hModule; 
      break; 
     } 
     isGetModuleSuccess = Module32Next(hProc32Module, &entryModule); 
    } 

    if (!hKernel32) { 
     __debugbreak(); 
     CloseHandle(hProc32Module); 
     return false; 
    } 

    CloseHandle(hProc32Module); 

    .... 
} 
+0

我確信我的應用程序是64位的原因是因爲我能夠將64位dll文件加載到64位進程中(我的鉤子工作正常)。這就是爲什麼我在爲什麼在32位進程上運行此應用程序之前返回ERROR_PARTIAL_COPY和INVALID_HANDLE_VALUE的原因而完全傻眼。 – Informat 2014-10-21 03:13:06

+0

僅僅因爲您可以將64位DLL加載到其他64位進程中,並不意味着調用進程是64位。您必須確保您正在編譯64位平臺的代碼。最簡單的方法是檢查sizeof(void *)'來查看它是4(32位)還是8(64位),或者在調用過程中調用'IsWow64Process()'。 – 2014-10-21 04:03:46

+0

sizeof(void *)返回8,意味着64位調用過程。我也做了你告訴我的更改,除了在if(hProc32Module == INVALID_HANDLE_VALUE)語句中添加了DWORD err = GetLastError()。在檢查hProc32Module的確是INVALID_HANDLE_VALUE後,我得到錯誤0x12b,它是ERROR_PARTIAL_COPY。 – Informat 2014-10-21 15:15:43