如何挂钩DLL的入口点?

逆向工程 视窗 C dll 聚乙烯 函数挂钩
2021-07-06 21:51:23

我已经通过覆盖导出函数的相应 IAT 条目编写了一个支持静态导入挂钩的 C API。它适用于较旧的简单应用程序,但对于更现代的应用程序,效果较差。这主要是由于当今大量应用程序动态导入函数。

我对这个问题的解决方案是在初始挂起状态下创建进程,然后钩住LoadLibrary(Ex)(A/W) 函数族,并GetProcAddress()用我自己的函数替换检索到的目标函数地址。该解决方案部分受到限制,因为它基于应用程序仅导入可执行模块中的动态函数和库,而不适用于稍后创建的进程(尽管这可以通过挂钩解决CreateProcess())或更重要的是,它没有t 处理应用程序中的 DLL,这些 DLL 也调用了我想要挂钩的目标函数这显然是因为 DLL 在它们自己的 PE 中有一个独立于可执行模块的导入部分。

这让我想到了我的问题,如何挂钩 DLL 的入口点我想实现该方法,因为我需要将 DLL 绑定到它静态导入的库,所以我可以在 DLL 有机会在 DLLMain 中加载/导入它们之前挂钩 LoadLibrary/GetProcAddress 函数。我假设有一种方法可以通过更改 DLL 的入口点或通过挂钩处理调用 kernel32.dll 中的 DLL 入口点的低级函数来实现此目的。

如果我要求的方法有更好的选择,那么如果它达到我想要的效果,我也很乐意接受该解决方案。

我的处理器是兼容 x86-x64 的 AMD Athlon II X2 250,我的操作系统是 Windows 7。

2个回答

要回答原来的问题,你可以做的是挂钩LdrpCallInitRoutinentdll.dllDLL 加载/卸载代码使用此函数来实际调用 DLL 入口点 ( DllMain) 以及 TLS 回调。第一个参数是要调用的地址:

BOOLEAN NTAPI LdrpCallInitRoutine(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);

出于您提到的相同原因,您不应该使用 IAT 覆盖挂钩方法。使用带有JMP指向目标钩子指令的内联钩子方法您需要将覆盖的字节保存在某处,因为您需要将其用作蹦床。看到为内联钩的一个例子。

使用内联挂钩可确保加载在同一地址空间中的所有(现有或未来)模块将使用挂钩函数,无论它们如何解析 API 的地址。

jbremer.org有关于 API 钩子的很好的信息资源。