导语:自从AFL这类Fuzz工具释放以来,Fuzzing就变得很老生常谈了。由于性能是关键,我们希望优化fuzzing方法,以最大化的方式在给定时间段内发现错误数量。
介绍
自从AFL这类Fuzz工具释放以来,Fuzzing就变得很老生常谈了。由于性能是关键,我们希望优化我们的fuzzing方法,以最大化的方式在给定时间段内发现错误数量。本文介绍了一种应用于Foxit Reader插件的一般方法,该插件负责将图像转换为PDF。
更具体地说,我们专注于漏洞插件(ConvertToPDF_x86)的版本是7.3.4.308以及Foxit版本7.3.6.321。这个版本的插件发现了几个有趣的crash。因为他们被另一个研究人员独立发现,他们向Foxit团队披露了这些信息(导致了一个新的,固定的版本),我们决定现在发布。
Fuzzing方法
当使用Foxit Reader打开一个图片时,插件ConvertToPDF_x86就被加载,用来将图片转化为PDF并显示。该插件可以兼容大部分格式的图片(JPEG, GIF, PNG, …)。
本例使用的图片格式是JPEG,随后我确认了Foxit调用该插件的函数:
通过检查在栈上推送的参数,我们可以看到第一个参数指向图像文件路径,第二个指向要写入的临时PDF文件。请注意,由于ASLR,下面显示的地址可能与上面的模块列表不同。
当Foxit调用函数时,通过动态改变参数,我们能够打开任何其他的任意图像。然后通过恢复调用之间的上下文关系(特别是x86寄存器),可以重复地快速调用这个转换函数。幸运的是,堆不需要每次都被恢复。
这种方法可以以多种方式进行自动化。我们可以使用Pintool,但是我决定为编写一个特定的优化工具。
为此,我编写了一个小型调试器,通过传递图像作为参数启动Foxit Reader,并对ConvertToPDF_x86.dll中的图像转换函数的相关调用进行下断点,以便于在下一步中可以直接获得上下文。
调试器然后在Foxit的内存中注入一个DLL(这由RunFuzzing()完成),并设置要传递给被调用函数的相应值。
在Intel Xeon E3-1230v3 (3.3 GHz)上,运行速度在150和300测试用例/秒,具体取决于使用的fuzzing方法。
重要的是要注意,fuzzing必须发生在Foxit进程中:手动调用DLL插件不会直接工作。
Fuzzing结果
即使存在简单的bit翻转,很多crash文件也会迅速产生,其中一些可能是可以进行利用的。总共三天的fuzzing测试产生了下面的崩溃。
可以在这里下载一些。
结论
该方法可以应用于任何软件,条件是要在目标函数(或函数组)被调用之前能够容易地进行重新创建软件的状态。这在我看来是需要克服的最大障碍。
这里ConvertToPDF_x86的情况很简单,但在其他许多情况下,必须注意内存分配,取消分配和全局状态更改(或初始化例程)。这样子Pintool可能会变得非常有用,这也有可能是可以进一步研究的有趣方向。
参考文献:
[1] American Fuzzy Lop, http://lcamtuf.coredump.cx/afl/
[2] Foxit Reader, https://www.foxitsoftware.com/products/pdf-reader/
[3] Pintool, https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool