内核漏洞挖掘技术系列(6)——使用AFL进行内核漏洞挖掘(1)
字数 2492 2025-08-05 08:20:12
使用AFL进行内核漏洞挖掘技术详解
1. AFL QEMU模式原理
AFL的QEMU模式是实现内核Fuzzing的基础,其核心机制包括:
1.1 基本执行流程
- 翻译块(TB)处理:
- QEMU将被模拟架构的基本块(BB)翻译到运行架构
- 翻译块(TB)存储在翻译块缓存(TBC)中,实现一次翻译多次使用
- 在基本块中添加prologue和epilogue处理块间跳转和控制恢复
1.2 关键函数
-
cpu_tb_exec:
- 负责执行TB
- 可获取PC地址等关键信息
-
afl_setup:
- 设置子进程中存储跟踪数据的共享内存数组
-
afl_forkserver:
- 创建fork server并监听fd以启动克隆
-
afl_maybe_log:
- 首次调用执行setup
- 每次执行TB时更新共享跟踪内存
-
tb_find/tb_gen_code:
- 查找和生成翻译块
- 通过afl_request_tsl通知fork server翻译并保存块
1.3 关键补丁
-
syscall.patch:
- 在fork server发生SIGABRT时传递正确的pid和tgid
-
elfload.patch:
- 记录afl_entry_point、afl_start_code和afl_end_code
- 用于afl_maybe_log中的边界检查
2. TriforceAFL实现详解
2.1 整体架构
TriforceAFL对AFL和QEMU进行修改,实现内核Fuzzing:
-
工作流程:
- 启动操作系统并加载Fuzzing驱动程序
- 驱动程序控制Fuzzing生命周期:
- 启动AFL fork server
- 获取测试用例
- 启用解析器跟踪
- 解析测试用例
- 启用内核跟踪
- 执行系统调用
- 通知测试完成
-
隔离机制:
- 每个测试用例在虚拟机的fork副本中运行
- 仅内存状态被隔离,建议使用内存文件系统(如Linux ramdisk)
2.2 关键修改
-
新增aflCall指令:
- 在disas_insn函数中添加处理该指令的case
- 支持操作:
- startForkserver:启动AFL fork server
- getWork:从host文件读取输入到guest缓冲区
- startWork:指定跟踪的虚拟地址范围
- doneWork:通知测试用例完成并传递退出代码
-
命令行参数处理:
- 传入getWork读取的文件名
- 传入panic函数和log_store函数地址
-
代码生成修改:
- 添加gen_aflBBlock函数
- 遇到panic函数时以exit(32)结束
- 遇到log_store函数时记录日志
-
执行优化:
- 禁用QEMU的block chaining特性
- 将AFL跟踪特性从cpu_exec移动到cpu_tb_exec
-
内存管理:
- patch掉ram_block_add中设置QEMU_MADV_DONTFORK的代码
- 新增privmem.c模拟IDE磁盘并支持写时拷贝
-
多线程处理:
- 改进fork server在多线程环境下的行为
- 记录CPU状态并在子进程中恢复
2.3 AFL修改
- 增加默认内存限制
- 延长等待fork server的时间
- 将所有非零退出状态视为崩溃
- 增强实用程序对fork server特性的支持
3. TriforceLinuxSyscallFuzzer实现
3.1 目录结构
- crash_reports:发现的crash
- docs:文档
- rootTemplate & makeRoot:构建ramdisk镜像
- aflCall.c:发起hypercall
- argfd.c:创建系统调用参数使用的文件描述符
- driver.c:主驱动程序
- gen.py/gen2.py/gen2-shapes.txt:生成系统调用输入文件
- getSyms:获取内核符号
- getvmlinux:从bzImage提取vmlinux
- heater.c:预热系统调用
- parse.c:解析函数
- runCmd:执行命令
- runFuzz:启动fuzz
- runTest & testAfl.c:复现crash
- sysc.c:生成系统调用参数
3.2 驱动程序工作流程
- fork子进程执行主要工作
- 子进程启动AFL fork server
- 调用getWork获取输入数据
- 调用startWork跟踪驱动程序解析输入
- 再次调用startWork停止跟踪驱动程序并开始跟踪内核
- 执行已解析的系统调用
- 调用doneWork通知测试完成
4. KAFL架构简介
KAFL采用不同于TriforceAFL的架构:
-
三大组件:
- fuzz逻辑:借鉴AFL,在host上运行
- VM组件:QEMU-PT(用户态)和KVM-QT(内核态)
- 用户态agent
-
通信机制:
- guest通过hypercall与host通信
- host可读写guest内存
-
关键技术:
- 实现Intel PT数据收集和解码
- 性能优于TriforceAFL
5. 实际应用与总结
5.1 工具对比
-
TriforceAFL:
- 优点:基于成熟AFL框架,修改相对简单
- 缺点:实际发现的漏洞较少,维护状态不佳
-
KAFL:
- 优点:性能更好,利用Intel PT技术
- 缺点:实现复杂度高
5.2 当前建议
对于一般内核漏洞挖掘,syzkaller在各方面表现更好,包括:
- 更活跃的维护
- 更丰富的系统调用模型
- 更高的漏洞发现率
6. 参考资料
- AFL官方文档:http://lcamtuf.coredump.cx/afl/
- TriforceAFL项目:https://github.com/nccgroup/TriforceAFL
- TriforceLinuxSyscallFuzzer项目:https://github.com/nccgroup/TriforceLinuxSyscallFuzzer
- KAFL项目:https://github.com/RUB-SysSec/KAFL