0%

模糊测试

Fuzzing的概念

模糊测试(Fuzzing),是一种软件测试技术,通过向目标系统提供非预期的自动或半自动的生成随机数据输入并监视异常结果来发现软件或计算机系统漏洞。

AFL概念

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

AFL工作流程

  1. 从源码编译程序时进行插桩,以记录代码覆盖率(Code Coverage)
  2. 选择一些输入文件,作为初始测试集加入输入队列(queue)
  3. 将队列中的文件按一定的策略进行“突变”
  4. 如果经过变异文件更新了覆盖范围,则将其保留添加到队列中
  5. 上述过程会一直循环进行,期间触发了crash的文件会被记录下来

尝试AFL漏洞挖掘

  1. 下载并安装

    1. https://lcamtuf.coredump.cx/afl/下载
    2. make以及make install
  2. 在Fuzzing程序之前,我们需要对程序进行插桩:afl-gcc -g -o afl_test test.c

    test.c是我随便找的一个ctf的pwn题源码

    插桩:在AFL编译文件时候afl-gcc会在规定位置插入桩代码,可以理解为一个个的小断点(但是没有暂停功能),在后续fuzz的过程中会根据这些桩代码进行路径探索,测试等。使得测试覆盖面更广,更全面。

  3. 新建afl_in文件夹用于存放初始输入文件,新建afl_out文件夹用于保存Fuzzing测试结果

    初始输入文件为/afl-2.52b/testcases/others/text/hello_world.txt

  4. 进行测试:afl-fuzz -i afl_in -o afl_out ./afl_test

  5. 认识AFL状态窗口

    ① Process timing:Fuzzer运行时长、以及距离最近发现的路径、崩溃和挂起经过了多长时间。

    ② Overall results:Fuzzer当前状态的概述。

    ③ Cycle progress:我们输入队列的距离。

    ④ Map coverage:目标二进制文件中的插桩代码所观察到覆盖范围的细节。

    ⑤ Stage progress:Fuzzer现在正在执行的文件变异策略、执行次数和执行速度。

    ⑥ Findings in depth:有关我们找到的执行路径,异常和挂起数量的信息。

    ⑦ Fuzzing strategy yields:关于突变策略产生的最新行为和结果的详细信息。

    ⑧ Path geometry:有关Fuzzer找到的执行路径的信息。

    ⑨ CPU load:CPU利用率

  6. 我的测试结果如下图:

  7. afl_out文件夹结果如下图:


    • crashes:导致目标接收致命signal而崩溃的独特测试用例。

    • crashes/README.txt:保存了目标执行这些crash文件的命令行参数。

    • hangs:导致目标超时的独特测试用例。

    • queue:存放所有具有独特执行路径的测试用例。

    • fuzzer_stats:afl-fuzz的运行状态。

    • plot_data:用于afl-plot绘图。

  8. 可见跑出了很多的的crashes,接下来就是根据这些crashes来判断是否可以利用,以及如何利用。

总结

至此,我们已经按照网上的教程完成一套流程,但也仅仅只是,因为很多问题都没能弄清楚。深入的知识以后慢慢研究。

这其中我遇到了很多问题:

  • Pipe at the beginning of ‘core_pattern’问题:

    需要以root用户修改/proc/sys/kernel/core_pattern,但sudo echo core >/proc/sys/kernel/core_patternPermission denied了。

    百度才知道,是因为重定向符号 > 也是 bash 的命令,sudo 只是让 echo命令具有了root 权限,但是没有让 >命令也具有root 权限,所以 bash 会认为这个命令没有写入信息的权限。

    于是可用sudo sh -c "echo core >/proc/sys/kernel/core_pattern"进行修改。

  • 测试停止问题

    在启动测试后,我们会发现程序一直在跑,似乎没有停下来的想法,了解后才知道afl-fuzz永远不会停止。因为测试数据会不断产生然后输入测试,而程序不会主观的认为所有的crashes都已经被发现,于是会不停的跑下去。至于我们应该什么时候中止程序,以下是网上的几种判断方法:

    • 状态窗口中“cycles done”字段颜色变为绿色:紫色->黄色->蓝色->绿色
    • 距上一次发现新路径(或者崩溃)已经过去很长时间
    • 目标程序的代码几乎被测试用例完全覆盖
  • 看到将队列中的文件按一定的策略进行“突变”这一介绍时,我想起了之前人工智能课上老师所讲到的遗传算法的知识,两者是否有关联或者两者是否可以结合?

参考文献

AFL 漏洞挖掘技术漫谈(一):用 AFL 开始你的第一次 Fuzzing

AFL漏洞挖掘技术漫谈(二):Fuzz结果分析和代码覆盖率