在Windows下,主要有两种方式来对系统API调用的拦截,一种是修改PE文件的IAT导入表,使API地址重定向;另一种方式就是把在API函数开始地址的机器码改成jmp的指令的机器码,来实现函数的跳转。
 
一、原理
 
PE结构的模块(exe/dll/...),有一个IAT表,保存着该模块使用到的API函数的地址,在默认的隐式API调用时,会先跳转到该IAT表中查找API的具体的函数地址,在跳转到具体的地址执行该API。所以,基于这个原理,我们可以使用修改IAT方式和机器码覆盖的方式来实现拦截。
 
二、两种方式的比较
修改IAT表方式:实现比较简单,直观,且对跨平台支持较好;但是需要对PE的结构及Windows Loader的工作过程比较了解,同时对于显示调用API的方式(LoadLibrary+GetProcess)则跳过了IAT表的定位而直接调用了API,便无法拦截到。
机器码覆盖方式:因为是直接修改函数首指令,只要调用这个函数,没有钩不到的问题,无论调用方是怎么调用的,但是因为不同的平台,有不同的机器码,所以跨平台支持不好,且实现起来复杂(需要使用汇编,可参考微软的Detours)。
 
三、IAT修改方式的Demo
    见附件。