Hook API,简单说,就是给API函数挂钩,将本应该调用的API函数拦截,使其转而调用我们自己的函数。这里,我主要介绍如何利用IAT挂钩来实现API拦截。
在我们启动目标程序时,操作系统负责为目标程序创建虚拟地址空间,并将这个可执行模块(就是目标程序)加载到地址空间中去,接下来,系统会将目标程序所需要的DLL文件映射到地址空间。我们将需要映射到地址空间的目标程序及所需DLL统称为模块(Module)。
这里的问题是,操作系统怎么知道这个目标程序需要映射什么DLL文件?这就涉及到PE文件格式。我们平时使用的EXE文件,DLL文件基本都是PE格式的,PE格式的文件存储了与这个文件相关的大量信息,系统可以使用这些信息去加载必要的文件,并运行这个可执行文件。
那我们如何拦截API函数,我们可以从映像文件头的导入信息表入手,导入信息表中记录了模块导入的函数的地址信息,比如我们的OpenProcess函数,它从kernel32.dll中导入,我们可以得到该函数的地址后,然后将地址修改为我们函数的地址,这样,当进程调用OpenProcess函数的时候,就会转而调用到我们自己的函数,windows系统的任务管理器有一个结束进程的功能,它会调用OpenProcess函数获得进程的句柄,我们可以拦截OpenProcess,并在自己的函数处理里面判断如果是我们的进程,则让该函数直接返回,否则才放行,也就是调用真正的OpenProcess函数,达到守护进程的目的。
但是这里又有一个问题,我们的函数式在我们的进程地址空间内,而被挂钩的进程如何才能调用到我们进程里的函数呢?这方法有多种,其中有两种比较常用,一种是将函数写在DLL中,然后将DLL注入目标进程中,这样DLL就进入了目标进程地址空间,至于DLL注入技术,网上很多都有介绍,我的博客中也有相应的文章;另外一种就是在目标进程中开辟一块空间(可以使用VirtualAllocEx函数),然后将我们的函数的内容写入目标进程的这块空间中(可以使用WriteProcessMemory函数)。好了,到此,我们可以看看下面具体的代码和分析了。
下面是PE文件的结构图
+-------------------+
| DOS-stub | --DOS-头
+-------------------+
| file-header | --文件头
+-------------------+
| optional header | --可选头
|- - - - - - - - - -|
| |