如何检测API挂钩?

问题描述:

我一直在尝试检测API钩子,内联和EAT钩子。如何检测API挂钩?

现在我没有找到如何检测EAT钩东西。

内联环挂钩,是我到目前为止有:

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等...

我不知道是否有人知道如何检测API中的这些挂钩(绕行)或修改。 还有一些方法来检测EAT钩子。

谢谢。

+7

如果有人钩住了你的程序,那么他们可以钩住你的钩子检测器。 –

+1

那么,查看导出地址表是否已被挂钩的一个显而易见的方法是查看表中的任何地址是否指向EAT所属的DLL之外的某个地方。虽然,我相信一些标准DLL通过EAT将一些函数转发给其他DLL,所以你必须处理这种情况。 –

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

+1

你说得对,当然,但我已经看到了一些非常有效的措施 - 加载KERNEL32.DLL从磁盘手动,确保文件进行签名,以及比较指令前奏曲等,像GetProcAddress的关键功能。如果GPA被挂钩,他们必须在比较数据之前动态解除绑定,以避免检测。之后,您可以比较磁盘和内存中的功能指令校验和等等。但是,它是一款猫捉老鼠游戏,没有任何傻瓜式的方法。 –

我相信你应该比从磁盘上的Kernel32.dll在存储当前的DLL,你也应该忽略IAT和修复搬迁,否则你会得到不同的哈希值。

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

您需要挂钩IAT地址为您当前的进程,然后立即保存字节。

之后,你有原始字节,这样你就可以在以后尝试复制他们再次使用memcmp()比较旧的(原来的)用新的字节,如果他们是不同的,那么您IAT地址有被另一个进程所吸引。