高级内核Rootkit攻防技术:从Kdmapper到PTE Walk与NMI检测
前言
内核Rootkit以其高权限、高隐蔽性而著称,传统的防御手段效率低下,不适合实战攻防。本文从内核Rootkit攻击原理出发,剖析著名的Kdmapper手动映射驱动项目,并从内存扫描、堆栈遥测、通信检测三个角度阐述先进的防御手段,帮助读者理解现代内核安全领域的攻防实践。
1. Kdmapper 原理剖析
Kdmapper是利用Intel驱动中的任意内核地址读写漏洞,手动将驱动映射至内核地址空间执行,从而绕过Windows驱动签名验证(DSE)的经典工具。
1.1 核心流程:MapDriver
-
内核内存分配:
根据模式选择分配内存。AllocateIndependentPages模式防止分配出大页内存,避免某些检测。ULONG64 kernel_image_base = 0; if (mode == AllocationMode::AllocateIndependentPages) { kernel_image_base = intel_driver::MmAllocateIndependentPagesEx(image_size); } else { // AllocatePool by default kernel_image_base = intel_driver::AllocatePool(nt::POOL_TYPE::NonPagedPool, image_size); } -
PE文件处理:
在用户态解析PE文件,执行重定位等操作,与DLL反射加载过程类似。 -
写入内核内存:
将处理好的PE镜像数据写入到分配的内核内存地址。if (!intel_driver::WriteMemory(realBase, (PVOID)((uintptr_t)local_image_base + (destroyHeader ? TotalVirtualHeaderSize : 0)), image_size)) { // 错误处理 } -
设置内存保护属性:
将内存页设置为可执行(PAGE_EXECUTE_READ等)。if (!intel_driver::MmSetPageProtection(secAddr, secSize, prot)) { // 错误处理 } -
调用DriverEntry:
通过HookNtAddAtom等函数,跳转执行驱动入口点。NTSTATUS status = 0; if (!intel_driver::CallKernelFunction(&status, address_of_entry_point, (PassAllocationAddressAsFirstParam ? realBase : param1), param2)) { // 错误处理 }
1.2 痕迹清除
Kdmapper会抹除以下列表中的加载痕迹,增强隐蔽性:
- PiDDBCacheTable:驱动加载记录表。
- g_KernelHashBucketList:内核模块哈希缓存列表。
- MmUnloadedDrivers:未加载驱动列表。
项目参考:FiYHer/system_trace_tool - 专门用于清理驱动加载/卸载痕迹。
2. 高级检测技术:PTE Walk
传统线性地址或物理地址扫描效率极低。PTE Walk通过遍历页表,快速定位实际映射的内存页,极大提升检测效率。
2.1 x64页表结构
Windows x64采用4级页表结构:
- PML4E (Page Map Level 4)
- PDPTE (Page Directory Pointer Table)
- PDE (Page Directory)
- PTE (Page Table)
2.2 页表项(PTE)结构
typedef union _HARDWARE_PTE_X64 {
ULONG64 value;
struct {
ULONG64 present : 1; // 页是否存在于物理内存
ULONG64 write : 1; // 是否可写
ULONG64 owner : 1; // 用户/内核模式
// ... 其他标志位 ...
ULONG64 large_page : 1; // 是否为大页 (1GB or 2MB)
ULONG64 global : 1;
// ... 其他标志位 ...
ULONG64 page_frame_number : 36; // 物理页帧号 (PFN)
// ... 其他标志位 ...
ULONG64 noExecute : 1; // 执行禁止位 (NX)
} Bits;
} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64;
2.3 PTE Walk 算法步骤
- 获取CR3:读取CR3寄存器获取当前进程的PML4物理地址。
- 映射CR3:将PML4物理地址映射到内核虚拟地址空间。
- 遍历页表:从PML4开始逐级向下遍历:
- 检查
Present位,快速跳过未使用的虚拟地址范围。 - 处理大页(1GB或2MB),直接获取大页属性。
- 遍历到最后一级PTE,获取4KB页的属性。
- 检查
- 记录内存属性:收集所有已映射页的虚拟地址、大小和属性(R/W/X)。
2.4 检测原理
Kdmapper等工具分配的内存通常具有可执行但未关联合法内核模块的特性。通过PTE Walk快速扫描整个内核地址空间(耗时<1秒),可以高效定位这些异常的可执行页,进而进行针对性扫描或特征提取。
3. 高级检测技术:NMI中断堆栈检查
另一种思路是通过中断触发,检查CPU各核心上正在执行线程的堆栈,寻找异常返回地址。
3.1 为何选择NMI?
- 不可屏蔽中断 (Non-Maskable Interrupt):拥有最高优先级,Rootkit无法屏蔽此中断。
- 其他方式(如IPI、DPC、APC)可能被绕过。
3.2 实现原理
- 发送NMI:向所有CPU核心发送NMI中断。
- 注册NMI回调:在每个CPU上触发回调函数。
- 安全采集堆栈:
- 关键点:NMI运行在极高IRQL,代码必须极简且快速,否则易导致系统蓝屏。
- 方法:参考可靠方法(如周旋久师傅的方法),避免直接在回调中调用
RtlWalkFrameChain。 - 步骤:
- 通过
KPCR结构获取CPU上下文。 - 通过
TSS获取异常处理栈地址。 - 解析
machineFrame结构,捕获被中断线程的RIP(返回地址)和RSP。
- 通过
- 分析堆栈:
- 在NMI回调之外的较低IRQL环境下,分析采集到的
RIP。 - 检查
RIP是否指向已知合法内核模块(ntoskrnl.exe,win32k.sys等)的地址范围内。 - 若
RIP不在任何合法模块中,则判定为Rootkit线程。
- 在NMI回调之外的较低IRQL环境下,分析采集到的
3.3 优缺点
- 优点:能有效检测无模块化Rootkit的执行线程。
- 缺点:需要Rootkit线程相对活跃才能命中。对游戏外挂等频繁运行的Rootkit效果较好。
4. 通信与检测:.data ptr Hijacking
当攻击者使用自家Rootkit驱动时,会避免使用标准通信方式(如IRP),转而采用更隐蔽的技术,如.data段函数指针劫持。
4.1 原理
- 背景:Windows图形子系统(如
win32kbase.sys)包含许多用户态可触发、内核态执行的函数指针。 - 漏洞:Patch Guard对内核
.data段的指针监控并非全覆盖。 - 攻击:找到这些函数指针,将其替换为攻击者控制的恶意函数地址。
4.2 利用步骤(以Win11 21H2为例)
-
定位目标函数:
- 目标函数:
ApiSetEditionCreateWindowStationEntryPoint(未导出)。 - 方法:先定位其上层导出函数
NtUserCreateWindowStation。
PVOID funcAddr = GetSystemRoutineAddress(L"win32kbase.sys", "NtUserCreateWindowStation");- 在
NtUserCreateWindowStation函数体中,通过特征码48 8B 05 ?? ?? ?? ?? 48 85 C0定位到ApiSetEditionCreateWindowStationEntryPoint中的函数指针。
- 目标函数:
-
挂靠进程上下文:
win32kbase.sys在会话空间加载。需使用KeStackAttachProcess挂靠到GUI进程(如winlogon.exe)的上下文中才能操作其内存。
-
替换指针:
- 备份原函数指针。
- 将指针替换为恶意Hook函数地址。
-
用户态触发:
- 用户态调用
CreateWindowStationA,触发执行被替换的函数指针,从而执行内核态恶意代码。 - 可实现通信、强杀安全软件、连接C2等功能。
- 用户态调用
4.3 检测方法
- 检测难度:困难。因Windows内核中此类指针数量庞大,且随版本变化。
- 现有方案:
- 行为监控:捕捉异常高频的特定系统调用(如
NtUserCreateWindowStation)。 - 指针验证:追踪到调用的内核函数,检查其
.data指针是否指向预期模块内部。若指针指向win32kbase.sys等模块外部,则判定为篡改。 - 特征扫描:对已知易受攻击的指针进行定期扫描和校验。
- 行为监控:捕捉异常高频的特定系统调用(如
5. 参考资源
- 反反 Rootkit 技术 - 第三部分:劫持指针
- Kernel-Adventures/DataPtrHijack
- 看雪论坛:简述常规的 "驱动.data通信" 如何利用/查找
- 看雪论坛:使用NMI中断检测无模块驱动
- FiYHer/system_trace_tool