本文主要是介绍Fuzzing-101 Exercises,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 前言
- AFL++ 环境搭建
- Exercise-1 Xpdf CVE-2019-13288
- Xpdf 环境搭建
- 种子库获取 && 前期准备
- 开始 fuzz && 分析 crash
- 总结
- Exercise-2 libexif CVE-2009-3895/CVE-2012-2836
- libexif 环境搭建
- 种子库获取 && 前期准备
- 开始 fuzz && 分析 crash
- 总结
前言
笔者将 AFL 源码审计的差不多了,打算接着 Fuzzing-101 这个项目来练练手,学习一下 Fuzz 工具的使用
AFL++ 环境搭建
sudo apt install llvm
sudo apt install clang
git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
make
sudo make install
如果想要使用 trace-pc-guard 模式,则需要 llvm 版本为 13+
Exercise-1 Xpdf CVE-2019-13288
Xpdf 是一个免费的 pdf 查看器和工具包,具体文本提取、图像转换等功能
CVE-2019-13288 是 Xpdf 中的一个漏洞,可以通过构造恶意文件,使得 Parser.cc 中的 Parser::getObj() 函数被循环调用,从而导致栈内存耗尽。攻击者可以利用该漏洞实现 DOS 攻击
Xpdf 环境搭建
cd $HOME
mkdir fuzzing_xpdf && cd fuzzing_xpdf/wget https://dl.xpdfreader.com/old/xpdf-3.02.tar.gz
tar -xvzf xpdf-3.02.tar.gz
cd xpdf-3.02
在 xpdf-3.02 目录下,存在一个 configure,其是用来生成 Makefile 的:

这里我们设置编译时采用 afl-clang-fast,以此来进行插桩:
export CC=/home/xiaozaya/fuzz/AFLplusplus/afl-clang-fast
export CXX=/home/xiaozaya/fuzz/AFLplusplus/afl-clang-fast++
插桩编译 xpdf:编译好的二进制程序在 $HOME/fuzzing_xpdf/install/bin 目录下
./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
sudo make install
根据插桩关键字 __sanitizer_cov 确认下是否成功插桩:
cd $HOME/fuzzing_xpdf/install/bin
strings pdftotext | grep __sanitizer_cov
结果如下,可以看到我们已经成功完成插桩编译:

种子库获取 && 前期准备
在笔者看来,种子库是 fuzz 效率的关键或者决定性因素,如果编写好的种子是一门艺术。当然这也得不断积累,但是笔者刚刚入门,这里仅仅只是为了熟练下工具的使用,所以这里按照实验说明是直接下载别人的种子
cd $HOME/fuzzing_xpdf
mkdir pdf_examples && cd pdf_examples
wget https://github.com/mozilla/pdf.js-sample-files/raw/master/helloworld.pdf
wget http://www.africau.edu/images/default/sample.pdf
wget https://www.melbpc.org.au/wp-content/uploads/2017/10/small-example-pdf-file.pdf
这里需要注意的时,helloworld.pdf 这个文件所在的项目已经没有了。所以这里得单独下载:
git clone https://github.com/mozilla/pdf.js-sample-files.git
然后第二个文件 sample.pdf 也找不到了,所以最后找到的种子如下:

测试下种子是否可用:利用 pdfinfo 查看下 helloworld.pdf 的信息
$HOME/fuzzing_xpdf/install/bin/pdfinfo -box -meta $HOME/fuzzing_xpdf/pdf_examples/helloworld.pdf

然后关闭系统的核心转储,防止 fuzz 过程中出现 crash 导致程序崩溃中止
sudo su
echo core >/proc/sys/kernel/core_pattern
exit
开始 fuzz && 分析 crash
使用如下命令开始 fuzz:
$HOME/fuzz/AFLplusplus/afl-fuzz -i $HOME/fuzzing_xpdf/pdf_examples/ -o $HOME/fuzzing_xpdf/out/ -M fuzzer1 -- $HOME/fuzzing_xpdf/install/bin/pdftotext @@ $HOME/fuzzing_xpdf/output
相关路径可以视情况而修改
参数说明:
-i in_dir:指定输入文件夹,即种子库-o out_dir:指定输出文件夹,存放fuzz过程中的一些信息-M fuzzer_name:并行fuzz,指定主fuzzer。可以使用-S指定从fuzzer,但是输出路径要保持一致--:分隔符,后面跟测试目标@@:表示测试目标的输入是文件,不加代表是stdin
这里可以使用 -S 指定 fuzzer2 进行并行 fuzz

crash 分析
笔者跑了 20 多分钟,最后有 5 个 crash,整体还是不错的

最后导致 crash 的测试用例在输出目录的 crashes 文件夹下:

