这是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(),pszFuncName); OutputDebugString(sz); return; } // Hook this function in all currently loaded modules ReplaceIATEntryInAllMods(m_pszCalleeModName,m_pfnOrig,m_pfnHook); }
这是钩子函数:
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,DWORD dwFlags) { HMODULE hmod = ::LoadLibraryExW(pszModulePath,dwFlags); return(hmod); }
替换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,PAGE_WRITECOPY,&dwOldProtect)) { WriteProcessMemory(GetCurrentProcess(),NULL); VirtualProtect(ppfn,dwOldProtect,&dwOldProtect); } } return; // We did it,get out } } } // Each import section is parsed until the right entry is found and patched } }
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,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.
他也在书上写了这个,但我又不知道该怎么做
A possible solution is to use the hooked LoadLibrary* functions to
detect when a module is exporting an unpatched hooked function and
then execute two actions:Hook again the import table of the module already loaded because it is
now possible to call GetProcAddress and get a pointer to the original
implementation of the function to hook. Notice that the name of the
function needs to be stored as a class member and set in the
constructor.Directly update this hooked function in the Export Address Table of
the exporting module as shown by the implementation of the
ReplaceEATEntryInOneMod function. That way,all new modules calling
the hooked function will call our handler
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); }
解决方法
你想要的是EAT挂钩而不是IAT.此外,挂钩:: LoadLibrary API本身,以便您知道何时加载DLL,并在加载后从DLL挂钩所请求的api.
互联网上有一些关于如何做到这一点的例子.这是我刚才发现的一个:
http://board.cheat-project.com/showthread.php?t=10633