windows hook 之IAT篇

来源:互联网 发布:htc t328w软件下载 编辑:程序博客网 时间:2024/05/21 17:56

 转载请注明出处http://blog.csdn.net/qingheuestc/article/details/6527991,并保证文章完整性,by Einstein In Ict。


      程序员通过使用微软提供的api不仅可以方便的实现绝大多数的编程任务,同时也不必与繁琐的计算机硬件直接打交道。出于某些工程上的需求,有时我们需要在调用某个api的时候做一些额外的工作(比如采集或修改一些进程状态信息,甚至直接将本次调用直接bypass掉,等等)。这时,我们需要找到合适的插入点,将我们的代码加入到以前代码的执行流中去。那么该如何找到合适的插入点呢?这就需要我们了解一些windows下可执行程序的运行机制。其实,进行hook的方式有很多种,本文采用了基于PE文件IAT的一种方式。

      下面,简单介绍一下这种方式的工作原理。

      我们的代码,说到底,不过是由一条条的汇编指令组成的。根据功能上、逻辑上的紧密程度,我们用“关系密切”的汇编指令集组成了一个个的小模块function。出于某些需要,我们用一个个的function组成了我们的dll(在windows里面),这些function就是我们需要经常调用的windows api(当然我们也可以定义自己的dll)。那么可执行程序是如何定位这些function的呢?这就要求助于PE文件格式了。

      在PE文件的IAT里面,存储着我们需要的function的地址。这些地址是在dll加载完成后由装入程序动态填入的。当我们需要调用某个function的时候,一般通过下面两种方式:

           1, call dword ptr[xxxx]

           下面这张图显示了我在VC++2010里面调用Sleep()时的情形。

           2,   jmp dword ptr[xxxx]

          (其中xxxx就是存储function地址的地方,而xxxx就位于IAT里面,通过call或者jmp,执行流就到了相应的api里)

 

      由此可见,如果我们要想在程序原本想调用某个api的时候,用我们的代码的address去覆盖xxxx(即原来的api函数的地址),那么就实现了对该api的hook。限于篇幅的原因,在此对于如何去确定某个函数在IAT里面的具体位置不作详细介绍(待会儿代码里面会有所体现),感兴趣的可以参看一下PE文件格式里面导入表。

实现代码如下:(环境:VC++2010 学习版)

 

 

//包含的头文件和全局变量定义如下

 

 

主程序的执行流程如下:

此处用Sleep函数开刀,用一个什么都不做(只打印一条消息的函数首址)的函数地址去替换Sleep的地址,用hookTest()对Sleep函数进行测试,对比hook前后的执行结果。

代码如下:

 

程序的运行结果如下:

 

可以看到,在hook Sleep()函数之前调用Sleep(3000),前后的时间间隔是3s,而被hook后,再次调用Sleep(),实际运行的是我们的hook使用的函数。此时再调用Sleep(3000),前后的时间间隔为0s。在unhook完成后,再次调用Sleep(3000),此时的时间间隔又变为3s,即调用的是真正的Sleep函数。

 

用来测试的hookTest()函数如下:

 

 

 

下面是关键部分,用来实现hook和unhook的函数:

(由于myhook函数稍长,此处截成两张图)

 

说明:hook的关键是找到文件镜像中存放函数地址的地方,也即此处的(LPVOID)(&pThunk->u1.Function),然后就是用新函数的地址去覆盖该函数的地址。此处注意如果镜像地址不能直接写的话,要先修改内存属性后在进行操作。

 

最后是unhook的代码:

 

 

unhook此处偷了个懒,直接用了前面找到的函数地址的存放地址,直接修改就行了。

 

 

总结:在整个过程中,找到函数地址的存放位置是个难点。不是说不易理解,而是比较麻烦,需要有点耐心才行。

 

题外话:本文提到的IAT只是hook中的一种方法,还有其他比如通过覆盖代码等等。在《windows核心编程5》P601页,作者在介绍通过覆盖代码来拦截API的不足时提到“这种方法在抢占式、多线程环境下根本不能工作。一个线程覆盖另一个函数起始位置的代码是需要时间的,在这个过程中,另一个线程可能试图调用同一个函数,其结果是灾难性的”。个人认为作者的理由有些牵强,至少结果不一定是灾难性的,这主要是看我们是怎么进行的覆盖以及其他是线程是怎么处理这种情况的。

 

由于水平和时间有限,错误之处恳请指正,谢谢!

原创粉丝点击