前言
本篇文章主要是为网鼎杯线下赛做准备,不会涉及到AFL的原理,主要的方向为AFL的使用。
AFL-FUZZ介绍
AFL则是fuzzing的一个很好用的工具,全称是American Fuzzy Lop,由Google安全工程师Michał Zalewski开发的一款开源fuzzing测试工具,可以高效地对二进制程序进行fuzzing,挖掘可能存在的内存安全漏洞,如栈溢出、堆溢出、UAF、double free等。由于需要在相关代码处插桩,因此AFL主要用于对开源软件进行测试。当然配合QEMU等工具,也可对闭源二进制代码进行fuzzing,但执行效率会受到影响。
白盒下的FUZZ
1 |
|
大概流程:
首先是用afl-gcc编译源代码进行插桩,然后以测试文件为输入,然后启动afl-fuzz程序,将testcase作为程序的输入执行程序,afl会在这个testcase的基础上进行自动变异输入,使得程序产生crash,产生了crash就会被记录起来
编译插桩
首先是面对上面这类小文件时采取的方法就是直接进行编译
1 | afl-gcc -g -o test test.c |
但是面对编译项目时,大多会使用到Makefile。如果存在configure的话肯定是可以在里面直接进行修改,如果没有的话可以直接修改Makefile或者添加以下内容:
1 | CC=/path/to/afl/afl-gcc |
当然面对clang或者clang++的话也是一样的。
开始FUZZ
对那些可以直接从stdin读取输入的目标程序来说,语法如下:
1 | ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program […params…] |
对从文件读取输入的目标程序来说,要用“@@”,语法如下:
1 | ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@ |
而对于这里命令为:afl-fuzz -i input_dir -o output_dir ./test
其中-i选项时输入测试文件的目录,-o选项时输出结果文件的目录。
对于这个简单的例子,测试文件只需要随便输入点东西就行,这里选择输入hello
一般会出现上图中的问题,解决办法就是
1 | sudo su |
上图就是AFL的界面,上面的内容根据前面的注释基本可以猜出来一二,不过跑了十分钟只跑出了五处crash就挺离谱的,这个跑的结果与testcase和电脑性能以及运气都有一定关系。
分析crashes
id:000000,sig:06,src:000001,op:havoc,rep:128样例
1 | ➜ crashes xxd id:000000,sig:06,src:000001,op:havoc,rep:128 |
可以猜测为栈溢出
id:000001,sig:06,src:000001,op:havoc,rep:128样例
1 | ➜ crashes xxd id:000001,sig:06,src:000001,op:havoc,rep:128 |
一样的应该也是栈溢出导致的
id:000002,sig:11,src:000000,op:flip1,pos:1样例
1 | ➜ crashes xxd id:000002,sig:11,src:000000,op:flip1,pos:1 |
这里应该是格式化字符串漏洞引起的crash
id:000003,sig:11,src:000000,op:havoc,rep:64样例
1 | ➜ crashes xxd id:000003,sig:11,src:000000,op:havoc,rep:64 |
这里应该是以F开头且长度为6引起的crash
id:000004,sig:11,src:000002,op:havoc,rep:8样例
1 | ➜ crashes xxd id:000004,sig:11,src:000002,op:havoc,rep:8 |
这里应该是以A开头并且长度为66引起的crash
总结
可以看到上面五个样例基本覆盖了源码中存在的漏洞。
黑盒下的FUZZ
黑盒模式需要使用qemu_mode,所以最好从开始就使用源码进行编译,这里可能会出现很多问题,大多都可以在网上搜到解决办法
这里直接使用以下命令进行编译。
1 | gcc -g ./test.c -o test |
开始FUZZ
这里的FUZZ选项略有不同,需要加上-Q选项。
1 | afl-fuzz -i ./input_dir -o ./output_dir -Q ./test |
虽然可以看到这里被保存的crashes有6个,比上面的还多一个,但是看total crashes远远少于上面的。可以看出来用qemu的性能远远小于插桩的。
这里就不再分析输出的crashes文件了。
文件读取输入的情况
首先做以下准备
1 | ➜ input_dir mkdir file |
随后直接进行fuzz
1 | ../afl-fuzz -i ./input_dir/file -o ./output_dir -Q ./readelf -a @@ |
跑了十分钟一次crash都没有的,当然跑再久应该也是一样的,这里就不再继续跑了。
参考资料:
https://xz.aliyun.com/t/4314
https://www.cjovi.icu/fuzzing/1138.html