跨越整个进程生效的API挂钩 – 包括EXE和DLL

我有一个应用程序由单个EXE和多个DLL组成。 在通过C / C ++读取Windows之后,我尝试在其中一个DLL上执行Sleep函数的钩子,期望钩子可以在EXE和所有的DLL上工作。 请注意, CAPIHook代码是通过C / C ++的示例代码从Windows获取的

在DLL项目中

 void WINAPI MySleep( DWORD dwMilliseconds ); CAPIHook g_Sleep("Kernel32.dll", "Sleep", (PROC)MySleep); typedef void (WINAPI *Sleep_Type)( DWORD dwMilliseconds ); // Hook function. void WINAPI MySleep( DWORD dwMilliseconds ) { printf ("-------> In MySleep\n"); ((Sleep_Type)(PROC)g_Sleep)(dwMilliseconds); } // This is an example of an exported function. DLL_API int dll_function_which_is_going_to_call_sleep(void) { printf ("DLL function being called\n"); printf ("Call Sleep in DLL function\n"); Sleep(100); return 42; } 

在EXE项目中

 void CexeDlg::OnBnClickedButton1() { // TODO: Add your control notification handler code here printf ("Button being clicked\n"); printf ("Call Sleep in EXE function\n"); Sleep(100); dll_function_which_is_going_to_call_sleep(); printf ("Call Sleep in EXE function\n"); Sleep(100); dll_function_which_is_going_to_call_sleep(); } 

这是我得到的输出

 Button being clicked Call Sleep in EXE function -------> In MySleep DLL function being called Call Sleep in DLL function Call Sleep in EXE function -------> In MySleep DLL function being called Call Sleep in DLL function 

令我感到奇怪的是,我期待CAPIHook将贯穿整个单一过程。 由于EXE和DLL属于同一个进程,两者都应该能够访问MySleep 。 不过,我的观察是,只有从EXE调用才能达到MySleep ,而不是DLL。

我在这里find示例代码CAPIHook-doesnt-have-effect-in-entire-process.zip ,它包含dllexe项目。

我也曾经用CHookAPI代码替代CHookAPI 。 同样的问题仍然存在。 挂钩效应不会在整个过程中传播。

有什么我错过了吗? 请不要build议我使用EasyHook,Detours,…,因为我只是想知道为什么上面的代码将无法正常工作,以及如何修复它。

这是因为原来的CAPIHook并不能替代本地的IAT(在你的情况下,包含CAPIHook二进制文件的DLL项目)。

其原因是保护自己免受无限递归导致的stackoverflow (用户也将在SO:D发布问题)。

为了确保随后加载的模块将导入“正确”的功能,
CAPIHook搜索并在构建时重定向LoadLibraryGetProcAddress

然而,这些函数也被CAPIHook自己使用,因此,将本地IAT改为代理函数(CAPIHook :: LoadLibrary或CAPIHook :: GetProcAddress)将导致无限递归,因为代理在尝试调用底层OS API时无意中自行调用!

解决这个问题的方法之一是修改CAPIHook来检查是否可以替换本地的IAT。

1.)添加到CAPIHook和ctor / dtor的新属性m_bIncludeLocalIAT被相应地修改。

 class CAPIHook { ... CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook, BOOL bIncludeLocalIAT = TRUE); ... BOOL m_bIncludeLocalIAT; ... }; CAPIHook::CAPIHook( PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook, BOOL bIncludeLocalIAT) { ... m_bIncludeLocalIAT = bIncludeLocalIAT; ... ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook, m_bIncludeLocalIAT); } CAPIHook::~CAPIHook() { ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnHook, m_pfnOrig, m_bIncludeLocalIAT); ... } 

2.)将新参数添加到静态函数CAPIHook :: ReplaceIATEntryInAllMods中

 static void WINAPI ReplaceIATEntryInAllMods(PCSTR pszCalleeModName, PROC pfnOrig, PROC pfnHook, BOOL bReplaceLocalIAT){ HMODULE hmodThisMod = ExcludeAPIHookMod ? moduleeFromAddress(ReplaceIATEntryInAllMods) : NULL; // Get the list of modules in this process CToolhelp th(TH32CS_SNAPMODULE, GetCurrentProcessId()); MODULEENTRY32 me = { sizeof(me) }; for (BOOL bOk = th.moduleeFirst(&me); bOk; bOk = th.moduleeNext(&me)) { if (bReplaceLocalIAT || (me.hmodulee != hmodThisMod)) { // Hook this function in this module ReplaceIATEntryInOneMod( pszCalleeModName, pfnCurrent, pfnNew, me.hmodulee); } } } 

3.)更新静态CAPIHook实例

 CAPIHook CAPIHook::sm_LoadLibraryA ("coreel32.dll", "LoadLibraryA", (PROC) CAPIHook::LoadLibraryA, FALSE); CAPIHook CAPIHook::sm_LoadLibraryW ("coreel32.dll", "LoadLibraryW", (PROC) CAPIHook::LoadLibraryW, FALSE); CAPIHook CAPIHook::sm_LoadLibraryExA("coreel32.dll", "LoadLibraryExA", (PROC) CAPIHook::LoadLibraryExA, FALSE); CAPIHook CAPIHook::sm_LoadLibraryExW("coreel32.dll", "LoadLibraryExW", (PROC) CAPIHook::LoadLibraryExW, FALSE); CAPIHook CAPIHook::sm_GetProcAddress("coreel32.dll", "GetProcAddress", (PROC) CAPIHook::GetProcAddress, FALSE);