Fuzzing101-Xpdf
Fuzzing101-Xpdf
环境
插桩编译
1 | |
- 设置
CC与CXX环境变量,从而使用afl-clang-fast进行编译插桩 - 编辑配置文件,指定安装目录
编译过程如下图,途中会显示afl-cc++

Fuzzing
1 | |
-i参数指定需要fuzzing的目标文件-s参数指定使用的静态随机种子@@为生成文件样本进行输入,而不是标准输入output路径是pdftotext文件执行后所生成的静态文件
在fuzzing之前需要在命令行输入echo core >/proc/sys/kernel/core_pattern,为了能够存储程序崩溃的情况

fuzzing速度非常快,一分钟就出crash样本了

复现崩溃
会发现打印了十分多的信息,这是因为使用afl++插桩时会开启内存泄漏探测,因此在复现时应该使用原来的编译器编译

1 | |
-g参数增加调试信息-O0关闭优化方便调试
重新运行一次样本

调试
使用gdb分析一下崩溃的原因
- 首先使用
gdb加载pdftotext

- 其次,设置参数

- 最后运行,输入
bt查看栈回溯,可以看到会不断调用getObj函数,因此可能是不断递归造成的崩溃

函数调用流程
1 | |
源码分析
函数递归开头在getObj函数中处理流数据,会使用makeStream函数处理数据

通过dictLookup函数搜索Length获取流数据的长度

通过键值搜索对象,若是对象不为空则调用fetch函数

若对象是引用对象则会调用XRef::fetch函数,这里就是漏洞存在点,这里并没有判断引用的对象是否是自身。

在XRef::fetch内部又调用了getObj函数

通过源码分析发现pdf对象内部是可以调用间接对象的,但是代码没有判断当前对象与调用的间接对象是否是相同对象,那么则会发送crash样本发生的情况,会不断递归调用getObj函数
pdf相关知识
为了分析crash样本崩溃的原因需要掌握pdf相关知识
这个网站介绍的非常详细https://lazymind.me/2017/10/pdf-structure/,这里简单记录一下
PDF文档结构是由许多PDF对象组成PDF对象分为直接对象与间接对象直接对象类型
- 布尔类型
- 数值类型
- 字符串
- 名称
- 数组
- 字典
- 流对象
- 空对象
间接对象
1 | |
crash样本分析
下图是样本的部分数据流,可以发现在7 0 obj间接对象中又交叉引用了7 0 R即对象本身与源码分析的情况一致,间接对象本身引用了自身导致了递归调用

崩溃样本构造
一个正常pdf的例子

正常pdf的数据流

修改后的pdf的数据流

构造成功

参考链接
https://github.com/antonio-morales/Fuzzing101/tree/main/Exercise%201
https://github.com/zxyle/PDF-Explained/blob/master/chapter2.md
https://lazymind.me/2017/10/pdf-structure/
https://juejin.cn/post/7023691050757652494#heading-18
https://blog.csdn.net/fxbjye/article/details/115460327
https://lazymind.me/2017/10/pdf-structure/