比较有名的Fuzz工具

Fuzz流程

AFL原理

fork-server
作用:如上图,相当于目标程序和afl-fuzz的中间媒介,相当于一个传递测试用例和执行结果的管道。
优化 AFL 在模糊测试中执行目标程序的方式,从而加速测试过程并降低资源消耗。
主要原理:fork-server在程序启动后,会将其保留在内存中,并提供一个通信接口,这样之后AFL每次生成测试用例向目标程序发送时都需要重新加载和初始化目标程序所带来的开销。从而可以达到减少启动时间和资源消耗、通信和控制、效率提升的作用。
实现细节:AFL通过在启动目标程序时创建子进程(fork)来实现fork-server。,这个fork的功能是加载目标程序并等待AFL发送测试用例,然后通过管道或其他IPC(进程间通信)机制将测试用例发送给fork-server,然后frok-server会将测试用例发送给目标程序执行,并将执行结果返回给AFL。
确定性变异
- 位翻转
- 字节翻转
- 添加或删除字节
不确定性变异
- 随机数生成
- 基于系统时间的变异
- 从外部源(如文件、网络请求)获取的数据等。
AFL的Fuzz方式
- 开源软件:AFL软件进行编译的同时进行插桩,以方便Fuzz
- 闭源软件:配合QEMU直接对闭源的二进制代码进行Fuzz
术语
语料库
就是我们要从语料库中选择种子,语料库就是模糊测试数据的集合,种子就是其中的一个数据。
插桩
即在程序中的一些地方插入输出代码,来检测程序执行到了哪里。

特点

举例
int had_exec[100] = {0};
void a(){
had_exec[0] = 1; //(1)
//...
}
void b(){had_exec[1] = 1;}
void c(){had_exec[2] = 1;}
int main(){
//...
if (had_exec[0] = 1) //(2)
puts("function a had has been called");
}
AFL++ 的使用
安装:
sudo apt install afl++
git clone https://github.com/AFLplusplus/ASLplusplus.git
cd AFLplusplus
make
sudo make install
装到了ubantu的Fuzz-tools/AFLplusplus文件夹下,运行afl-fuzz --version查看版本
1、开源fuzz
测试程序test.c
#include <stdio.h>
#include <unistd.h>
int main(){
int a, idx;
char buf[100];
scanf("%d", &idx);
buf[idx] = '\0';
read(0, &a, 0x2);
if (a == 0xdead)
*(int *)0 = 0xdeadbeef;
return 0;
}
使用AFL++对test.c进行模糊测试
export AFL_USE_ASAN=1
afl-gcc -fsanitize=address test.c -o test # 使用afl-gcc对test.c进行编译

afl-as

afl-fuzz命令
afl-fuzz -i seed-dir -o out-dir -m none ./test
# 其他参数
-x # 指定字典,afl-fuzz过程中会将字典中的数据包含到-i的原始输入数据的变异样本当中去
-M 4 # 并行fuzzing实例数,此处并行4个fuzzing实例
-S # 指定随机种子,会影响随机变异输入。后面可以跟一个整数值或者文件路径。

结果
fuzz的结果输出到了out-dir/default/crashes目录下
cd /out-dir/defalut/crashes
ls # 即可查看到crash信息
./test.out < out-dir/default/crashes/id:000000,sig:11,src:000000,time:46,execs:10,op:quick,pos:0
2、闭源fuzz
运行qemu的编译脚本
qemu是基于路径信息覆盖制导的fuzz技术
分别为x86 arm 交叉编译的arm下

然后,假设test.c是测试程序
cd ../ # cd到AFLplusplus目录下
make install
gcc test.c -o test.out # 因为是闭源fuzz,所以我们不使用afl-gcc来编译
afl-fuzz -i input-dir/ -o output-dir/ -m none -Q ./test.out # -Q 就是使用qemu
crash分析
1、Sanitizer
如果不开启Sanitizer,即使程序存在漏洞,如果没有执行到有漏洞的代码段,那么程序也不会出现异常,这样Fuzz的效率就会大大降低。
开启Sanitizer后,虽然性能和时间上会有所损耗,但找bug的能力会大大提高。
2、AdressSanitizer



3、ThreadSanitizer
4、UndefinedBehaviorSanitizer
5、MemorySanitizer
AFL-Fuzz实战
1、测试对象:libpng
wget https://nchc.dl.sourceforge.net/project/libpng/libpng16/1.6.36/libpng-1.6.36.tar.xz # 下载libpng项目
tar xvf libpng-1.6.36.tar.gz # 解压
cd libpng-1.6.36
./autogen.sh
# 把编译器指定为afl的编译器
CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --enable-static # afl-clang是另一个编译器 # --enable-static 用于生成静态库,fuzz开源库时会需要
make -j4 # 编译
2、准备环境(准备种子)
获取官网提供的测试集作为输入
mkdir huzz_in fuzz_out
cd fuzz_in
wget http://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz
tar vxf afl_testcases.tgz
3、开始fuzz
afl-fuzz -i fuzz_in/png/full/images -o fuzz_out .libs/pngimage @@ # @@代表测试输入样本
总结
