2012-04-07 93 views
5

我想調用一個我已經注入的DLL的遠程進程中的函數。注入DLL中的調用函數

我已經成功地注入我的DLL有:

CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"), pLibRemote, 0, NULL); 

的DllMain的執行和DLL是在待機模式下運行。我想要做的是以某種方式調用遠程加載的DLL來完成一些工作。

我曾嘗試導出函數是這樣的:

extern "C" __declspec(dllexport) void MyFunc(void) 

,然後執行該函數是這樣的:

CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("mydll"), "MyFunc"), NULL, 0, NULL); 

,但它會導致崩潰。

我該如何解決這個問題?

+0

GetModuleHandle返回什麼? GetProcAddress返回什麼? – 2012-04-07 19:56:35

+0

兩者都返回0. GetModuleHandle嘗試獲取主機進程中尚未加載模塊的句柄。 – 2012-04-07 20:12:58

回答

13

調用GetModuleHandle,因爲您已經將DLL映射到您的進程(如果有的話)的基礎。所以你需要做的是首先確保在DLL中導出函數。您可以按照您的操作完成,或者創建文件,如here所示。其後:

理論上

  1. 注入DLL到目標進程,並把它在
  2. 加載的基址注入DLL到當前進程。使用GetProcAddress來查找導出的函數和DLL的基址之間的偏移量。
  3. 將此偏移量添加到從步驟1獲得的基地址。CreateRemoteThread在此位置。

在實踐

如果做你的DLL注入,可以讓你獲得你的DLL加載到目標的基礎。

HMODULE hInjected; 

hThread = CreateRemoteThread(hProcess, NULL, 0, 
     (LPTHREAD_START_ROUTINE)(GetProcAddress(hMod, 
     "LoadLibraryW")), lpAddress, 0, NULL); 

// Locate address our payload was loaded 
if(hThread != 0) { 
    WaitForSingleObject(hThread, INFINITE); 
    GetExitCodeThread(hThread, (LPDWORD)&hInjected); 
    CloseHandle(hThread); 
} 

hInjected將成爲注入DLL的基礎。然後,我有另一個功能:

void* GetPayloadExportAddr(LPCWSTR lpPath, HMODULE hPayloadBase, LPCSTR lpFunctionName) { 
    // Load payload in our own virtual address space 
    HMODULE hLoaded = LoadLibrary(lpPath); 

    if(hLoaded == NULL) { 
    return NULL; 
    } else { 
    void* lpFunc = GetProcAddress(hLoaded, lpFunctionName); 
    DWORD dwOffset = (char*)lpFunc - (char*)hLoaded; 

    FreeLibrary(hLoaded); 
    return (DWORD)hPayloadBase + dwOffset; 
    } 
} 

這是做什麼是首先加載有效載荷到我們自己的虛擬地址空間。之後, 我們可以使用GetProcAddress來獲取導出函數的地址。從這裏,我們可以從DLL的基礎獲得函數的偏移量。將此偏移量添加到我們之前得到的hInjected將告訴我們應該在哪裏調用CreateRemoteThread。所以,你可以撥打電話,像這樣:

BOOL InitPayload(HANDLE hProcess, LPCWSTR lpPath, HMODULE hPayloadBase, HWND hwndDlg) { 
    void* lpInit = GetPayloadExportAddr(lpPath, hPayloadBase, "Init"); 
    if(lpInit == NULL) { 
    return FALSE; 
    } else { 
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, 
     lpInit, hwndDlg, 0, NULL); 

    if(hThread == NULL) { 
     return FALSE; 
    } else { 
     CloseHandle(hThread); 
    } 
    } 

    return TRUE; 
} 

這是拆出來的old project I have的所有代碼。歡迎您採取代碼並做任何你想做的事情,但我知道如果我現在要重寫代碼,我會做很多不同的事情。

2

如果您將32位DLL注入到32位進程中,Mike的答案將有效。

如果你想在64位進程中注入一個64位DLL,你不能從GetExitCodeThread得到DLL的基地址,因爲它只會給你64位地址的低32位。

要獲得在這種情況下,正確的地址,您必須編寫的代碼到調用LoadLibrary(存儲在處理內存中的特定位置的結果)的過程中,執行(使用CreateRemoteThread)的代碼塊,並然後使用ReadProcessMemory從該位置讀回地址。

你可以找到更多的細節該位置(包括PowerShell和ASM代碼)在這裏: http://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and-assembly/

然後可以計算偏移導出的函數一樣邁克介紹,但要小心存放的區別在一個64位的值,而不是一個DWORD(這是32位)。