第 27 章 Windows 内核逆向(驱动 / Rootkit)
内核逆向 = 分析 .sys 驱动、内核模块、Rootkit。核心知识点:驱动模型(WDM/KMDF)、IOCTL 通信、Dispatch 例程、Rootkit 技术分类、内核调试。本章以知识架构为主,代码为辅。
📍 知识点地图 | 主题:内核逆向 | 前置:第4章 | 后续:第79章 | 核心概念:WDM/KMDF、IOCTL、Rootkit、WinDbg
27.1 为什么要分析内核
驱动是提权漏洞的重灾区: 内核驱动 ioctl 越权写 → 任意地址写 → SYSTEM
Rootkit 是隐蔽持久化的基础: 内核态可隐藏进程/文件/网络
EDR 与反 EDR 的战场: 现代检测都在内核层
27.2 Windows 驱动模型分类学
| 模型 | 特征 | 分析重点 |
|---|---|---|
| WDM | 老式,手动管理 IRP | DriverEntry → 设备创建 → Dispatch 例程 |
| KMDF | 现代框架,事件驱动 | EvtDriverDeviceAdd → Queue → I/O 回调 |
| Minifilter | 文件系统过滤驱动 | FltRegisterFilter → Pre/Post 回调 |
| NDIS | 网络驱动 | 网卡/协议栈 |
| 恶意驱动 | 常伪装成合法签名(BYOVD) | 看 LolDrivers 已知漏洞驱动库 |
27.3 WDM 驱动分析流程(架构)
1. 找 DriverEntry(入口)
→ IDA 自动识别,或搜 IoCreateDevice / IoCreateSymbolicLink
2. 找设备名与符号链接
→ \Device\MyDriver(内核名) / \DosDevices\MyDriver(用户态名)
→ 用户态 CreateFile("\\.\MyDriver") 就能打开
3. 找 Dispatch 例程(核心!)
→ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl
→ 这是 DeviceIoControl 调用的入口
4. 分析 IOCTL 分发
→ switch(IoControlCode) 分发不同功能
→ 每个 case 是一个"功能模块"
5. 找漏洞(安全分析的核心)
→ 用户可控缓冲区未验证长度 → 溢出
→ METHOD_NEITHER 直接用用户指针 → 任意读写
→ 未检查权限 → 非特权用户可调用
27.4 IOCTL 编码原理(必须会解析)
IOCTL code 是 32 位整数,4 段信息编码:
31 16 15 14 13 2 1 0
┌────────┬────┬────────┬──┐
│DeviceType│Acc│ Function│Meth│
└────────┴────┴────────┴──┘
Method: 0=BUFFERED 1=IN_DIRECT 2=OUT_DIRECT 3=NEITHER
Access: 0=ANY 1=READ 2=WRITE 3=READ|WRITE
def decode_ioctl(code):
device_type = (code >> 16) & 0xFFFF
access = (code >> 14) & 0x3
function = (code >> 2) & 0xFFF
method = code & 0x3
methods = {0:"BUFFERED",1:"IN_DIRECT",2:"OUT_DIRECT",3:"NEITHER"}
return (f"DevType=0x{device_type:X} Func=0x{function:X} "
f"Method={methods[method]} Access=ANY")
decode_ioctl(0x80002034)
# DevType=0x8000 Func=0x80D Method=BUFFERED Access=ANY
安全含义:
METHOD_BUFFERED: 系统复制缓冲区 → 漏洞点是长度检查缺失
METHOD_NEITHER: 直接用用户态指针 → 可造成任意读写(高危)
Access=ANY: 任何权限都能调用该 ioctl → 提权入口
27.5 内核 Rootkit 技术分类(检测视角)
| 技术 | 实现原理 | 检测方法 |
|---|---|---|
| syscall table hook | 修改 sys_call_table 条目 | 对比内存表与磁盘 vmlinux |
| VFS hook | 改 file_operations 函数指针 | 检查 fops 指针是否越界 |
| Netfilter hook | 注册网络过滤回调 | 遍历 netfilter hook 链表 |
| kprobe/ftrace hook | 注册内核回调 | 检查 ftrace 注册列表 |
| eBPF rootkit | 加载恶意 BPF 程序 | bpftool prog list |
| DKOM | 直接修改内核对象(进程链表) | 遍历 task_struct 对比 /proc |
| IRP hook | 劫持驱动 IRP 分发 | 检查 MajorFunction 表 |
Rootkit 逆向重点:找到它 hook 了什么(哪个表/哪个函数)、hook 逻辑是什么(过滤了什么)、怎么恢复。
27.6 Linux 内核模块(LKM)逆向
识别与分析流程
file module.ko # 注意: relocatable,不是 executable!
# 找入口
readelf -s module.ko | grep -E "init_module|cleanup_module"
modinfo module.ko # 元信息
# 找 file_operations(核心!)
# 搜索 register_chrdev / cdev_add / misc_register
# → 找到 fops 结构体 → 定位 ioctl/read/write 处理函数
# 分析 ioctl
# unlocked_ioctl / compat_ioctl → switch(cmd) 分发
# 找 Rootkit 行为
# 修改 sys_call_table / /proc / netfilter / VFS
加载调试
# QEMU + GDB 内核调试
qemu-system-x86_64 -kernel bzImage -s -S ...
gdb vmlinux -ex "target remote :1234"
# 常用: info threads / lx-symbols / lx-dmesg / p init_task
27.7 内核调试环境搭建
Windows(WinDbg)
被调试机:
bcdedit /debug on
bcdedit /dbgsettings net hostip:192.168.x.x port:50000
调试机:
WinDbg → Attach to Kernel → Net → Port:50000
常用命令:
!analyze -v # 自动分析崩溃
lm # 已加载模块
!drvobj \Driver\xxx # 驱动对象
dt nt!_DRIVER_OBJECT # 结构体
bp module!function # 下断点
Linux(QEMU + GDB)
qemu-system-x86_64 -kernel bzImage -s -S ... # -s = gdb 1234, -S = 暂停
gdb vmlinux
(gdb) target remote :1234
(gdb) lx-symbols # 加载内核符号
(gdb) lx-dmesg # 内核日志
27.8 驱动漏洞常见模式(安全审计清单)
□ 未验证缓冲区长度 → 栈/堆溢出
□ METHOD_NEITHER 用户指针未校验 → 任意地址读写
□ 无权限检查 → 非特权用户触发
□ 竞争条件(多线程同时 ioctl)→ 双重释放/UAF
□ 整数溢出 → 绕过长度检查
□ 任意地址写 → 改 SSDT/调用门/进程令牌
□ 符号链接劫持 → 与用户态配合
27.9 工具链
| 工具 | 用途 |
|---|---|
| IDA + Driver Buddy Reloaded | 驱动分析(自动识别 IOCTL/Dispatch) |
| WinDbg Preview | Windows 内核调试 |
| GDB + QEMU | Linux 内核调试 |
| Volatility 3 | 内存取证(找隐藏模块) |
| crash | 内核 dump 分析 |
| LolDrivers | 已知漏洞驱动库(BYOVD 查询) |
| FLIRT/Lumina | 识别 WDK 库函数 |
动手练习
- 用 IDA 打开一个 WDM 示例驱动(微软驱动示例),走完 27.3 的五步流程。
- 练习 IOCTL 解码:给 5 个 IOCTL code,写出 Method/Access/Function。
- 阅读一个 Rootkit 样本分析报告,指出它用了 27.5 表中的哪些技术。
- 搭一个 QEMU + GDB 内核调试环境,加载一个测试模块并下断点。
深入阅读
- 仓库:
skills/reverse-engineering/kernel-driver-reverse.md(本仓库内核驱动逆向全量参考) - 仓库:
skills/reverse-engineering/platforms.md(内核驱动/eBPF 章节) - 仓库:
skills/reverse-engineering/languages-compiled.md(C++ vtable 恢复) - 仓库:
skills/pwn-chain/references/kernel-pwn.md(内核漏洞利用) - 实战案例:
skills/field-journal/seed-016_k8s-container-escape.md