Exercise 6 - GIMP

Exercise 6 - GIMP

一、实验背景

CVE-2016-4994是一个可以通过精心制作的XCF文件触发的Use-After-Free漏洞。当程序在释放指针后继续使用指针时,会发生释放错误。这可能会产生许多不良后果,从破坏有效数据到执行任意代码。

Use-After-Free漏洞(https://cwe.mitre.org/data/definitions/416.html)

持久模式

AFL持久模式基于进程内fuzzers: fuzzers利用单个进程,将代码注入目标进程并更改内存中的输入值。full -fuzz支持一种工作模式,它结合了进程内模糊测试的优点和更传统的多进程工具的健壮性:持久模式。在持久模式下,afl++在单个分叉进程中对目标进行多次模糊处理,而不是为每次执行模糊处理都创建一个新进程。该模式可将模糊测试速度提高20倍。

目标的基本结构如下

1
2
3
4
5
6
7
8
9
10
11
//Program initialization

while (__AFL_LOOP(10000)) {

/* Read input data. */
/* Call library code to be fuzzed. */
/* Reset state. */
}

//End of fuzzing

afl++持久模式(https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md)

二、实验目的

模糊GIMP图像编辑器。目标是在GIMP 2.8.16中找到CVE-2016-4994的崩溃/PoC

三、实验环境:

win10,VMware,Ubuntu 20.04.2 LTS(虚拟机用户名密码均为fuzz)

四、实验步骤

1、下载并构建目标

得到模糊目标,为要模糊化的项目创建一个新目录

1
2
cd $HOME
mkdir Fuzzing_gimp && cd Fuzzing_gimp

安装依赖项

1
sudo apt-get install build-essential libatk1.0-dev libfontconfig1-dev libcairo2-dev libgudev-1.0-0 libdbus-1-dev libdbus-glib-1-dev libexif-dev libxfixes-dev libgtk2.0-dev python2.7-dev libpango1.0-dev libglib2.0-dev zlib1g-dev intltool libbabl-dev

image

下载并构建GEGL 0.2(通用图形库)

1
2
wget https://download.gimp.org/pub/gegl/0.2/gegl-0.2.0.tar.bz2
tar xvf gegl-0.2.0.tar.bz2 && cd gegl-0.2.0

image

对源代码做两个小的修改

1
2
sed -i 's/CODEC_CAP_TRUNCATED/AV_CODEC_CAP_TRUNCATED/g' ./operations/external/ff-load.c
sed -i 's/CODEC_FLAG_TRUNCATED/AV_CODEC_FLAG_TRUNCATED/g' ./operations/external/ff-load.c

image

构建并安装Gegl-0.2

1
2
3
./configure --enable-debug --disable-glibtest  --without-vala --without-cairo --without-pango --without-pangocairo --without-gdk-pixbuf --without-lensfun --without-libjpeg --without-libpng --without-librsvg --without-openexr --without-sdl --without-libopenraw --without-jasper --without-graphviz --without-lua --without-libavformat --without-libv4l --without-libspiro --without-exiv2 --without-umfpack
make -j$(nproc)
sudo make install

image

image

image

如果在测试阶段看到一些错误消息,不要担心

下载并解压GIMP 2.8.16

1
2
3
cd ..
wget https://mirror.klaus-uwe.me/gimp/pub/gimp/v2.8/gimp-2.8.16.tar.bz2
tar xvf gimp-2.8.16.tar.bz2 && cd gimp-2.8.16/

image

使用afl-clang-lto作为编译器构建GIMP的时间(可能需要一些时间)

1
2
3
CC=afl-clang-lto CXX=afl-clang-lto++ PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$HOME/Fuzzing_gimp/gegl-0.2.0/ CFLAGS="-fsanitize=address" CXXFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" ./configure --disable-gtktest --disable-glibtest --disable-alsatest --disable-nls --without-libtiff --without-libjpeg --without-bzip2 --without-gs --without-libpng --without-libmng --without-libexif --without-aa --without-libxpm --without-webkit --without-librsvg --without-print --without-poppler --without-cairo-pdf --without-gvfs --without-libcurl --without-wmf --without-libjasper --without-alsa --without-gudev --disable-python --enable-gimp-console --without-mac-twain --without-script-fu --without-gudev --without-dbus --disable-mp --without-linux-input --without-xvfb-run --with-gif-compression=none --without-xmc --with-shm=none --enable-debug  --prefix="$HOME/Fuzzing_gimp/gimp-2.8.16/install"
make -j$(nproc)
make install

image

image

image

2、持久模式

有两种非常简单的方法:

第一个是修改’ ‘ app.c ‘ ‘文件,并将AFL_LOOP宏包含到for循环中

image

第二种方法是在’ ‘ xcf_load_invoker ‘ ‘函数中插入AFL_LOOP宏

Image1

虽然第一个允许我们针对不同的输入格式,第二个更快,我们将有更多的机会抓住错误。

下载第二个补丁在这里

2、种子语料库创建

建议创建多个GIMP项目并保存它们以获得多个.xcf示例,或者,可以将SampleInput.xcf文件复制到您的AFL输入文件夹中

image

3、fuzzing

由于该漏洞影响GIMP核心,可以通过删除不需要的插件来节省一些启动时间

1
rm ./install/lib/gimp/2.0/plug-ins/*

image

使用以下命令运行fuzzer

1
ASAN_OPTIONS=detect_leaks=0,abort_on_error=1,symbolize=0 afl-fuzz -i './afl_in' -o './afl_out' -D -t 100 -- ./install/bin/gimp-console-2.8 --verbose -d -f @@

image

笔记:

  • gimp-console-2.8是GIMP的控制台版本
  • 我建议启用确定性突变(-D)
  • 代码中还有一个无限循环的bug,所以我们需要设置一个较低的超时限制(例如-t 100)。此超时限制取决于您的机器功能,因此您需要根据具体情况对其进行调整

几分钟后可以看见有多个崩溃

Image2

4、Triage

ASan跟踪可能看起来像

image3

5、修复问题

修复这两个bug后重建目标,并检查PoC不再使程序崩溃

五、总结

通过这个实验,我了解了CVE-2016-4994漏洞,学会如何使用持久模式加快模糊测试,如何模糊交互/ GUI应用程序