HOOK技术主要分为两大类,一是内核层HOOK,一是用户层HOOK. 用户层HOOK也就是在ring3环境下hook kenerl32.dll、
User3.dll、Gui32.dll、Advapi.dll等导出的函数。而内核层HOOK就是HOOK只有ring0级别环境下才能操作写入改变的内核
对象,例如SSDT系统服务描述符表等。综合而言,主要有以下9种HOOK技术。
(1)消息钩子
消息钩子是最常见的钩子之一,例如常见的键盘鼠标钩子,很多木马就是通过消息钩子获取密码的。消息钩子是由Win32子
系统提供,用户通过它注册全局钩子。当系统获取某些事件,比如用户按键,键盘driver将扫描码等传入win32k的KeyEvent
处理函数,处理函数判断有无相应hook,有则通过回调函数处理。此时,系统取得Hook对象信息,若目标进程没有装载对应
的Dll,则装载之。
(2)IAT HOOK
IAT HOOK[4]是最常见和普遍的HOOK之一。IAT表示导入地址表(Import Address Table),导入函数就是被程序调用但其执行
代码又不在程序中的函数,当PE 文件被装入内存的时候,Windows 装载器才将DLL 装入,并将调用导入函数的指令和函数
实际所处的地址联系起来(动态连接),这种操作就需要导入表完成。其中导入地址表就指示函数实际地址。程序每个调用的
API 函数地址都保存在 IAT 表中,而每个调用 API 函数的 CALL 指令所使用的地址都是相应函数登记在 IAT 表的地址。
IATHOOK原理是在将 IAT 表中的地址换成用户自己的 函数地址,这样每个 API 调用都是先调用用户自己的 函数。在这个
函数中我们可以完成函数名称的记录、参数的记录、调用原来的过程,并在返回时记录结果。
(3)EAT HOOK
EAT HOOK的原理是根据替换 PE 格式导出表中的相应函数来实现的。EAT表示导出地址表(Export Address Table),EAT存在
于PE文件中的edata节,保存了可执行文件(如DLL 文件)的导出的可供其他模块来调用的函数和公共变量,包括函数名称
和地址等。通过替换Windows 系统某些重要DLL中的输出函数地址,即可实现目标函数的挂接。EAT记录DLL中可供其他程序
使用的函数,可执行文件装载时会使用相应DLL的EAT表来初始化IAT表。
EAT HOOK原理是通过替换EAT表中的函数地址,使依赖于本DLL的程序得到一个假的地址。
(4)SSDT HOOK
SSDT是最常见的内核层 HOOK。SSDT的全称是系统服务描述符表(System Services Descriptor Table)。SSDT是关联ring3的
Win32 API和ring0的内核API的重要数据结构,它存储着Windows把需要调用的所有内核API地址。
SSDT HOOK原理是将内核层 API地址修改为指向其位于Ring0层的驱动入口,这样每次系统执行到这个函数时,都会通过SSDT表将原始调用引向修改后的模块中。
(5)IDT HOOK
IDT HOOK是Win2000操作系统上常用的一种HOOK。IDT是中断描述表,可以替换其中的中断处理程序。这种方法对于跟踪、分析系统调用来说用的比较多。
IDT HOOK的原理是通过替换 IDT表中的 INT 2E 中断,使之指向新的中断服务处理例程来实现的。它首先保存出特定的中断
向量中断服务程序(ISR), 然后直接修改该中断向量的ISR为自定义的函数,每当这个中断向量对应的中断产生时,就会调用
自定义的函数。由于我们自定义的函数里面执行完我们的功能后再跳转到原ISR处执行。
(6)SYSENTRY HOOK
SYSENTRY是Windows XP之后的操作系统进入ring0的函数。Win2000中通过 int2e系统调用机制,涉及到的
Interrupt/Exception Handler的调用都是通过 call/trap/task这一类的gate来实现的,这种方式会进行栈切换,并且系统
栈的地址等信息由TSS提供,可能会引起多次内存访问 (来获取这些切换信息),系统开销较大。SYSENTER通过汇编指令实现快速系统调用机制。
SYSENTER HOOK的原理是首先Ntdll 加载相应的请求服务号到EAX 寄存器中,同时EDX 寄存器存贮当前的栈指针ESP,然后
Ntdll发出SYSENTER 指令,该指令转移控制权到寄存器IA32_SYSENTER_EIP 存贮的地址中[21],通过修改这个地址,可实现
相应的挂接。
(7)Inline HOOK
inline hook是直接在以前的函数体内修改指令,用一个跳转或者其他指令来实现挂钩的目的。
而普通的hook只是修改函数的调用地址,而不是在原来的函数体里面做修改。
Inline hook原理是解析函数开头的几条指令,把他们Copy到数组保存起来,然后用一个调用我们的函数的几条指令来替换
,如果要执行原函数,则在我们函数处理完毕,再执行我们保存起来的开头几条指令,然后调回我们取指令之后的地址执行
。它需要在程序中嵌入汇编代码(Inline Assembly)以操作堆栈和执行内核API对应的部分汇编指令。
(7)OBJECT HOOK
OBJECT HOOK是相对于IAT HOOK之类的 API HOOK而言,API HOOK是挂钩应用层函数,而OBJECT HOOK是挂钩内核层函数。其原理与API HOOK类似。
(9)IRP HOOK
IRP是 I/O request packets,在Windows中几乎所有的I/O都是通过包(packet)驱动的,每个单独的I/O由一个工作命令描
述,此命令将会告诉驱动程序需要一些什么操作,并通过I/O子系统跟踪处理过程。这些工作命令就表现为一个个被称为IRP
的数据结构。
IRP HOOK原理是拦截管理器发向文件或网络系统等驱动程序的IRP。一般通过创建一个上层过滤器设备对象并将之加入系统
设备所在的设备堆栈中。也有部分IRP HOOK通过拦截传递IRP请求包的函数IofCallDriver或MajorFunction函数表来实现的。