📖学习路线 AFL++ -> LibAFL -> libgoafl
安装和使用以及基本概念
arch一键allin就行。
afl++是一个基于afl的改进版开源模糊测试工具。对于fuzz来说,分为有源码和无源码的版本。afl基于clang实现了一个定制的编译器afl-clang
系列。afl-clang能通过编译时插桩来为afl提供代码覆盖率监控等功能。同时它还有qemu mode能提供无源码fuzz,
有一个afl-training项目可以帮我们上手掌握相关的内容,这里以quckstart为例简单介绍afl++执行的入门流程。
Quickstart
在有源码(c)的情况下,我们要使用CC=afl-clang-fast
来编译我们需要测试的程序。在afl编译器完成插桩编译之后,执行afl-fuzz -i inputs -o out ./vulnerable
即可。-i
指定了输入种子的文件夹,-o
指定了崩溃输出的文件夹。快速启动就这么容易。我们应当看到如下内容:
如果不做任何处理,afl默认会对标准输入进行fuzz。
Harness
harness的英文正式翻译是“系带/(马)挽具”或是“控制/利用…的动力”。在fuzz中指的是一个“接口”。AFL并不知道我们具体要测试什么函数,也不知道函数的输入是什么样的如何输入,因此这就需要我们编写harness。
对于fuzz一个接口/函数需要准备什么,afl-training给出了以下三条:
-
代码需要是可执行的——需要编译成一个程序。
-
为了让 AFL 有效工作,代码需要被插桩(instrumented)——所以我们必须用 afl-clang-fast、afl-clang 或 afl-gcc 之一进行编译。
-
为了让 AFL 生成的数据真正测试到库函数,我们需要编写一个 harness,它能接收外部输入并传递给库。这可以通过命令行指定的文件,或者直接从标准输入(stdin)读取。
所以我们编写harness的过程,其实是想办法让标准输入缓冲区和目标函数对接,并且在终端更加用户友好。对于一个标准的harness示例,我们现在要尝试fuzz自定义的lib_echo
和lib_mul
函数。
1 |
|
接下来我们只需要调用
1 | afl-fuzz -i in -o out ./harness echo |
或者
1 | afl-fuzz -i in -o out ./harness mul |
就能让afl对这两个函数做fuzz。而这个主函数就是我们写的harness。
注意事项
一般来说,终端执行afl-fuzz如果报错它会输出错误原因的。
常见的参数
@@: 占位符
https://cloud.tencent.com/developer/article/2483298
qemu纯二进制下,关于fuzz的调优。比如设置afl入口点,选择要覆盖的动态库,设定code起止地址。也就是说我们通过逆向+设定一大堆环境变量也可以实现针对性的fuzz
原理
这是afl++的架构图:
实战尝试
LibAFL
LibAFL是一个用rust编写的fuzzing工具,提供了高自定义的很多工具用于构建自己的fuzz环境。
golibafl
fuzz101
这是一套fuzz的教程