的艺术字

的艺术字,第1张

AFLfuzzing的艺术

在这篇文章中,作者BrendanDolan-Gavit可能会详细描述他的工作经历和对AFLfuzzing的理解。

它使用前一篇文章中使用的功能测试来测试AFL发现程序中LAVA设置错误的能力。在整个测试过程中,他发现了AFL中一个可能无害的错误,以及损害其特性的有趣元素。虽然它的页面极其简单,但是AFL还是需要做一些调整,因为有一些意想不到的错误会决定成败。

美国Lop,俗称AFL,是由GoogleMichalZalewski开发设计的一种强大的覆盖和正确引导模糊器。自2013年出版以来,在安全领域广受好评。由于它惊人的成功,作者急于知道它是如何解决一个自动错误的。

Brendan最初应用了他以前文章中使用的程序,并添加了一个错误。每次file_entry的前四个字节设置为0x7c6175de或0xde75617c时,这个由LAVA添加的错误就会被打开。该错误将导致printf成为无效的文件格式字符串数组,程序将开始崩溃。

认证错误可以合理开启后,作者用aflgcc开发了编译器,刚开始模糊运算。为了更好地在初始检测中获得成功,他在程序中应用了包括塑料和浮点file_entry类型在内的优秀文件格式的打字文档:

0000000:   4156 414c 0000 0000 0200 0000 7212 8357  AVAL........r..W 0000010:   7c69 6768 7400 0000 0000 0000 0000 0000  light........... 0000020:   0200 0000 4a78 de11 707c 616e 636b 0000  ....Jx..planck.. 0000030:   0000 0000 0000 0000 0100 0000 c308 d440  ...............@

幸运的是,因为作者有一个24核的网络服务器,他已经全速运行了四天半(一个应用-M,其他-S),希望它能在这段时间内寻找类型化的值。
但结果并不令人满意。


大约200亿实施后,劳联发现零。

此外,在作者的Twitter上,他的朋友JohnRegehr建议他看看AFL过去完成了哪些报道。直到那时,提交人才意识到,事实上,他不知道劳联是如何进行测试的。

深部开采AFL检测原理

基本的afl-gcc和afl-clang专用工具实际上相对简单。它们各自包含gcc和clang,然后改变自己编译器的整个流程,把中间的汇编代码发出去(application-S选项)。最后,做一些简单的字符串匹配(C,ew)来找出在哪里添加AFL来覆盖日志记录功能。可以使用AFL来存储使用AFL_KEEP_ASSEMBLY系统变量形成的汇编代码,然后就可以看到它的所有个人行为。(事实上,我们最近应用了LLVMpass来添加新的测试方法)

原始程序代码

同样的代码已被添加到AFL的仪表板中。

在看到如下图所示形成的程序集后,您可以意识到与if语句分支匹配的代码无法被验证。这是一个潜在的问题,因为AFL无法覆盖程序的每个部分,除非所有记录都告诉它类型化的值已经实现了它的目标。

看一下afl-as(检查汇编的程序)的源代码。仔细观察这些的编码。

AFL绕过汇编代码中的下一个p2align命令。

按照这个建议,应该总是危及到在OpenBSD下编译程序的程序。殊不知,你可以发现你一开始想查的分支也是被攻破了,即使软件环境是Linux,不是OpenBSD,程序中也没有自动跳转表。

.l18控制模块应该应用AFL,但是在它的句子之后,是合适的。

因为不在OpenBSD的自然环境中,所以可以马上去掉if语句。作为一种保留的解决方法,您还可以在编译器指令中添加“-fno-align-labels-fno-align-loops-fno-align-jumps”(但它会损坏可能很慢的二进制文件)。更改后,您需要重新启动 *** 作。再次希望AFL能快点发现这个错误。

但是又失败了。7个小时的 *** 作后,一无所获,大家只好重新开始。现在,作者仍然相信他在AFL中发现了一个错误,但是恢复这个错误并不能帮助它找到我感兴趣的错误。(备注名称:也许你可以再等四天来找到错误。另一方面,AFL的周期时间的电子计数器已经变成了翠绿色,表示感觉没必要再做了。)

