Files
reverse-skill/skills/reverse-engineering/kernel-driver-reverse.md
T
yhc 241fa77be0 feat(workflow): non-PE multi-format cookbook U-AV (#65)
Add nonpe-format-cookbook for BAT/PS/VBA/JS/SYS/DLL/Android recipes.
Wire re-agent-workflow §3.4, malware/js/apk/kernel skills, verify asserts.
Dedup DLL Delay-Load with A-T R; detection-only for wiper/BYOVD/reflective.
2026-08-12 21:09:04 +08:00

10 KiB
Raw Blame History

内核驱动逆向参考

覆盖 Windows/Linux 内核驱动逆向、Rootkit 分析、C/C++ 二进制模式识别。


Windows 驱动逆向

驱动类型

类型 特征 分析重点
WDM (Windows Driver Model) 老式驱动,手动管理 IRP DriverEntry → 设备创建 → Dispatch 例程
KMDF (Kernel Mode Driver Framework) 现代框架,事件驱动 EvtDriverDeviceAdd → Queue → I/O 回调
WDF (Windows Driver Foundation) KMDF + UMDF 统称 看 WdfDriverCreate 调用
Minifilter 文件系统过滤驱动 FltRegisterFilter → Pre/Post 回调

WDM 驱动分析流程

1. 找 DriverEntry(入口点)
   - IDA 自动识别,或搜索 IoCreateDevice / IoCreateSymbolicLink

2. 找设备名和符号链接
   - IoCreateDevice → DeviceName(如 \Device\MyDriver)
   - IoCreateSymbolicLink → SymLink(如 \DosDevices\MyDriver)

3. 找 Dispatch 例程
   - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl
   - 这是用户态通过 DeviceIoControl 调用的入口

4. 分析 IOCTL 处理
   - switch(IoControlCode) 分发不同功能
   - IOCTL 编码:CTL_CODE(DeviceType, Function, Method, Access)
   - Method: METHOD_BUFFERED / METHOD_IN_DIRECT / METHOD_OUT_DIRECT / METHOD_NEITHER

5. 找漏洞
   - 用户可控缓冲区未验证长度 → 溢出
   - METHOD_NEITHER 直接使用用户指针 → 任意读写
   - 未检查 IOCTL 权限 → 非特权用户可调用

IOCTL 编码解析

# 解析 IOCTL code
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"}
    access_types = {0: "ANY", 1: "READ", 2: "WRITE", 3: "READ|WRITE"}
    
    return f"DevType=0x{device_type:X} Func=0x{function:X} Method={methods[method]} Access={access_types[access]}"

# 示例
decode_ioctl(0x80002034)
# DevType=0x8000 Func=0x80D Method=BUFFERED Access=ANY

IDA 插件

插件 用途 链接
Driver Buddy Reloaded 自动识别 IOCTL、Dispatch、设备名 https://github.com/VoidSec/DriverBuddyReloaded
WinDbg + IDA 内核调试 + 静态分析配合 内置
FLIRT/Lumina 识别 WDK 库函数 IDA 内置

参考文章


Linux 内核模块逆向

LKM (Loadable Kernel Module) 结构

关键函数:
- init_module / module_init → 模块加载时执行
- cleanup_module / module_exit → 模块卸载时执行

关键结构:
- struct file_operations → 字符设备的 open/read/write/ioctl
- struct net_device_ops → 网络设备操作
- struct block_device_operations → 块设备操作

分析流程

1. 确认是内核模块
   file module.ko → "ELF 64-bit ... relocatable"(注意是 relocatable 不是 executable)

2. 找 init/exit 函数
   readelf -s module.ko | grep -E "init_module|cleanup_module"
   或在 .modinfo section 找模块信息

3. 找 file_operations 结构
   搜索 register_chrdev / cdev_add / misc_register
   → 找到 fops 结构体 → 定位 ioctl/read/write 处理函数

4. 分析 ioctl 处理
   unlocked_ioctl / compat_ioctl 函数
   → switch(cmd) 分发

5. 找 Rootkit 行为
   - 修改 sys_call_table → syscall hook
   - 修改 /proc 文件系统 → 隐藏进程/文件
   - 注册 netfilter hook → 隐藏网络连接
   - 修改 VFS 层 → 隐藏文件

Rootkit 常见技术

技术 特征 检测方法
syscall table hook 修改 sys_call_table 条目 对比内存中的表与磁盘上的 vmlinux
VFS hook 修改 file_operations 函数指针 检查 fops 指针是否指向内核代码段外
Netfilter hook nf_register_net_hook 遍历 netfilter hook 链表
kprobe/ftrace hook 注册 kprobe 或 ftrace 回调 检查 ftrace 注册列表
eBPF rootkit 加载恶意 BPF 程序 bpftool prog list
DKOM 直接修改内核对象(进程链表) 遍历 task_struct 链表对比 /proc

工具

工具 用途
crash 内核 dump 分析
volatility3 内存取证(Linux profile)
dmesg / journalctl 内核日志
lsmod / /proc/modules 已加载模块列表
modinfo 模块元信息
strace 系统调用跟踪(用户态视角)

C/C++ 逆向模式识别

C 语言常见模式

源码模式 反汇编特征
if-else cmp + jcc(条件跳转)
switch-case 跳转表(jmp [rax*8 + table])或连续 cmp
for 循环 cmp + jl/jle + 循环体 + inc/add + jmp 回跳
while 循环 条件判断在循环顶部
do-while 条件判断在循环底部
函数指针调用 call rax 或 call [reg+offset]
struct 访问 [reg+固定偏移](如 [rdi+0x10])
malloc + 使用 call malloc → 返回值存入寄存器 → 后续用该寄存器+偏移访问
字符串比较 call strcmp 或 repe cmpsb

C++ 特有模式

源码模式 反汇编特征
虚函数调用 mov rax, [rcx](取 vtable)→ call [rax+offset](调用虚函数)
构造函数 分配内存 → 写入 vtable 指针 → 初始化成员
析构函数 清理成员 → 可能调用 operator delete
this 指针 第一个参数(rcx/rdi)是对象指针
继承 vtable 中包含父类虚函数 + 子类覆盖
多重继承 对象内有多个 vtable 指针(偏移不同)
RTTI vtable 前面有 type_info 指针
异常处理 __cxa_throw / _CxxThrowException
STL 容器 std::vector: {begin, end, capacity} 三指针结构
std::string 小字符串优化(SSO):短串内联,长串堆分配

vtable 逆向方法

1. 找 vtable
   - 搜索连续的函数指针数组(在 .rodata 或 .rdata 段)
   - 构造函数中 `mov [rcx], offset vtable` 写入 vtable 指针

2. 确定类层次
   - vtable 前 -8 偏移处通常是 RTTI 指针(如果未 strip)
   - 多个 vtable 共享前几个条目 → 继承关系

3. 标注虚函数
   - vtable[0] 通常是析构函数(或 deleting destructor)
   - 后续按偏移标注:vtable[1] = func1, vtable[2] = func2...

4. IDA 中操作
   - 在 vtable 地址创建 struct(每个字段是函数指针)
   - 对 `call [rax+offset]` 添加注释标明调用的虚函数

结构体恢复

方法 1:从访问模式推断
  mov eax, [rdi+0x00]  → field_0: int/ptr (4/8 bytes)
  mov ecx, [rdi+0x08]  → field_8: int/ptr
  movss xmm0, [rdi+0x10] → field_10: float

方法 2:从 sizeof 推断
  call malloc(0x30) → 结构体大小 0x30 (48 bytes)
  
方法 3:从构造函数推断
  构造函数会初始化所有字段 → 字段类型和偏移一目了然

方法 4:用 IDA 的 "Create struct" 功能
  选中访问模式 → Edit → Struct → Create struct from selection

常见编译器特征

编译器 识别特征
MSVC _security_cookie 检查、__fastcall 调用约定、Rich Header
GCC __stack_chk_fail、-fstack-protector、.note.GNU-stack
Clang/LLVM 类似 GCC 但优化模式不同、__asan_*(如果开了 sanitizer)
MinGW GCC 特征 + Windows API 调用
AOSP Clang Android 特有的 __android_log_print、PGO 标记

优化级别识别

优化级别 特征
-O0 大量冗余 mov、每个变量都在栈上、函数不内联
-O1 基本优化、部分变量在寄存器
-O2 循环展开、函数内联、尾调用优化
-O3 / -Os 激进内联、向量化(SIMD)、代码难读
PGO 热路径优化、冷代码分离到 .text.cold
LTO 跨模块内联、全局死代码消除

内核调试环境

Windows

调试器:WinDbg Preview
连接方式:网络调试(推荐)或串口

被调试机设置:
bcdedit /debug on
bcdedit /dbgsettings net hostip:192.168.x.x port:50000

调试机连接:
WinDbg → File → Attach to Kernel → Net → Port:50000 Key:xxx

常用命令:
!analyze -v          # 自动分析崩溃
lm                   # 列出已加载模块
!drvobj \Driver\xxx  # 查看驱动对象
dt nt!_DRIVER_OBJECT # 显示结构体
bp module!function   # 下断点

Linux

调试器:GDB + QEMU 或 kgdb

QEMU 内核调试:
qemu-system-x86_64 -kernel bzImage -s -S ...
gdb vmlinux -ex "target remote :1234"

常用命令:
info threads         # 内核线程
lx-symbols           # 加载内核符号(需要 scripts/gdb/)
p init_task          # 查看 init 进程
lx-dmesg             # 内核日志

Agent 动作锚点(Issue #65 U–AV)

与 references/nonpe-format-cookbook.md §5 对齐(短表,不替代上文流程):

ID 动作 Evidence
AG DriverEntry 短 → 扫 MajorFunction 非空槽,优先 DEVICE_CONTROL/CREATE E-driver-irp-handlers
AH 建立 IOCTL 控制码 → handler 表与 METHOD_* E-driver-ioctl
AI 疑 BYOVD:对照公开脆弱驱动列表;记名/哈希/签名与调用意图;不写 exploit 步骤 E-driver-byovd

参考资源

资源 说明 链接
VoidSec 驱动逆向方法论 Windows WDM 驱动完整分析流程 https://voidsec.com/windows-drivers-reverse-engineering-methodology/
Elastic Rootkit 系列 Linux Rootkit 分类+检测 https://security-labs.elastic.co/security-labs/linux-rootkits-1-hooked-on-linux
Driver Buddy Reloaded IDA 驱动分析插件 https://github.com/VoidSec/DriverBuddyReloaded
LOLDrivers 已知漏洞驱动列表 https://www.loldrivers.io/
Windows Driver Samples 微软官方驱动示例 https://github.com/microsoft/Windows-driver-samples
Linux Kernel Module Programming 内核模块开发教程 https://sysprog21.github.io/lkmpg/
Trail of Bits - Devirtualizing C++ vtable 逆向方法 https://blog.trailofbits.com/2017/02/13/devirtualizing-c-with-binary-ninja/