2012-04-07 31 views
5

में कॉलिंग फ़ंक्शन मैं एक इंजेक्शन डीएलएल की रिमोट प्रक्रिया में एक फ़ंक्शन को कॉल करना चाहता हूं।इंजेक्शन डीएलएल

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 वापस क्या करता है? –

+0

दोनों वापसी 0। GetModuleHandle मेजबान प्रक्रिया में एक मॉड्यूल के हैंडल प्राप्त करने का प्रयास करता है जहां मैंने इसे लोड नहीं किया है। –

उत्तर

13

कॉलिंग GetModuleHandle जैसा कि आपको डीएलएल का आधार मिलेगा क्योंकि यह आपकी प्रक्रिया में मैप किया गया है (यदि बिल्कुल)। तो आपको सबसे पहले डीएलएल में फ़ंक्शन को निर्यात करना सुनिश्चित करना है। here दिखाए गए अनुसार आप ऐसा कर सकते हैं या .def फ़ाइल बना सकते हैं। इसके बाद:

थ्योरी

  1. लक्ष्य प्रक्रिया के लिए DLL सम्मिलित करें और मिल आधार पता यह
  2. पर लोड किया गया था वर्तमान प्रक्रिया के लिए DLL सम्मिलित करें। निर्यात किए गए फ़ंक्शन और डीएलएल के आधार के बीच ऑफसेट खोजने के लिए GetProcAddress का उपयोग करें।
  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 का उपयोग कर सकते हैं। इससे, हम डीएलएल के आधार से फ़ंक्शन का ऑफसेट प्राप्त कर सकते हैं। इस ऑफसेट को 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 बिट प्रक्रिया में 32 बिट डीएलएल इंजेक्शन दे रहे हैं।

यदि आप 64 बिट प्रक्रिया में 64 बिट डीएलएल इंजेक्ट करना चाहते हैं, तो आप डीएलएल का मूल पता GetExitCodeThread से प्राप्त नहीं कर सकते हैं क्योंकि यह आपको केवल 64 बिट पते के निचले 32 बिट्स देगा।

इस मामले में सही पता पाने के लिए आपको प्रक्रिया है कि LoadLibrary (प्रक्रिया स्मृति में एक विशिष्ट स्थान पर परिणाम भंडारण) कॉल में कोड का एक खंड लिखना चाहिए, (CreateRemoteThread का प्रयोग करके) कोड के इस खंड पर अमल, और फिर ReadProcessMemory का उपयोग कर उस स्थान से पता वापस पढ़ें।

आप (PowerShell और एएसएम कोड सहित) यहाँ यहाँ इस के लिए और अधिक जानकारी प्राप्त कर सकते हैं: http://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and-assembly/

फिर आप गणना कर सकता है अपने निर्यात समारोह उसी तरह माइक का वर्णन करने के लिए ऑफसेट, लेकिन अंतर स्टोर करने के लिए बाहर घड़ी 64 बिट मान में, और डीडब्ल्यूओआर में नहीं (जो 32 बिट है)।

संबंधित मुद्दे