2012-07-21 2 views
6

Ich möchte Funktionen, die von einer geladenen DLL zur Laufzeit aufgerufen werden, ich habe die Klasse CAPIHook aus dem Buch "Windows Via C/C++" (die DLL Injecting done durch Installieren von systemweitem Hook und dem Hooking durch Ändern von IAT), aber dieser Code funktioniert nur, wenn der DLL-Name/die DLLs in der IAT in der ausführbaren Datei vorhanden sind. (Dh für die implizite DLL Linking)Wie Ändern der Importadressentabelle für Laufzeit geladen DLL

ist dieser DLL-Code:

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); 
} 

dies die Funktionen Haken ist:

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); 
} 

das Verfahren zum IAT ersetzt:

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 
    } 
} 

die Autor hinzugefügt Kommentare, um diese Funktionalität hinzuzufügen, aber ich bin mir nicht sicher, wie es geht

Hinweis: Die Funktion kann nur angeschlossen werden, wenn das Exportmodul bereits geladen ist. Eine Lösung könnte sein, die Funktion Name als Mitglied zu speichern; dann, in der Hakenloadlibrary * Handler, die Liste der CAPIHook Instanzen analysieren, überprüfen, ob pszCalleeModName der Name des geladenen Moduls ist seine Exporttabelle und Wiederhaken der Importtabellen aller geladenen Module zu anschließen.

er auch diese auf das Buch schreiben, aber auch hier nicht, weiß ich, was

Eine mögliche Lösung besteht darin, die süchtig Loadlibrary * Funktionen erkennen, wenn ein Modul ein exportiert zu verwenden ungepatchte Haken Funktion und dann zwei Aktionen ausführen:

Haken wieder die Importtabelle des Moduls bereits geladen, weil es nun möglich ist, GetProcAddress aufrufen und einen Zeiger auf die ursprüngliche Umsetzung des bekommen Funktion zum Haken. Beachten Sie, dass der Name der -Funktion als ein Klassenmitglied gespeichert und in dem -Konstruktor festgelegt werden muss.

Aktualisieren Sie diese verknüpfte Funktion in der Exportadresstabelle von direkt in das Exportmodul, wie in der Implementierung der Funktion ReplaceEATEntryInOneMod gezeigt. Auf diese Weise werden alle neuen Module die Haken Funktion aufrufen wird unser Handler

nenne ich versuchen, das IAT nach dem Laden der DLL zu ändern, aber meine Hakenfunktion nicht

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); 
} 

so genannt, wie man Ändern Sie diesen Code, um den dynamischen Ladefall zu behandeln?

+0

Sie versuchen, DLL-Injektion zu blockieren? Weil ein einfaches 'JNZ' das Ganze umgehen kann –

+0

Ändern Sie' ReplaceIATEntryInOneMod', um einen Fehlercode zurückzugeben, damit Sie wissen, ob der Eintrag erfolgreich ersetzt wurde oder nicht, oder ob er den Eintrag sogar gefunden hat. – Jay

Antwort

8

Ich habe das schon mal gemacht. Was Sie wollen, ist EAT Hooking statt IAT. Hängen Sie auch die :: LoadLibrary-API selbst an, damit Sie wissen, wann die DLL geladen ist, und hängen Sie die angeforderte API nach dem Laden an die DLL an.

Es gibt einige Beispiele im Internet, wie man das macht.Hier ist eine, die ich gerade gefunden habe: http://board.cheat-project.com/showthread.php?t=10633

+0

Könnten Sie bitte erklären, was Sie damit meinen, EAT anstelle von IAT anzuhängen? – mox

+4

Das bedeutet, dass Sie in die Export-Adresstabelle der importierten DLL schreiben, anstatt in die Importadressentabelle Ihres eigenen Moduls zu schreiben. Wenn Sie eine DLL dynamisch laden und etwas von ihr aufrufen, hat die Funktion, die Sie anrufen, keinen Eintrag in der IAT Ihres Moduls. Es wird jedoch in seiner eigenen DLL EAT vorhanden sein. – EddieBytes

+2

Leider funktioniert der von Ihnen angegebene Link nicht mehr - vielleicht können Sie ihn durch einen anderen ersetzen, der das tut (oder einen Teil des Codes in Ihre Antwort einbaut)? –

Verwandte Themen