AFL
一、简单测试
1 | int main(int argc, char const *argv[]) |
1.基础尝试
(1)白盒
①基础
首先使用简单的afl-clang-fast来编译
1 | afl-clang-fast ./test.c -z execstack -fno-stack-protector -no-pie -z norelro -o afl_test |
然后跑起来,速度大约是11.6k

大概跑了6分钟,出现了第一个crash,查看一下,是大小为0x76

然后蒸馏一下afl-tmin -i inputSeed -o outSeed programer

大小变为了0x2d,减去开始的4个字节,为0x29,再看看IDA反汇编出来的

可以看到确实距离rbp为0x28,多溢出一个字节就可以覆盖到rbp了。
此外设置的标志int v4也在buf上面,而非正常编译的先声明的更靠近栈底。
另外实际gdb调试的,其main函数栈不再是通过leave ret来返回了,而是直接add rsp 0x38,而rbp为0

main函数实际的返回地址距离buf为0x28倒是也能说的过去,就是不知道为什么要这么做。
②尝试__AFL_INIT()
在源码中加入__AFL_INIT(),参考:
sakuraのAFL源码全注释(二)-安全客 - 安全资讯平台 (anquanke.com)
AFL-Training学习记录-安全客 - 安全资讯平台 (anquanke.com)
sakura师傅介绍说,目的是为了在某些情况下可以减少操作系统、链接与libc内部执行程序的成本
iskindar师傅介绍说,这是采用Deferred initialization的方式来提高AFL的性能,大概提高1.5x,最合适的地方是放在read函数前。也就是下面这几行代码。
1 |
|
放入进去
1 |
|
之后正常编译
1 | afl-clang-fast ./test.c -z execstack -fno-stack-protector -no-pie -z norelro -o afl_test |
也相差无几,可能是程序太小,相关的libc库调用太少吧

发现crash之后蒸馏得到的和不加__AFL_INIT()是一样的。
③尝试__AFL_LOOP(1000)
persistent模式,常常用来fuzz某些无状态的API
iskindar师傅介绍说,对于一些无状态的API库,可以复用进程来测试多个测试样例,从而减少fork系统调用的使用,进而减少OS的开销。
- 状态:指的是交互过程中保存的会话信息,比如
cookie、session等
那么无状态的API指的就是在这个API里没有保存状态了。
先不使用__AFL_LOOP
1 |
|
库如下
1 |
|
编译加FUZZ
1 | afl-clang-fast ./testNoLoopAPI.c ./noStateAPI.c -z execstack -fno-stack-protector -no-pie -z norelro -o afl_API_noLoop_test |
开始运行之后会有(odd, check syntax!),但是运行一段时间后就没有了,不太知道为啥

最后大概五六分钟也能得到crash
加入__AFL_LOOP
1 |
|
然后编译FUZZ
1 | afl-clang-fast ./testAPI.c ./noStateAPI.c -z execstack -fno-stack-protector -no-pie -z norelro -o afl_API_test |
但是这个跑一个小时都没出结果,很奇怪,不知道为什么,难道说有read或者有比对值的代码
1 | if(*flag == 0x1234){ |
就代表是有状态的API吗
(2)黑盒
此外使用正常的gcc编译后,采用黑盒测试时
1 | afl-fuzz -Q -i in -o hei_out ./test |
速度下降一大截

不过还是能够发现crash,大概跑了十五六分钟。

可以看到大小是0x4f,减去标志的4个字节即为0x4b,与期待的大概0x39字节还是相差一点

此外黑盒好像没办法蒸馏
