fuzz初战-fuzz Xpdf3.02详解
字数 1343 2025-08-29 08:30:18
Fuzz初战:Fuzz Xpdf 3.02详解
1. AFL++安装与配置
1.1 安装依赖项
首先需要安装AFL++的依赖项,确保系统具备编译和运行AFL++的基本环境。
1.2 检验和构建AFL++
- 下载AFL++源代码
- 执行构建命令:
make - 安装:
sudo make install
1.3 验证安装
输入AFL_fuzz命令进行验证,确认安装成功。
AFL++特点:
- 覆盖引导的fuzzer
- 为每个变异的输入收集覆盖信息
- 支持插桩技术
- 当源代码可用时,AFL可以使用检测,在每个基本块(函数、循环等)的开头插入函数调用
2. Xpdf编译与插桩
2.1 正常编译Xpdf
首先进行正常编译,验证Xpdf可以正常构建。
2.2 插桩编译
- 删除之前编译的Xpdf
- 使用AFL++提供的编译器进行插桩编译:
CC=afl-clang-fast CXX=afl-clang-fast++ ./configure make
3. Fuzz过程
3.1 常见问题解决
在fuzz过程中可能会遇到核心转储(core dump)通知问题,解决方法:
echo core | sudo tee /proc/sys/kernel/core_pattern
3.2 运行Fuzzer
使用以下命令启动fuzzing:
afl-fuzz -i input_dir -o output_dir ./xpdf @@
3.3 结果分析
- 通常几分钟后就会出现crash
- 检查output_dir/crashes目录中的崩溃样本
- 可以测试这些样本是否确实会导致Xpdf崩溃
4. 漏洞分析与调试
4.1 准备调试环境
- 删除之前插桩的Xpdf
- 重新编译正常且可调试的Xpdf版本(使用-g选项)
4.2 崩溃分析
- 使用gdb加载崩溃样本:
gdb --args ./xpdf crash_sample - 运行程序直到崩溃
- 查看函数调用栈(backtrace)
4.3 漏洞原理
通过分析发现存在无限递归问题,调用链如下:
Object::fetch --> XRef::fetch --> Parser::getObj --> Parser::makeStream --> Object::dictLookup --> Dict::lookup --> Object::fetch
关键点:
- 涉及PDF文档结构中的Catalog和交叉引用表(xref table)
- Catalog是PDF文档的根目录对象,负责指向文档的其他重要部分
- 交叉引用表(xref table)描述文件中的对象如何相互引用
4.4 调试技巧
- 在确定会循环的位置设置断点
- 连续执行几次(continue命令)
- 这样可以保证有循环节追踪的同时,程序不会立即崩溃
5. PDF文档结构相关知识
5.1 Catalog对象
- PDF文档结构中的重要对象
- PDF文档的根目录对象
- 位于PDF文件的最顶层
- 负责指向文档的其他重要部分
5.2 交叉引用表(xref table)
- 描述文件中的对象如何相互引用
- 包含所有对象的偏移量信息
- 是PDF文件解析的关键数据结构
5.3 页面处理流程
对于PDF中的每一页:
- 调用
catalog->getPage(page)获取页码 - 执行
Page::display,实际上是调用displaySlice输出
6. 漏洞修复方案
官方修复方法是在循环中添加限制,当循环达到一定次数时自动跳出,防止无限递归。
修复关键点:
- 添加循环计数器
- 设置最大递归深度
- 超过限制时返回错误或终止处理
7. 总结
通过本次fuzz实践,我们:
- 成功搭建了AFL++ fuzzing环境
- 对Xpdf进行了插桩编译
- 发现了导致崩溃的漏洞
- 通过调试分析了漏洞成因(无限递归)
- 了解了PDF文档的基本结构
- 学习了官方修复方案
这个案例展示了如何从fuzz发现崩溃到最终分析出漏洞原理的完整过程,对于学习软件安全测试和漏洞分析具有很好的参考价值。