Hook入门
Hook的概念
从某个角度看,Windows操作系统是由事件向驱动运行的,消息的产生、传递及响应是系统的核心内容之一。
Hook(钩子)是一种特殊的消息处理机制, 它可以监视系统或者进程中的各种消息和事件,截获发往目标对象的消息(包括实体和抽象形式 的消息),并进行响应。
Hook技术能在程序实现正常功能的情况下,先于程序获取到程序的参数、信息、执行情况等
- 监控系统中特定事件的发生并完成相应的功能,包括获取键盘和鼠标的输入信息,进而完成屏幕取词等功能
- 代码功能的嵌入,包括应用程序的补丁、程序的破解、插件的开发、系统中多种信息的隐藏等(如基于函数 CreateProcess、CreateToolhelp32Snapshot、 ZwQuerySystemInformation实现进程隐藏的功能)
根据钩取的对象,Hook技术分为:
Message Hook:
-
线程钩子,可以监视指定线程的消息;
-
系统钩子,可监测整个系统内部的所有消息,由于会影响多个进程,需要进程注入;
API Hook,根据实现方法:
-
内联汇编Hook(Inline Hook);
-
IAT Hook等;
-
API Hook是木马程序编写中的常用技术,在APT攻击中扮演重要角色,是本章要讲授的主要内容
1 Message Hook
Message Hook也叫做消息钩子,针对的是GUI(图形用户界面)程序
使用的关键Windows API函数SetWindowsHookEx, MSDN(Microsoft Developer Network)定义如下
-
第一个参数是Windows消息值
比如WH_KEYBOARD可以控制WM_KEYUP和WM_KEYDOWN两个消息值(用于描述键盘虚拟键码,对应物理按键Pgup和Pgdn)
-
第二个参数是我们对应消息的回调函数,比如当触发按键消息的时候,设置的对应按键回调函数就会调用
-
第三个参数是包含hook代码的动态链接库DLL句柄
DLL句柄是操作系统分配的标识符,用于表示动态链接库在内存中的加载状态,实际上是一个内存地址,指向DLL在内存中加载的位置。它的主要功能是访问DLL中的资源、调用函数、动态加载/卸载DLL。
当应用程序或其他DLL调用
LoadLibrary
或GetModuleHandle
加载DLL时,操作系统为该DLL分配一个句柄,表示DLL在进程地址空间中的加载位置。此句柄被用来访问和操作该DLL的内容。DLL句柄可用于调用DLL中的函数(例如通过GetProcAddress
)或访问DLL中定义的资源(如字符串、对话框模板、图标等)。 -
第四个参数是所钩取的线程id,如果设置为0,则为全局钩取,即所有的GUI程序都将被钩取
在使用SetWindowsHookEx函数以后,消息钩子会先于应用程序看到相应消息,并对消息进行拦截,调用回调函数里对消息进行处理
自己写的回调函数代码应该是在我们自己写的应用程序里,怎么会被其他应用程序调用的呢,进程和进程之间不应该是相互隔离的么?
在SetWindowsHookEx函数成功产生作用时,对应监控的应用程序里会被注入一个动态链接库DLL,我们的关键代码就写在被加载的这个DLL当中
进程注入需求的产生:
-
应用程序之间是相互独立的,各自享有自己的内存空间
-
应用程序需要跨越进程边界来访问另一个进程的地址空间时,就会使用进程注入
-
为了对内存中的某个进程进行操作,并且获得该进程地址空间里的数据,或者修改进程的私有数据,修改程序执行流,就需要把代码放入到目的进程当中,这时就避免不了使用进程注入方法了
进程注入的方法:

Message Hook方式虽然简单,但是也存在不足, 它只能捕获Windows操作系统向用户提供的消息事件,诸如借助键盘、鼠标操作的事件,能控制的函数有限(具体的消息范围都可以在MSDN的介绍中找到)
2 Inline API Hook
内联汇编是指在高级语言(如C或C++)代码中直接插入汇编代码的一种编程技术
实现步骤:
-
获取API的函数地址
获取WriteFile函数地址
#include<stdio.h> #include<Windows.h> int main(){ HMODULE hKernel32; // HMODULE 是代表应用程序载入的模块 FARPROC pWriteFile; // 指向函数的指针,其指针类型为WINAPI hKernel32 =GetModuleHandle(L"kernel32.dll"); //GetModuleHandle函数用于获取已加载的模块句柄,这里用于获取kernel32.dll的句柄,因为WriteFile函数位于该模块中 //参数 L"kernel32.