AFL简要介绍:
AFL由lcamtuf所开发。通过对源码进行重新编译时进行插桩的方式自动产生测试用例来探索二进制程序内部新的执行路径。
简而言之,它采用了一个极其简单但是绝对可靠的,插桩代码导向的遗传算法。它使用一种自定义的边缘覆盖率来识别程序控制流的局部变化。
整个算法的逻辑结构如下:
也就是说,被选择出来的测试用例会进行周期性的删减,消除那些已经被更新的、更高覆盖率的废弃的测试用例,就这样反复测试。
AFL模式介绍:
基本的模式选择如上,而测试主要有两种形式:
一种是有源码并且使用afl-gcc编译通过的程序可以直接用afl-fuzz进行测试:如
即对二进制程序readelf进行测试,测试集来源于afl_in,而crashes以及queue等信息输出至afl—out。
第二种就是对没有源码的二进制程序而言,可以利用QEMU 的“user emulation”模式帮助建立独立特征,并允许调用者获得黑盒、闭源的二进制程序的插桩输出。
具体指令可以是:
当然如图可知,afl-gcc编译过的,不推荐使用这种模式。
这是因为QEMU使用basic blocks作为翻译单元,利用QEMU做instrumentation,启动很慢的QEMU mode同样使用了一个fork server,和编译期一样,通过把一个已经初始化好的进程镜像,直接拷贝到新的进程中。 所以相当于第一次翻译一个新的basic block,这肯定会有必要的延迟,为了解决这个问题AFL forkserver在emulator和父进程之间提供了一个信息管道。这个信息管道用来通知父进程新添加的blocks的地址,之后把这些blocks放到一个缓存中,以便直接复制到将来的子进程中。但这样处理之后,QEMU模式对目标程序造成2-5倍的减速。
注:QEMU的-Q模式,在afl的根目录下的qemu_mode,有一下build_qemu_support.sh,在终端运行即可,至于需要配置的库可以根据readme里介绍的进行配置编译安装即可。
如在运行时-Q仍无法正常运行,且报错如下:
那么这个时候需要将AFL的根目录添加至系统环境变量即可解决:
如:export AFL_PATH=/home/downloads/afl-2.52b