“继续”变量定义

在思考AFL还需要什么来寻找这个错误之后,突然,作者意识到它寻找错误的概率非常低。AFL在看到新的覆盖时总是优先考虑功能测试。在大家的测试程序中,它都要在文档的确切部分猜出两个实际的32位系统启动值,概率太小了。

AFL如何形成CDATAlogo?Libxml2有宏来制作一组字符串数组,然后通过标识符与简单的if语句进行比较。这使得AFL能够找到合理的字符串数组标识符,因为每个适当的标识符都将添加一个新的覆盖类别,这将进一步模糊类型化的值。

你也可以把它应用到测试程序中。我们不检查固定参数0x7c6175de,我们只是独立比较每个字节的个数。这使得AFL能够一次一个字节地阐明触发原理。新代码是这样的:

if (strcmp(header.magic_password, "h4ck3d by   p1gZ")) goto terminate_now;...or: if (header.magic_value == 0x12345678) goto   terminate_now;

一旦用aflgcc编译,afl可以在三分钟内找到单个CPU的错误!

AFL发现了bug

这也让作者更加毫无疑问的认为,尝试将整个控制模块分解成字节大小是非常非常值得的,这样可以更容易的编译程序。对于字符串比较,可以在strcmp/memcmp中内联完成替换。

一个隐藏的陷阱

当研究涵盖难题时,你可以注意到AFL有了一个新的C语言编译器:afl-clang-fast。这个控制模块是拉斯洛Szekeres专用的,仪器设备作为LLVM通行卡,而不是根据变化形成的汇编代码。所以AFL可以变强,测试选项会越来越多。

因此,即使您已经在源代码中添加了不同的if语句,生成的LLVM语句看起来也更像您的初始语句。

通过使用LLVM的仪器设备,AFL不会发现每个人的错误。

让AFL词典更智能

虽然你可以让AFL引起启动输入和显示信息错误的调整程序,这已经很好了,但是如果我们能让它发现你初始程序中的bug就更好了。

AFL应用程序很难,因为他们必须一次猜测32位系统的类型。鉴于此,必须搜索的室内空空间非常大:即使假设刚刚开始系统搜索文档右侧的字节数字,也需要20亿次平均值的实现才能找到合适的值。自然,除非它有理由相信改进覆盖将在这个文档的部分工作中执行,否则它不容易致力于正确的文档部分,因为这使得它更不可能寻找正确的类型。

众所周知,我们可以允许AFL选择不完整的任意打字来连接。AFL的一个特征是,当它执行模糊检测时,它适用于应用字典的值。大部分是一组标记,可以在遗传变异的文献中使用,而不是随机选取的值。因此,典型的技巧是将程序中找到的所有变量定义和字符串数组添加到字典中。下面,用AFL从二进制中获取变量定义和字符串数组,环境污染的脚本制作如下:

#!/bin/bash objdump -d "${1}" | grep -Eo '$0x[0-9a-f]' | cut -c 2- | sort -u | while read const; do echo $const | python -c 'import sys,   struct; sys.stdout.write("".join(struct.pack("<I" if   len(l) <= 11 else "<Q", int(l,0)) for l in   sys.stdin.readlines()))' > testcases/$const; done i=0; strings "${1}"| while read line; do echo -n "$line" > testcases/string_${i} ; i=$[ $i  1 ] ; done

因此,一旦你给AFL一个字典,它可能会在15分钟内发现94%(149/159)的错误。

在看到自己的错误之后,我们发现了一些关于AFL的有趣的事情:

AFL发现错误的能力与覆盖和检查能力密切相关,检查能力与AFL的错误和不同的编译时间有关。

编码结构也会严重伤害AFL特性,看起来细微的差别都会造成很大的伤害。

最后,这就是我们期望用熔岩达到的目标。根据对当今错误测试工具的仔细研究,每个人都会对其原理有更好的理解,并找到更强的发现错误的方法。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/771812.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-02
下一篇2022-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存