2012-07-21 15 views
6

मैं रन टाइम पर लोड किए गए डीएलएल से बुलाए गए कार्यों को हुक करना चाहता हूं, मैंने "विंडोज वाया सी/सी ++" (डीएलएल इंजेक्शनिंग "पुस्तक से क्लास कैपहूक का उपयोग किया सिस्टम वाइड हुक और संशोधित आईएटी द्वारा हुकिंग द्वारा स्थापित करें) लेकिन यह कोड केवल तभी काम करता है जब निष्पादन योग्य फ़ाइल में आईएटी में डीएलएल नाम/प्रतीक मौजूद हों।रन टाइम के लिए आयात पता तालिका को संशोधित करने के लिए कैसे करें डीएलएल

HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath) { 

    HMODULE hmod = ::LoadLibraryA(pszModulePath); 
    FixupNewlyLoadedModule(hmod, 0); 
    return(hmod); 
} 

HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) { 

    HMODULE hmod = ::LoadLibraryW(pszModulePath); 
    FixupNewlyLoadedModule(hmod, 0); 
    return(hmod); 
} 

HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath, 
    HANDLE hFile, DWORD dwFlags) { 

    HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags); 
    FixupNewlyLoadedModule(hmod, dwFlags); 
    return(hmod); 
} 

HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath, 
    HANDLE hFile, DWORD dwFlags) { 

    HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags); 
    FixupNewlyLoadedModule(hmod, dwFlags); 
    return(hmod); 
} 

आई ए टी की जगह के लिए विधि:

CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook) { 

    // Note: the function can be hooked only if the exporting module 
    //  is already loaded. A solution could be to store the function 
    //  name as a member; then, in the hooked LoadLibrary* handlers, parse 
    //  the list of CAPIHook instances, check if pszCalleeModName 
    //  is the name of the loaded module to hook its export table and 
    //  re-hook the import tables of all loaded modules. 

    m_pNext = sm_pHead; // The next node was at the head 
    sm_pHead = this;  // This node is now at the head 

    // Save information about this hooked function 
    m_pszCalleeModName = pszCalleeModName; 
    m_pszFuncName  = pszFuncName; 
    m_pfnHook   = pfnHook; 
    m_pfnOrig   = GetProcAddressRaw(GetModuleHandleA(pszCalleeModName), m_pszFuncName); 

    // If function does not exit,... bye bye 
    // This happens when the module is not already loaded 
    if (m_pfnOrig == NULL) 
    { 
     wchar_t szPathname[MAX_PATH]; 
     GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); 
     wchar_t sz[1024]; 
     StringCchPrintfW(sz, _countof(sz), 
     TEXT("[%4u - %s] impossible to find %S\r\n"), 
     GetCurrentProcessId(), szPathname, pszFuncName); 
     OutputDebugString(sz); 
     return; 
    } 

    // Hook this function in all currently loaded modules 
    ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook); 
} 

इस हुक कार्यों है: (अंतर्निहित DLL लिंकिंग के लिए यानी)

इस DLL कोड है

void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, 
    PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) { 

    // Get the address of the module's import section 
    ULONG ulSize; 

    // An exception was triggered by Explorer (when browsing the content of 
    // a folder) into imagehlp.dll. It looks like one module was unloaded... 
    // Maybe some threading problem: the list of modules from Toolhelp might 
    // not be accurate if FreeLibrary is called during the enumeration. 
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL; 
    __try { 
     pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
     hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize); 
    } 
    __except (InvalidReadExceptionFilter(GetExceptionInformation())) { 
     // Nothing to do in here, thread continues to run normally 
     // with NULL for pImportDesc 
    } 

    if (pImportDesc == NULL) 
     return; // This module has no import section or is no longer loaded 


    // Find the import descriptor containing references to callee's functions 
    for (; pImportDesc->Name; pImportDesc++) { 
     PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name); 
     if (lstrcmpiA(pszModName, pszCalleeModName) == 0) { 

     // Get caller's import address table (IAT) for the callee's functions 
     PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
      ((PBYTE) hmodCaller + pImportDesc->FirstThunk); 

     // Replace current function address with new function address 
     for (; pThunk->u1.Function; pThunk++) { 

      // Get the address of the function address 
      PROC* ppfn = (PROC*) &pThunk->u1.Function; 

      // Is this the function we're looking for? 
      BOOL bFound = (*ppfn == pfnCurrent); 
      if (bFound) { 
       if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
        sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) { 
        DWORD dwOldProtect; 
        if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, 
        &dwOldProtect)) { 

        WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
         sizeof(pfnNew), NULL); 
        VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, 
         &dwOldProtect); 
        } 
       } 
       return; // We did it, get out 
      } 
     } 
     } // Each import section is parsed until the right entry is found and patched 
    } 
} 

लेखक ने इस कार्यक्षमता को जोड़ने के लिए टिप्पणियां जोड़ दीं, लेकिन मुझे यकीन नहीं है कि यह कैसे करें

