AFL的入门学习

先贴上我参考的教程


实验环境

ubuntu 16.04(虚拟机) 内存分配4gb

afl 2.52b

AFL是什么

AFL(American Fuzzy Lop)是由安全研究员Michał Zalewski开发的一款基于覆盖引导(Coverage-guided)的模糊测试工具,它通过记录输入样本的代码覆盖率,从而调整输入样本以提高覆盖率,增加发现漏洞的概率。

我们可以在官方网站发现更多有用信息

AFL的工作流程

afl1

1
2
3
4
5
6
7
8
9
①从源码编译程序时进行插桩,以记录代码覆盖率(Code Coverage);

②选择一些输入文件,作为初始测试集加入输入队列(queue);

③将队列中的文件按一定的策略进行“突变”;

④如果经过变异文件更新了覆盖范围,则将其保留添加到队列中;

⑤上述过程会一直循环进行,期间触发了crash的文件会被记录下来。

AFL流程freebuf

下载AFL

下载指引

用afl-gcc编译源程序

  • 先写一个简单的c程序

我这里就直接照搬了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

int vuln(char *str)
{
int len = strlen(str);
if(str[0] == 'A' && len == 66)
{
raise(SIGSEGV);
//如果输入的字符串的首字符为A并且长度为66,则异常退出
}
else if(str[0] == 'F' && len == 6)
{
raise(SIGSEGV);
//如果输入的字符串的首字符为F并且长度为6,则异常退出
}
else
{
printf("it is good!\n");
}
return 0;
}

int main(int argc, char *argv[])
{
char buf[100]={0};
gets(buf);//存在栈溢出漏洞
printf(buf);//存在格式化字符串漏洞
vuln(buf);

return 0;
}

将这段代码程序命名为hello.c

  • 用afl-gcc编译
    1
    sudo afl-gcc -g -o hello hello.c

    同理 c++ 程序用 afl-g++ 编译

    对编译好的文件开始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 @@
    这里采用第一种,首先需要一个测试用例集testcase。输出集会自动生成
1
afl-fuzz -i /your_path/testcase -o /your_path/fuzz_out_file ./hello

常见参数及含义

  • -f参数表示:testcase的内容会作为afl_test的stdin
  • -m参数表示分配的内存空间
  • -i 指定测试样本的路径
  • -o 指定输出结果的路径
  • /dev/null 使错误信息不输出到屏幕
  • -t:设置程序运行超时值,单位为 ms
  • -M:运行主(Master) Fuzzer
  • -S:运行从属(Slave) Fuzzer

在虚拟机上一般会报错,需要根据提示设置一波core_pattern:

1
2
sudo su
echo core >/proc/sys/kernel/core_pattern

再次fuzz,即可出现afl界面
hello

对afl界面的简单分析

  • process timing

这里展示了当前fuzzer的运行时间、最近一次发现新执行路径的时间、最近一次崩溃的时间、最近一次超时的时间。

值得注意的是第2项,最近一次发现新路径的时间。如果由于目标二进制文件或者命令行参数出错,那么其执行路径应该是一直不变的,所以如果从fuzzing开始一直没有发现新的执行路径,那么就要考虑是否有二进制或者命令行参数错误的问题了。对于此状况,AFL也会智能地进行提醒

  • overall results

这里包括运行的总周期数、总路径数、崩溃次数、超时次数。

其中,总周期数可以用来作为何时停止fuzzing的参考。随着不断地fuzzing,周期数会不断增大,其颜色也会由洋红色,逐步变为黄色、蓝色、绿色。一般来说,当其变为绿色时,代表可执行的内容已经很少了,继续fuzzing下去也不会有什么新的发现了。此时,我们便可以通过Ctrl-C,中止当前的fuzzing

  • stage progress

这里包括正在测试的fuzzing策略、进度、目标的执行总次数、目标的执行速度

执行速度可以直观地反映当前跑的快不快,如果速度过慢,比如低于500次每秒,那么测试时间就会变得非常漫长。如果发生了这种情况,那么我们需要进一步调整优化我们的fuzzing

以上是简单的介绍,如果要看完整的可以查看官方文档

分析crash

  • 打开刚刚创建的fuzz_out文件夹
    1
    cd /your_path/fuzz_out_file
  • 使用xxd分析漏洞
    1
    xxd id:******,sig:**    ***********
    这样就完成了第一次对afl的探索,同样我们可以对开源程序进行fuzz用AFL编译开源软件

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!