AFL++ 挖掘ImageMagick

安装AFL++

方便起见,直接用官方提供的docker镜像,两条命令即可,docker使用的是ubuntu20的版本

1
2
docker pull aflplusplus/aflplusplus
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus

我这里使用的是:

1
docker run -ti --privileged=true -v /root/fuzz:/root/fuzz aflplusplus/aflplusplus

进去之后再给apt换个源

1
vim /etc/apt/sources.list
1
2
3
4
5
6
7
8
9
10
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal universe
deb http://mirrors.aliyun.com/ubuntu/ focal-updates universe
deb http://mirrors.aliyun.com/ubuntu/ focal multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-security universe
deb http://mirrors.aliyun.com/ubuntu/ focal-security multiverse

wq保存后,再apt update

ImageMagick安装

ImageMagick是一款免费开源的图片编辑软件,可以通过命令行就完成一些图片转换的操作,比如jpg -> png

使用以下命令进行下载、编译和安装

afl-clang-lto/afl-clang-lto++是clang/clang++ 11+以上版本使用的插桩方式

1
2
3
4
git clone https://github.com/ImageMagick/ImageMagick.git
cd ImageMagick/
CC="afl-clang-lto" CXX="afl-clang-lto++" ./configure --disable-shared
AFL_USE_ASAN=1 make -j8

--disable-shared选项表示禁止构建共享库,libz.so.1被编译进了目标程序中

完成之后,在utilities 目录下会生成magick

用以下命令进行并行fuzz,使用-M指定一个主fuzzer,-S指定多个从fuzzer,使用screen命令来运行,防止终端断开连接导致fuzz中断

1
2
3
screen AFL_MAP_SIZE=271312 afl-fuzz -D -i ../../png/ -o output1/ -M fuzzer01 -m none ./magick convert @@ out.jpg
screen AFL_MAP_SIZE=271312 afl-fuzz -D -i ../../png/ -o output1/ -S fuzzer02 -m none ./magick convert @@ out.jpg
screen AFL_MAP_SIZE=271312 afl-fuzz -D -i ../../png/ -o output1/ -S fuzzer03 -m none ./magick convert @@ out.jpg

参数说明:

  • -i:指定测试样本所在目录;
  • -o:指定测试结果存放目录(这里是一个同步目录,并行测试中所有的Fuzzer将相互协作,在找到新的代码路径时,相互传递新的测试用例);
  • -M:运行主(Master) Fuzzer;
  • -S:运行从属(Slave) Fuzzer;
  • -m:最大运行内存,单位为 MB(设置none,对内存不做限制);

查看fuzzer

afl++有自带的afl-whatsup工具,可以查看每个fuzzer的运行状态和总体运行概况

1
afl-whatsup -d ./output1/

需要注意的是,ImageMagick 会在/tmp 目录下生成临时文件,积累过多的话就会导致fuzzer停下来,可以使用以下脚本进行删除

rm_magick.py

1
2
3
4
5
6
7
8
9
10
11
12
import os
import time
if __name__ == '__main__':
while True:
file_list = os.listdir('/tmp')
for file_index in file_list:
if file_index.startswith('magick'):
try:
os.remove('/tmp/' + file_index)
except:
pass
time.sleep(0.1)
1
screen python rm_magick.py

最后

先让它跑几天再看吧。


跑了快6天了,上线看一看。

fuzzer02和fuzzer03都出现crash了,上一个crash都是在4天以前,进入screen看一下。

既然出现了crash,那还得验证一下,因为也可能是误报

把crash文件拷出来

1
cp ./output1/fuzzer02/crashes/id:000001,sig:06,sync:fuzzer01,src:001520 2.png

然后先手动把crash文件喂给程序

1
./magick convert ./2.png 1.jpg

谷歌搜索一下,看看能得到啥信息,关键词SUMMARY: AddressSanitizer: UNKNOWN SIGNAL

这个ASAN结果看起来跟我们的类似,但下面作者回复用gdb调试没发现啥异常,那pwn手肯定得自己调试一波了。ASAN把函数调用关系已经返回给我们了,我们只要在关键函数下断点跑起来看看就行。

调试后发现程序在strcpy处死掉了

根据这个异常signal SIGBUS, Bus error,搜索一波,网上的解释都是

SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。

1
vmovdqu ymmword ptr [rdi], ymm3

上面这个是个很少见的指令,好像是处理浮点数的,也可以看看ymm3寄存器存了啥,知识盲区。

大概是把ymm3的内容放到rdi地址处,手动看看rdi地址处的内容,地址无法访问。

1
2
x/20gx 0x7ffff2be3000
0x7ffff2be3000: Cannot access memory at address 0x7ffff2be3000

那么就vmmap看看这个虚拟地址是哪一部分的内容

搜了搜/dev/shm,说是tmpfs,这里面的文件不是在硬盘上而是存在内存里的,不是很了解。

太菜了,调试也没发现啥有用的信息,先就此作罢吧。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!