dig into the afl
本文最后更新于:2023年12月28日 晚上
0x0:写在所有之前
在笔者看来,fuzz无疑是一个天才的想法,通过自动化的大量的随机数据测试,进行漏洞挖掘。
笔者一直很想学习这一方面的知识,在粗略的拜读完Fuzzing: A Survey for Roadmap之后,恰好暑假也有点空闲时间(主要是放了两礼拜假什么也没干有点良心不安),便打算从afl入手来学习fuzz。
0x1:初探
下载安装什么的网上可以自己找捏wakuwaku
首先呢可以自己先随遍写一些测试用例
1 |
|
分别用gcc和afl-gcc编译
1 |
|
然后用ida打开看看这两个elf文件有什么不同
可以看到afl_test里面出现了许多奇怪的东西,这其实就是afl-gcc在编译时对测试源码进行了插桩(主要是**__afl_maby_log**函数)
这些被插入的桩总的来讲类似于传感器,实现对branch、edge(分支、边缘)覆盖率的捕获和分支点的统计,在后续的fuzz测试中会根据这些反馈信息进行新的路径探索和测试。(其实铸币笔者也刚刚在看afl源码,又回到了被源码支配的日子了呜呜呜)
接下来可以试着来真正fuzz一下这个test
先搞两个空文件夹存放输入样例和输出样例,fuzz_in里面touch 一个testcase随便写点什么。
1 |
|
第一次尝试可能会报错需要设置一下core_pattern
1 |
|
然后就可以愉快的afl_fuzz啦
进去后可以看到这样一个界面,相信大家英文都比我好,各种参数的含义korey看得懂得各位看官老爷也一定看懂嘻嘻。
由于铸币笔者只能用垃圾笔记本跑(乐色13900h),所以跑了大概一个小时跑出来了8个crash
接下来便是进到fuzz_out中看看每个crash是什么样的
1 |
|
crash0满足了buf[0] = ‘A’且len = 6
crash1满足了buf[1] = ‘F’且len = 66
crash2因为gets函数造成了栈溢出
遗憾的是buf[2] = ‘L’且len = 666的crash并未触发
之后便可以使用gdb将test文件和crash样例组合调试
1 |
|
用bt回溯可以看到stack smashing,造成栈溢出了
0x2:Fuzzing 101
这是个github上的项目,专门来帮助那些想要把fuzz应用于实战的带手子们。
项目中有十分详细的步骤,笔者就不在此赘述。笔者仅在此记录一些收获
exercise 1:Xpdf
第一个example是 CVE-2019-13288
在version 4.01.01的xpdf中,Parser.cc中的Parser::getObj()函数将会被无限调用导致内存耗尽,最终使程序崩溃,达到DoS攻击的效果。
感觉afl++比afl好用点
【-M】:主fuzzer,配合【-S】多开从属fuzzer效率可以提高
当输入为文件时,需要使用【@@】,否则为标准输入
插桩完后恢复成正常的gcc编译
1 |
|
exercise 2:libexif
在version 0.6.14 的libexif中,存在heap buffer overflow CVE-2009-3895以及out-of-bounds readCVE-2012-2836
这边插桩时使用的是afl-clang-lto
但libexif只是一个解析、保存、编辑exif数据的库,所以还要有相应的可执行文件(exif,编译的时候制定一下链接库文件夹)才能正常实现功能
就最后的调试而言,项目中使用的eclipse,具有图形化界面,笔者还是GDB用的习惯,直接
gdb –args 指定参数就行了
exercise 3:tcpdump
目前为止最折磨的一集
在version 4.9.2的 Tcpdump中,BOOTP协议数据包可以触发out-of-bouds Read,其实也算是overflow的一种 CVE-2017-13028
这次采用速度更快的afl-clang-lto(但nmd还是fuzz了10个小时才出来8个crash,不过一看hollk师傅的博客,用afl-clang-fast15个小时出一个crash,心里突然平衡了一点)
且在编译tcpdump和所对应的动态链接库时,加入了ASAN选项
ASAN(Address Sanitizer)是针对 C/C++ 的快速内存错误检测工具,在运行时检测 C/C++ 代码中的多种内存错误
铸币笔者也不是很懂,附带一个官方说明书AddressSanitizer — Clang 18.0.0git documentation (llvm.org)
后面执行运行tcpdump就能直接看到报错,感觉还是挺方便的,就是ASAN运行时所需内存有点大,fuzz的时候要加上 -m none 的参数解除内存限制
贴个图意思一下
exercise 4:LibTiff
逐渐熟练,笑
前面还是用ASAN和AFL++进行一个fuzz操作
在此次exercise中,项目作者用到了lcov,一个基于GCC代码覆盖测试工具gcov的图形前端
在编译的时候
1 |
|
编译完成后,进入tiff文件夹
1 |
|
笔者这边把前10个crash试了试,感觉代码覆盖率不是很理想
exercise 5:LibXml2
难绷,crash出不来就出不来吧
第一次完全没有看项目里的solution,自己解决,编译的时候看缺了个Python.h的头文件还自己编译了一个python(笑哭),好在最后成功跑起来了。
【 -x 】:指定字典
【 -D 】: 确定性突变
ASAN真好用,嘿嘿嘿嘿
exercise 6:GIMP
寄,我也不知道为什么fuzz101提供的demo会直接crash,怎么直接会有memory leak啊
试了好几个xcf文件都是这样
exercise 7: VLC
更抽象的一集
exercise 8: Adobe Reader
无源码直接fuzzelf文件