नोट: फ़ंक्शन को केवल तभी लगाया जा सकता है जब निर्यात मॉड्यूल पहले ही लोड हो चुका है। एक समाधान के रूप में कार्य नाम स्टोर करने के लिए एक समाधान हो सकता है; फिर, हुक किए गए लोड लाइब्रेरी * हैंडलर में, पार्स सीएपीआईएचक उदाहरणों की सूची, जांचें कि क्या pszCalleeModName लोड किए गए मॉड्यूल का नाम है जो इसकी निर्यात तालिका को हुक करने के लिए है और सभी लोड मॉड्यूल की आयात तालिका को फिर से हुक करता है।

वह भी किताब पर यह लिख, लेकिन फिर मैं क्या

सम्भावित समाधान के शौकीन LoadLibrary कार्यों का उपयोग करने के लिए * का पता लगाने के लिए जब एक मॉड्यूल एक निर्यात कर रहा है क्या करने के लिए पता नहीं है पैच न किया गया शौकीन समारोह और तो दो कार्यों को निष्पादित करें:

हुक फिर मॉड्यूल पहले से ही भरा हुआ है के आयात तालिका क्योंकि यह अब संभव है GetProcAddress कॉल और के मूल कार्यान्वयन के लिए एक सूचक प्राप्त करने के लिए हुक करने के लिए समारोह। ध्यान दें कि फ़ंक्शन का नाम कक्षा सदस्य के रूप में संग्रहीत करने और कन्स्ट्रक्टर में सेट करने की आवश्यकता है।

निर्यात निर्यात तालिका में ReplaceEATEntryInOneMod फ़ंक्शन के कार्यान्वयन द्वारा दिखाए गए निर्यात पता तालिका में सीधे इस हुक किए गए फ़ंक्शन को अपडेट करें। इस तरह से, सभी नए बुला शौकीन समारोह मॉड्यूल हमारे हैंडलर

मैं DLL लोड करने के बाद आई ए टी को संशोधित करने की कोशिश, लेकिन मेरे hooking समारोह नहीं बुलाया जाता है

HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) { 

    HMODULE hmod = ::LoadLibraryW(pszModulePath); 

    if (StrCmpIW(pszModulePath, myDLLUnicodeName.c_str()) == 0) { 
     PROC proc = GetProcAddressRaw(GetModuleHandleA(myDLLName.c_str()), myFunctionName.c_str()); 

     if (proc != NULL) { 
      for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) { 
       if (StrCmpIA(p->m_pszCalleeModName, myDLLName.c_str()) == 0) { 
        MessageBox(NULL, L"This is the New Dynamic DLL", L"Test!", 0); 
        ReplaceIATEntryInAllMods(p->m_pszCalleeModName, proc , p->m_pfnHook); 
       } 
      } 
     } 
    } 

    FixupNewlyLoadedModule(hmod, 0); 
    return(hmod); 
} 

हां, तो कैसे करने के लिए कॉल करेंगे डायनामिक लोडिंग केस को संभालने के लिए इस कोड को संशोधित करें?

+0

आप डीएल इंजेक्शन को अवरुद्ध करने की कोशिश कर रहे हैं? चूंकि एक साधारण 'जेएनजेड' पूरी चीज को बाईपास कर सकता है –

+0

त्रुटि कोड वापस करने के लिए 'ReplaceIATEntryInOneMod' बदलें ताकि आप जान सकें कि प्रविष्टि सफलतापूर्वक बदल दी गई है या नहीं, या अगर यह प्रविष्टि भी मिलती है। – Jay

उत्तर

8

मैंने पहले यह किया है। आप जो चाहते हैं वह आईएटी के बजाय ईएटी हुकिंग है। साथ ही, :: लोड लाइब्रेरी एपीआई को स्वयं हुक करें ताकि आप जानते हों कि डीएलएल लोड होने पर, और लोड होने के बाद अनुरोधित एपीआई को डीएलएल से हुक करें।

इंटरनेट पर कुछ उदाहरण हैं कि यह कैसे करें।यहां एक ऐसा है जो मुझे अभी मिला है: http://board.cheat-project.com/showthread.php?t=10633

+0

क्या आईएटी के बजाय ईएटी को जोड़ने के बारे में आप क्या समझ सकते हैं? – mox

+4

इसका मतलब है कि आपके मॉड्यूल की आयात पता तालिका में लिखने के बजाय आयातित डीएलएल की निर्यात पता तालिका में लिखना। यदि आप गतिशील रूप से एक डीएल लोड कर रहे हैं और इससे कुछ कॉल कर रहे हैं, तो आपके द्वारा कॉल किए जाने वाले फ़ंक्शन में आपके मॉड्यूल के आईएटी में कोई प्रविष्टि नहीं होगी। हालांकि यह अपने स्वयं के डीएलएल के ईएटी में उपस्थित होगा। – EddieBytes

+2

दुर्भाग्य से आपके द्वारा प्रदान किया गया लिंक अब काम नहीं करता है - हो सकता है कि आप इसे किसी अन्य व्यक्ति के साथ प्रतिस्थापित कर सकें (या आपके उत्तर में कुछ कोड शामिल करें)? –

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