0%
毅种循环

模块 83 - NTDLL 取消挂钩 (Unhooking) - 简介

恶意软件开发课程 - NTDLL 取消挂钩 (Unhooking) - 简介


模块 83 - NTDLL 取消挂钩 (Unhooking) - 简介#

NTDLL 取消挂钩 (Unhooking) - 简介#

简介#

前面的模块展示了如何使用 Direct Syscalls(直接系统调用) 来绕过用户态挂钩 (Userland Hooks)。在本模块中,我们将介绍另一种实现相同目标的策略:取消挂钩 (Unhooking)

💡 初学者提示:什么是取消挂钩 (Unhooking)?

类比理解: 想象 EDR 在你的办公桌(ntdll.dll)上装了许多监控(Hooks)。

  • 之前的策略(直接系统调用):你决定不在桌子上办公了,直接跑去地下的工厂(内核)干活,以此避开监控。
  • 现在的策略(取消挂钩):你找了一张一模一样、但没有装监控的新桌子,悄悄把原来的旧桌子给换掉。这样你就能继续在大摇大摆地在桌面上干活,而 EDR 的监控却失效了。

这种技术的核心在于:将进程中被挂钩的 DLL 替换为一个未经修改的、干净的版本。

处理核心难点:.text 节替换#

替换整个 DLL 会涉及繁琐的 IAT(导入地址表)重新设置、重定位修复等任务。为了简化操作,我们通常只替换 DLL 中真正被挂钩的部分,即 .text

.text 节包含了 DLL 导出的所有函数代码,也是监控代码(Hooks)被注入的地方。替换它需要以下关键信息:

  1. 基地址 (Base Address).text 节在内存中的起始位置。
  2. 大小 (Size).text 节占据的字节数。

这些信息可以在 PE 文件的 IMAGE_OPTIONAL_HEADER 中的 BaseOfCodeSizeOfCode 字段找到。

关键概念:文件 vs 内存中的对齐差异#

实现取消挂钩时,必须理解 DLL 在“磁盘上”和“内存中”的布局差异。

📚 知识扩展:为什么会有对齐差异?

  • 磁盘对齐 (File Alignment):通常为 1024 字节 (1KB)。这是为了优化磁盘 I/O(读写速度),让硬件能够大块大块地读取。
  • 内存对齐 (Section Alignment/Page Alignment):通常为 4096 字节 (4KB)。这是因为现代 CPU 和操作系统管理虚拟内存的最小单位是“页” (Page),通常就是 4KB。

偏移量的变化#

  1. 在磁盘上:多数 DLL 的 .text 节文件偏移量 (Raw Offset) 是 0x400 (1024)。
  2. 在内存中:当 DLL 被加载到进程空间后,.text 节的虚拟偏移量 (Virtual Offset) 通常变为 0x1000 (4096)。

这种位移差异至关重要。当你从磁盘读取一个干净的 ntdll.dll 打算替换内存中的挂钩版本时,你必须根据读取方式(是作为原始文件读取,还是作为映像映射)来正确计算 .text 节的起始位置,否则你的数据拷贝将会完全错位,导致程序崩溃。

NTDLL 取消挂钩的几种获取来源#

在接下来的模块中,我们将学习如何从以下不同渠道获取“干净”的 ntdll.dll 副本:

  • 来自磁盘 (From Disk):直接读取 C:\Windows\System32\ntdll.dll
  • 来自 KnownDlls 目录 (From KnownDlls):利用 Windows 内部维护的 DLL 缓存路径。
  • 来自挂起状态的进程 (From a Suspended Process):从另一个未被 EDR 挂钩的“干净”进程中读取。
  • 来自 Web 服务器 (From a Webserver):从远程服务器下载匹配版本的 DLL。

我们将逐一深入探讨这些实战方法。