ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AFL++初探-手把手Fuzz一个PDF解析器

2021-09-07 13:02:22  阅读:359  来源: 互联网

标签:AFL 解析器 xpdf ++ install pdf HOME fuzzing


CVE-2019-13288

目前漏洞在正式版本已经被修复,本文章仅供学习Fuzz过程,不存在漏洞利用的内容

这是一个pdf查看器的漏洞,可能通过精心制作的文件导致无限递归,由于程序中每个被调用的函数都会在栈上分配一个栈帧,如果一个函数被递归调用太多次,就会导致栈内存耗尽和程序崩溃。因此,远程攻击者可以利用它进行 DoS 攻击。

练习目的

  • 使用检测编译目标应用程序
  • 运行Fuzzer (afl-fuzz)
  • 使用调试器 (GDB) 对崩溃进行分类

环境构建

环境使用Ubuntu 20.04.2 LTS,尽量在物理机进行Fuzz而不是虚拟机来获取更多的性能(当然这只是性能方面,对Fuzz最终结果不会产生影响)

VMWare 镜像下载地址:

UbuntuVMware.zip

此 VM 的用户名/密码是fuzz/ fuzz

下载并构建

首先为Fuzz目标创建一个新目录:

cd $HOME
mkdir fuzzing_xpdf && cd fuzzing_xpdf/

可能需要安装一些额外的工具(即 make 和 gcc)

sudo apt install build-essential

下载 Xpdf 3.02:

wget https://dl.xpdfreader.com/old/xpdf-3.02.tar.gz
tar -xvzf xpdf-3.02.tar.gz

构建 Xpdf:

cd xpdf-3.02
sudo apt update && sudo apt install -y build-essential gcc
./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
make install

现在可以开始测试Xpdf。首先,需要下载一些 PDF 示例:

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

可以使用以下命令测试 pdfinfo 二进制文件:

$HOME/fuzzing_xpdf/install/bin/pdfinfo -box -meta $HOME/fuzzing_xpdf/pdf_examples/helloworld.pdf

结果如下:

安装AFLplusplus

对于本实验,使用最新版本的AFL++,GitHub链接如下:

GitHub - AFLplusplus/AFLplusplus: The fuzzer afl++ is afl with community patches, qemu 5.1 upgrade, collision-free coverage, enhanced laf-intel & redqueen, AFLfast++ power schedules, MOpt mutators, unicorn_mode, and a lot more!

  • 推荐本地安装

    安装依赖:

    sudo apt-get update
    sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
    sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang 
    sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
    

    构建 AFL++(国内网络原因安装时间较长,耐心等待):

    cd $HOME
    git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
    export LLVM_CONFIG="llvm-config-11"
    make distrib
    sudo make install
    

    可能会出现qemu_mode、frida和unicorn安装失败的情况,多数原因是因为网络,这几个功能是用于二进制文件黑盒Fuzz,可以暂时先不用管,从源码构建Fuzz不需要这几个功能

  • 也可以使用docker构建,性能比较低:

    安装docker:

    sudo apt install docker
    

    拉取镜像:

    docker pull aflplusplus/aflplusplus
    

    启动 AFLPlusPlus docker 容器:

    docker run -ti -v $HOME:/home aflplusplus/aflplusplus
    

    然后输入

    export $HOME="/home"
    

安装成功后,应该可以使用afl-fuzz了,输入afl-fuzz命令可以看到如下内容:

使用AFL++开始Fuzz

当源代码可用时,AFL 可以使用检测,在每个基本块(函数、循环等)的开头插入函数调用。为了为目标应用程序启用检测,所以需要使用 AFL 的编译器编译代码。简单来说就是需要使用afl编译器来编译目标。

首先,清理所有以前编译的目标文件和可执行文件:

rm -r $HOME/fuzzing_xpdf/install
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean

现在将使用afl-clang-fast编译器构建 xpdf :

export LLVM_CONFIG="llvm-config-11"
CC=$HOME/AFLplusplus/afl-clang-fast CXX=$HOME/AFLplusplus/afl-clang-fast++ ./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
make install

现在可以使用以下命令运行Fuzz:

afl-fuzz -i $HOME/fuzzing_xpdf/pdf_examples/ -o $HOME/fuzzing_xpdf/out/ -s 123 -- $HOME/fuzzing_xpdf/install/bin/pdftotext @@ $HOME/fuzzing_xpdf/output

执行参数说明:

  • -i:表示输入文件目录
  • -o:表示 AFL++ 将存储变异文件的目录
  • -s:表示要使用的静态随机种子(AFL 使用非确定性测试算法,因此两个Fuzz会话永远不会相同。这就是为什么设置固定种子 -s 123的原因。用以保证Fuzz结果和示例相同。)
  • @@:是占位符目标的命令行,AFL 将用每个输入文件名替换它

如果收到「Hmm, your system is configured to send core dump notifications to an external utility...」类似的命令,执行以下操作关闭核心转储:

sudo su
echo core >/proc/sys/kernel/core_pattern
exit

几分钟后,应该会看到如下内容:

可以看到红色的uniq crashes值,显示找到的唯一崩溃的数量。可以在$HOME/fuzzing_xpdf/out/目录中找到这些崩溃文件。一旦发现第一个崩溃,就可以使用control+c停止 fuzzer。

什么时候可以停止fuzzer?其中一个指标可以参考cycles done 的数字颜色,依次会出现洋葱红色,黄色,蓝色,绿色,变成绿色时就很难产生新的crash文件了。

复现崩溃和修复漏洞

复现崩溃

$HOME/fuzzing_xpdf/out/目录中找到崩溃对应的文件。文件名类似于id:000000,sig:11,src:001504+000002,time:924544,op:splice,rep:16

将此文件作为输入传递给 pdftotext 二进制文件(如果提示无法打开文件,将文件名称改为xxx.pdf再尝试)

$HOME/fuzzing_xpdf/install/bin/pdftotext '$HOME/fuzzing_xpdf/out/default/crashes/<your_filename>' $HOME/fuzzing_xpdf/output

它会导致分段错误并导致程序崩溃:

使用 gdb 找出程序因该输入而崩溃的原因

首先,需要使用调试信息重建 Xpdf 以获得符号堆栈跟踪:

rm -r $HOME/fuzzing_xpdf/install
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean
CFLAGS="-g -O0" CXXFLAGS="-g -O0" ./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
make install

现在,可以运行 GDB:

gdb --args $HOME/fuzzing_xpdf/install/bin/pdftotext $HOME/fuzzing_xpdf/out/default/crashes/<your_filename> $HOME/fuzzing_xpdf/output

然后,在 GDB 中输入:

run

如果一切顺利,应该会看到以下输出:

然后输入bt以获取栈回溯:

滚动调用堆栈,将看到Parser::getObj方法的许多调用,这些调用似乎表示无限递归,如上图的红框所示。

修复问题

下载4.02版本代码,对比Parser.cc,可以看到此漏洞被修复:

总结

  • 通过复现一个漏洞,学习AFL++的基本使用方法,并使用GDB查看crash原因
  • 后续还有AFL++Fuzz学习的笔记会同步更新到博客

参考文章

标签:AFL,解析器,xpdf,++,install,pdf,HOME,fuzzing
来源: https://www.cnblogs.com/unr4v31/p/15237728.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有