我将在本文中分享我在使用通用Fuzzing工具挖掘非源产品中的漏洞的过程中学到的Fuzzing经验。我学习的环境是Windows,我通常使用的Fuzzing工具针对的是该环境中的产品。在本文中,我将使用Winafl这个流行Fuzzing工具来挖掘图像查看器中的漏洞,例如Irfanview ,Fast Stone ,Xnview 等。
0x01 基本介绍
我不会详细介绍Winafl的体系结构,也不会详细介绍如何使用它。我将在文章末尾提供一些资料,任何有兴趣的人都可以阅读学习。
为什么选择“图像查看器”来Fuzzing?可以说,文件格式的Fuzzing是当今最流行的一种Fuzzing方向。花费很少的时间准备,可访问,易于挖掘的语料库(取决于大小写),...并且可能逻辑上解析这些文件格式的漏洞仍然很高。
在这里,我将以Irfanview为例,说明如何使用和使用Fuzzing工具挖掘解析Irfanview图像格式的漏洞。
0x02 逆向分析
我们可以看到Irfanview处理了许多图像文件格式。某些格式将在i_view32.exe程序中处理,某些其他文件格式将通过通过DLL部署的插件处理。
我们需要了解如何执行图像文件流。了解逻辑的快慢,困难或容易,这取决于每个程序的复杂性。对于复杂的程序,将需要很多时间。
但是,在这种情况下,我将使用DynamoRIO [6](一种用于在程序执行时计算覆盖率的工具)来更快地支持我的逆向操作。
通过将DynamoRIO与IDA的插件结合使用,我们可以通过输入来告诉程序执行的方式,执行的代码。逆向时节省大量时间。
例如,当Irfanview处理jpeg2000图像格式时,该命令运行drrun.exe来生成文件覆盖率:
drrun.exe -t drcov-i_view32.exe _00042.j2k
使用此命令,DynamoRIO将生成一个文件,其中包含有关已加载的DLL的信息以及程序和每个DLL文件的覆盖范围。
这是输出文件覆盖率的示例:
我们可以看到在处理_00042.j2k文件的过程中已加载JPEG2000.dll DLL。
现在,使用IDA上的lighthouse插件查看结果。我们可以看到,以绿色突出显示的命令是i_view32.exe处理_00042.j2k文件时执行的命令。
从那里我们将追溯jpeg2000图像处理函数,方法是找到相关的字符串,这是我经常使用的最快,最有效的方法。我们可以看到i_view32.exe将加载库JPEG2000.dll,然后调用ReadJPG2000_W()函数来处理jpeg2000文件。
让我们进行调试以查看传递给ReadJPG2000_W()函数的参数,我们在调用ReadJPG2000_W()函数的地址处设置断点:
根据调用ReadJPG2000_W()函数时堆栈的状态,传递给该函数的参数如下:
-wchar_t * argv1:需要处理jpeg2000文件的名称。
-int argv2:变量存储值为0。
-wchar_t * argv3:大小为2048的内存。
-wchar_t * argv4:大小为2048的内存,由字符串“ None”初始化。
-int argv5,argv6:用于在解析jpeg2000文件时保存参数。
这很简单,可以编译一个调用此函数的工具,并将上述参数传递给解析jpeg2000图像文件。因为这些参数完全独立于程序i_view32.exe。
这是我写的工具:
使用输入的jpeg2000文件运行文件,并检查其在JPEG2000.dll上的覆盖范围
它可以与i_view32.exe的jpeg2000处理流一起正常工作。
有了这个文件,我们将能够使用它进行Fuzzing。我在GitHub存储库上使用了语料库:
-openjpeg
-Fuzzing语料库
-以及以前的Fuzzing项目中的一些语料库。
使用lighthouse,我们还可以看到DLL中每个函数的覆盖范围。
我使用ReadJPG2000_W函数覆盖的文件只有大约34%,当然,当Fuzzing时,这个数字并不理想,你需要找到一个语料库来将这个数字提高。
使用Winafl使我上面编译的文件来Fuzzing jpeg2000:
查看Winafl界面,我们应该对以下一些参数感兴趣:
-执行速度:可以在1秒内执行的测试用例数
-稳定性:此指示器在Fuzzing期间显示稳定性。在运行Winafl时,该测试用例将有一定数量的迭代,从理论上讲,同一测试用例的覆盖率值不得更改。如果该值改变,则稳定性将不高。
-地图密度:此参数显示在使用当前测试用例运行时目标的覆盖范围。
这三个参数必须较高才能在Fuzzing代码覆盖率较高时有效。
对于其他图像文件格式,Irfanview与jpeg2000相同。负责解析图像文件的插件具有相同的处理函数,除了Fuzzing jpeg2000文件格式外,我还尝试了其他格式,例如gif,dicom,djvu,ani,dpx,wbmp,webp,...
最终我们得到如下漏洞结果:CVE-2019-17241,CVE-2019-17242,CVE-2019-17243,CVE-2019-17244,CVE-2019-17245,CVE-2019-17246,CVE-2019-17247,CVE-2019-17248, CVE-2019-17249,CVE-2019-17250,CVE-2019-17251,CVE-2019-17252,CVE-2019-17253,CVE-2019-17254,CVE-2019-17255,CVE-2019-17256,CVE- 2019-17257,CVE-2019-17258,CVE-2019-17259,CVE-2019-17261,CVE-2019-17262
0x03 Fuzzing技巧
使用Winafl时,我发现Winafl在Windows 7上最稳定。Windows10非常糟糕,DynamoRIO在Windows 10上的内存存在一些问题,导致Fuzzing或崩溃。
当进行Fuzzing时,我建议为该文件打开“页面堆”,以更好地检测出界和未初始化的内存漏洞。
Afl-tmin是帮助你最小化语料库的有用工具,这对于变异语料库中的Fuzzing非常有用。但是我通常不使用它,因为它太慢了,我将来会尝试使用Halfempty工具取代afl-tmin。
加快速度:文件用于调用Windows API,DynamoRIO的处理速度更快。在我上面编写的工具中,在main函数中,我使用LoadLibraryA函数加载需要fuzz的DLL和main函数中的target_offset,这将大大降低fuzzer的运行速度。
有许多解决方法。我有几种读取和读取的方法,更改偏移量以启动工具非常好,但是使用此方法时,当在带有迭代器的调试模式下运行时,我会对其进行检查,我的Fuzzing工具不稳定,我不会知道为什么。在这里,我使用lief 解决此问题。我将在执行主要函数之前加载需要Fuzzing 处理的库:
这是在我确定了这个Fuzzing 目标之后的结果:
速度有所提高,但这不是最好的方法,因为速度取决于Fuzzing 的目标,不仅取决于编译的文件。我使用它是因为在Windows上还有一个Fuzzing工具,但是后来我更喜欢使用它而不是Winafl,这是我的库在主要函数与该Fuzzing工具的体系结构匹配之前加载的方式。下面的文章我将更多地提及该Fuzzing工具。
语料库:对我来说,寻找语料库是最困难的问题。搜索具有较高覆盖率的语料库非常罕见,并且使用这些语料库的人通常不会共享,因为这对于Fuzzing非常有价值。
当找到一个大型语料库时,你应该使用winafl-cmin减少测试用例的数量。将有一些测试用例,其覆盖范围是重复的或包含在其他测试用例中。
0x04 分析总结
这是我用来学习Fuzzing的第一个目标。继续本系列的Fuzzing,我将根据我在本文中所讲的内容,分享如何处理和Fuzzing VMWare,Microsoft等的漏洞。
0x05 参考资料
[1] https://www.irfanview.com/
[2] https://www.faststone.org/
[3] https://www.xnview.com/en/
[4] https://www.apriorit.com/dev-blog/644-reverse-vulnerabilities-software-no-code-dynamic-fuzzing
[5] https://symeonp.github.io/2017/09/17/fuzzing-winafl.html
[6] https://github.com/DynamoRIO/dynamorio
[7] https://github.com/gaasedelen/lighthouse
[8] https://github.com/googleprojectzero/halfempty
[9] https://github.com/googleprojectzero/winafl/issues/4
[10] https://github.com/lief-project/LIEF
本文翻译自:https://ezqelusia.blogspot.com/2020/05/start-fuzzing-fuzz-various-image-viewers.html如若转载,请注明原文地址