Windows Hook原理与实现

Windows Hook原理与实现WindowsHook 原理与实现教程参考自 逆向工程核心原理 1 概述 Hook 技术被广泛应用于安全的多个领域 比如杀毒软件的主动防御功能 涉及到对一些敏感 API 的监控 就需要对这些 API 进行 Hook 窃取密码的木马病毒 为了接收键盘的输入 需要 Hook 键盘消息 甚至是 Windows 系统及一些应用程序 在打补丁时也需要用到 Hook 技术 接下来 我们就来学习 Hook 技术的原理

Windows Hook原理与实现



1.概述

Hook技术被广泛应用于安全的多个领域,比如杀毒软件的主动防御功能,涉及到对一些敏感API的监控,就需要对这些API进行Hook;窃取密码的木马病毒,为了接收键盘的输入,需要Hook键盘消息;甚至是Windows系统及一些应用程序,在打补丁时也需要用到Hook技术。接下来,我们就来学习Hook技术的原理。

下图很简单易懂地诠释了Hook的机制,在notepad.exe和kernel32.dll之间挂上一个“钩子”,把它们要使用的CreateFile()函数替换掉,换成MyCreateFile()函数,实现我们想要的自定义功能。

1


2.Hook分类

Hook分为应用层(Ring3)Hook和内核层(Ring0)Hook,应用层Hook适用于x86和x64,而内核层Hook一般仅在x86平台适用,因为从Windows Vista的64版本开始引入的Patch Guard技术极大地限制了Windows x64内核挂钩的使用。

2


3.消息Hook

3.1 技术原理

3.2 代码实现


4.调试Hook

4.1 技术原理

所以,调试Hook的核心思路就是将API的第一个字节修改为0xCC(INT 3),当API被调用时,由于触发了异常,控制权就被转交给调试器。

4.2 代码实现

7


5.注入Hook

Hook的核心思想就是修改API的代码,但是,比如我A进程要Hook一个B进程的CreateProcess函数,A是没有权限修改B内存中的代码的,怎么办?这时候使用DLL注入技术就可以解决这问题,我们将Hook的代码写入一个DLL(或直接一个shellcode),将此DLL注入到B进程中,此时因为DLL在B进程的内存中,所以就有权限直接修改B内存中的代码了。

5.1 IAT Hook

IAT Hook顾名思义就是通过修改IAT里的函数地址对API进行Hook。

5.1.1 技术原理

7

8

5.1.2 代码实现

下图是Hook IAT的代码实现,核心代码很少,大部分代码在计算IAT的位置。这里值得注意的是,我们把SetWindowTextW()替换为我们的恶意函数后,我们的恶意函数执行完后必须要调用回SetWindowTextW()(在Hook之前我们保存了SetWindowTextW()的地址),这样才能保证功能的完整性。

9

5.2 Inline Hook

内联Hook相比于IAT Hook,显得更简单粗暴,它直接修改内存中任意函数的代码,将其劫持至Hook API。同时,它比IAT Hook的适用范围更广,因为只要是内存中有的函数它都能Hook,而后者只能Hook IAT表里存在的函数(有些程序会动态加载函数)。

5.2.1 技术原理

Inline Hook的目标是系统函数,如下,左图是Hook之前的状态,procexp.exe进程调用ZwQuerySystemInformation()函数时,ZwQuerySystemInformation()的代码是正常的代码。右图是Hook后的状态,注意红框中的代码,ZwQuerySystemInformation()函数开头5个字节已被修改,变成了jmp 0x,也就是我们恶意代码的地址,之后便可以开始我们的自定义操作。0xA我们先进行unhook操作(脱钩),目的是将ZwQuerySystemInformation()的代码恢复。大家可能有疑惑,为什么刚修改完又要恢复回来,原因很简单,Hook的目的是当调用某个函数时,我们能劫持进程的执行流。现在我们已经劫持了进程的执行流,便可以恢复ZwQuerySystemInformation()的代码,以便我们的恶意代码可以正常调用ZwQuerySystemInformation()。执行完恶意代码后,再次挂钩,监控该函数。

10

11

5.2.2 代码实现

首先获取原API的地址,并保存在pfnOrg中,然后修改内存段属性为RWX,备份原有代码(以便后续代码恢复),实时计算JMP的相对偏移,最后修改API前5字节的代码,恢复内存属性。

12

5.3 HotFix Hook

5.3.1 技术原理

MOV EDI,EDI用于将EDI的值再次复制给EDI,这没有什么实际意义。也就是说,API起始代码的MOV指令(2个字节)与其上方的5个NOP指令(5个字节)合起来共7个字节的指令没有任何意义。所以我们就可以通过修改这7个字节来实现Hook操作。这种方法因为可以在进程处于运行状态时临时更改进程内存中的库文件,所以微软也常用这种方法来打“热补丁”。

13

这样,当API被调用时,首先执行了JMP SHORT 0x7C,便跳到了JMP 处执行,最后跳到了恶意代码的起始处0x。

14

在5字节代码修改技术中“脱钩”是为了“调用原函数”,而使用“热补丁”技术钩取API时,在API代码遭到修改的状态下也能正常调用原API(从[API起始地址+2]地址开始,仍然能正常调用原API,且执行的动作也完全一样)。

5.3.2 代码实现

该技术难的地方在于计算偏移地址。

15

由于HotFix Hook需要修改7个字节的代码,所以并不是所有API都适用这种方法,若不适用,请使用5字节代码修改技术。


6.SSDT Hook

SSDT Hook属于内核层Hook,也是最底层的Hook。由于用户层的API最后实质也是调用内核API(Kernel32->Ntdll->Ntoskrnl),所以该Hook方法最为强大。不过值得注意的是

6.1SSDT原理

内核通过SSDT(System Service Descriptor Table)调用各种内核函数,SSDT就是一个函数表,只要得到一个索引值,就能根据这个索引值在该表中得到想要的函数地址。

16

下图0x处就是ntoskrnl对应的服务描述符表结构SSDT。那么第一个32位的0x804e58a0则是SSDT Base,即SSDT的首地址。

17

通过对这些地址反汇编,就能得到相应的函数,下图中0x80591bfb是SSDT表中的第一个函数NtAcceptConnectPort的地址。

18

我们接下来试着寻找NtQuerySystemInformation的地址,首先反汇编ZwQuerySystemInformation,得知它要寻找SSDT中索引号为0xAD的地址。

19

20

6.2SSDT Hook

21

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/217678.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午9:01
下一篇 2026年3月18日 上午9:02


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号