删除插桩编译的目标文件,然后重新利用 gcc 编译:
sudo rm $HOME/fuzzing_xpdf/install/ -rf
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean
CFLAGS="-g -O0" CXXFLAGS="-g -O0" ./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
sudo make install
然后就可以用 gdb 调试了
cd $HOME/fuzzing_xpdf/install/bin/
gdb pdftotext
set args /home/xiaozaya/fuzzing_xpdf/out/fuzzer1/crashes/id:000000,sig:11,src:000658,time:279572,execs:105141,op:havoc,rep:11
r
此时程序崩溃在 _int_malloc 的一个 push rbx 指令处,注意此时的 rsp

可以看到这里的 rsp 已经到达栈顶边界了
通过 bt 回溯看下函数调用链:可以看到一直在循环调用
总结
主要就简单的学习了下 AFL++ 的基本使用
- 使用
afl-clang-fast对目标程序进行插桩编译 - 准备种子库
afl-fuzz直接fuzz@@指明输入为文件
gdb调试分析crash
Exercise-2 libexif CVE-2009-3895/CVE-2012-2836
libexif 是一个用于解析、编辑和保存 EXIF 数据的库
EXIF:可交换图像文件格式,是专门为数码相机的照片设计的,可以记录数码照片的属性信息和拍摄数据
CVE-2009-3895 是一个堆溢出漏洞,发生在 exif-data.c 文件下的 exif_data_load_data 函数中
CVE-2012-2836 是一个越界读漏洞,发生在 exif-entry.c 文件下的 xif_entry_fix function 函数中
libexif 环境搭建
cd $HOME
mkdir fuzzing_libexif && cd fuzzing_libexif/
wget https://github.com/libexif/libexif/archive/refs/tags/libexif-0_6_14-release.tar.gz
tar -xzvf libexif-0_6_14-release.tar.gz
按照一些必要的依赖和库:
sudo apt-get install autopoint libtool gettext libpopt-dev
然后生成 configure 程序:
cd libexif-libexif-0_6_14-release
autoreconf -fvi
这里设置一下 $CC 为 afl-clang-fast 实现插桩编译

export CC=/home/xiaozaya/fuzz/AFLplusplus/afl-clang-fast
然后进行插桩编译:生成的文件在 $HOME/fuzzing_libexif/install 目录下
./configure --enable-shared=no --prefix="$HOME/fuzzing_libexif/install/"
make
make install
可以看到插桩编译成功:

种子库获取 && 前期准备
这里值得注意的是这里的目标是一个链接库,其无法直接执行,所以我们得找一个可以调用该库的程序。其中 libexif 官网 就提供了 fuzz 的目标程序。然后该实验本身也提供了,这里就直接用
cd $HOME/fuzzing_libexif
wget https://github.com/libexif/exif/archive/refs/tags/exif-0_6_15-release.tar.gz
tar -xzvf exif-0_6_15-release.tar.gz
然后安装一下就行了,注意用 PKG_CONFIG_PATH 指定一下链接库的位置,最后生成的二进制文件同样在 instball 目录下,只是存放在了 bin 子目录下
cd exif-exif-0_6_15-release/
autoreconf -fvi
./configure --enable-shared=no --prefix="$HOME/fuzzing_libexif/install/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig
make
sudo make install
最后可以看到成功插桩编译:

准备种子语料库
程序本身是解析 EXIF 文件的,所以种子找一些 EXIF 文件就好了。可以找一些 EXIF 文件生成器生成,这里直接用实验给的
cd $HOME/fuzzing_libexif
wget https://github.com/ianare/exif-samples/archive/refs/heads/master.zip
unzip master.zip
简单测试一下:
$HOME/fuzzing_libexif/install/bin/exif $HOME/fuzzing_libexif/exif-samples-master/jpg/Canon_40D_photoshop_import.jpg

开始 fuzz && 分析 crash
$HOME/fuzz/AFLplusplus/afl-fuzz -i $HOME/fuzzing_libexif/exif-samples-master/jpg/ -o $HOME/fuzzing_libexif/out/ -M fuzzer1 -s 123 -- $HOME/fuzzing_libexif/install/bin/exif @@
-s seed:使用固定的随机种子【主要就是为了复现用的】
crash 分析
跑了 20 多分钟,共触发了 14 次 crash

这里其实也可以直接用 gdb 调试,而不一定去重新编译非插桩代码
这里 crash 发生在 exif_data_load_data 函数中,应该是 CVE-2009-3895

另外一个漏洞好像没有跑出来
总结
通过这个实验学习到了如何对链接库进行 fuzz:
- 对链接库进行插桩编译
- 寻找一个调用该库的程序,并对其进行插桩编译
这篇关于Fuzzing-101 Exercises的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!