如何检测API钩子?

5

我一直在尝试检测API Hook、内联Hook和EAT Hook。

目前为止,我还没有找到如何检测EAT Hook的方法。

关于Ring 3内联Hook,我的进展如下:

FARPROC Address = GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitProcess");
if (*(BYTE*)Address == 0xE9 || *(BYTE*)Address == 0x90 || *(BYTE*)Address == 0xC3)
{
 printf("Api hooked\n");
}

问题在于有几个操作码可以用来钩取/改变函数的序言,检查 JMP / NOP / RET 很容易,我见过很多 HOOK 类型,如 PUSH RET、MOV、RETN 等等。
我想知道是否有人知道如何检测这些钩子(detours)或 API 中的修改。 还有一些方法可以检测 EAT 钩子。
谢谢。

7
如果有人已经钩取了你的程序,那么他们也可以钩取你的钩子检测器。 - Raymond Chen
1
检查导出地址表是否被hook的明显方法是查看表中的任何地址是否指向EAT所属的DLL之外的某个地方。虽然我相信一些标准的DLL通过EAT将某些函数转发到其他DLL,因此您需要处理该情况。 - Ross Ridge
3个回答

1

GetProcAddress 也可以被挂钩。由于您无法知道将被修补的确切 API,因此必须检查所有已导入的函数,这相当繁琐。由于入侵者具有足够的特权来注入到您的进程地址空间并挂钩 API 方法,因此实际上几乎没有办法防止他完全消除任何保护机制。通常现代软件保护系统包括内核模式驱动程序,该驱动程序扫描程序内存并防止 DLL 注入和远程内存修改。还很常见使用代码加密/混淆系统(例如 Themida),甚至是具有完全外部处理器指令集的内部虚拟执行机,这使得即时修补代码变得非常困难。


1
当然,你是对的,但我见过一些相当有效的对策 - 从磁盘手动加载Kernel32.dll,确保文件已签名,以及比较关键函数(如GetProcAddress)的指令前缀等。如果GPA被挂钩,他们必须在你比较数据之前动态取消挂钩以避免被检测到。之后,您可以比较磁盘与内存中的函数指令校验和等。但是,是的,这是一场猫鼠游戏,没有绝对可靠的方法。 - Jake H

0

我认为你应该将磁盘中的kernel32.dll与内存中的当前dll进行比较,同时忽略IAT并修复重定位,否则会得到不同的哈希值。

如果你想要一个更简单的解决方案,只需将kernel32.dll重命名,并从重命名的DLL中进行API调用。


0
你需要钩取当前进程的 IAT 地址,然后立即保存字节。
这样一来,你就有了原始字节,因此稍后可以尝试再次复制它们并使用 memcmp() 函数将旧(原始)字节与新字节进行比较,如果它们不同,那么你的 IAT 地址已经被其他进程钩取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接