2012-07-21 16 views
6

Voglio agganciare le funzioni richiamate da una DLL caricata in fase di esecuzione, ho utilizzato la classe CAPIHook dal libro "Windows tramite C/C++" (l'iniezione DLL eseguita Installa System Wide hook e Hooking by Modify IAT) ma questo codice funziona solo se i nomi/i simboli DLL esistono nello IAT nel file eseguibile. (Cioè per implicito DLL Linking)Come modificare la tabella degli indirizzi di importazione per la DLL caricata in fase di esecuzione

questo codice DLL:

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

questo funzioni hook:

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

il metodo di sostituzione IAT:

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

la l'autore ha aggiunto commenti per aggiungere questa funzionalità, ma non sono sicuro di come farlo

Nota: la funzione può essere agganciata solo se il modulo di esportazione è già caricato. Una soluzione potrebbe essere quella di memorizzare il nome della funzione come membro; quindi, nei gestori hook LoadLibrary *, analizzare l'elenco di istanze CAPIHook, controllare , verificare se pszCalleeModName è il nome del modulo caricato per agganciare la tabella di esportazione e riagganciare le tabelle di importazione di tutti i moduli caricati.

ha anche scrivere questo sul libro, ma ancora una volta non so cosa fare

Una possibile soluzione è quella di utilizzare il LoadLibrary agganciato * funzioni di rilevare quando un modulo sta esportando un patch funzione agganciato e quindi eseguire due azioni:

Hook nuovamente la tabella importazione del modulo già caricato perché è ora possibile chiamare GetProcAddress e ottenere un puntatore alla implementazione originale del funzione da agganciare. Si noti che il nome della funzione deve essere memorizzato come membro della classe e impostato nel costruttore .

aggiornamento direttamente questa funzione agganciato nella Tabella esportazione Indirizzo modulo esportazione come mostrato dalla implementazione della funzione ReplaceEATEntryInOneMod. In questo modo, tutti i nuovi moduli di chiamata la funzione agganciato chiameranno nostro gestore di

provo a modificare l'IAT dopo il caricamento della DLL, ma la mia funzione di aggancio non viene chiamata

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

così, come modificare questo codice per gestire il caso di caricamento dinamico?

+0

Stai provando a bloccare l'iniezione di dll? Perché un semplice 'JNZ' può bypassare l'intera cosa –

+0

Modificare il' ReplaceIATEntryInOneMod' per restituire un codice di errore in modo da sapere se la voce è stata sostituita o meno, o se è stata trovata la voce. – Jay

risposta

8

L'ho già fatto. Quello che vuoi è l'aggancio EAT al posto di IAT. Inoltre, agganciare l'API :: LoadLibrary stessa in modo da sapere quando viene caricata la DLL e collegare l'API richiesta dalla DLL dopo che è stata caricata.

Ci sono alcuni esempi su Internet su come farlo.Eccone uno che ho trovato proprio ora: http://board.cheat-project.com/showthread.php?t=10633

+0

Potresti spiegare cosa intendi con l'aggancio di EAT al posto di IAT? – mox

+4

Significa scrivere nella tabella degli indirizzi di esportazione della DLL importata anziché scrivere nella tabella degli indirizzi di importazione del proprio modulo. Se stai caricando una dll in modo dinamico e chiamando qualcosa da essa, la funzione che stai chiamando non avrà alcuna voce nello IAT del tuo modulo. Sarà comunque presente nel proprio EAT della DLL. – EddieBytes

+2

Sfortunatamente il collegamento che hai fornito non funziona più - forse potresti sostituirlo con un altro che fa (o incorpora parte del codice nella tua risposta)? –

Problemi correlati