|
原文作者:Vitaly Nikolenko译者:Arming 校对:布兜儿
原文链接:http://www.hdwsec.fr/en/blog/inprocessfuzzing.html
Introduction(前言)
Fuzzing现在已经很普遍了,尤其是在AFL发布以来。众所周知,性能是非常关键的,因此为了在给定时间段内尽可能多的发现bug,我们希望优化我们的Fuzzing方法。本文以Foxit Reader的一个图片转为PDF的插件为例,描述了一种通用方法。更具体地说,我们用的Foxit版本是7.3.6.321,有漏洞的插件(ConvertToPDF_x86)版本是7.3.4.308. 这个版本的插件有几个有意思的crash。这些crash是由另一位研究人员独立发现的,并且已经提交给Foxit团队(已修复并发布新版本),因此我们决定公开它们。
Fuzzing Method
当通过Foxit Reader打开一个图片时,插件ConvertToPDF_x86就会被加载,将转换图片为PDF并显示出来。该插件可以处理最常见的图片格式(JPEG, GIF, PNG, ...)。[table][tr][td]
1
2
3[/td][td]
ModLoad: 6cf90000 6cf96000 C:\Windows\SysWOW64\IconCodecService.dll
ModLoad: 50230000 50f61000 C:\Windows\SysWOW64\ieframe.dll
ModLoad: 53820000 53d45000 C:\Program Files (x86)\Foxit Software\Foxit Reader\Plugins\Creator\x86\ConvertToPDF_x86.dll
在我的Fuzzing测试中,我决定专注于JPEG文件格式,然后定位到了Foxit调用插件的函数:[table][tr][td]
1
2
3
4
5
6
7[/td][td]
003b96f0 533c932e kernel32!CreateFileW
003b9720 533cb136 ConvertToPDF_x86!DestorFXPDFConvertor+0x4fe
003b975c 02598c3f ConvertToPDF_x86!CreateFXPDFConvertor+0x646
003bb644 0128e6fd FoxitReader_Lib_Full!CryptUIWizExport+0x8856ff
003beac8 0128637a FoxitReader_Lib_Full+0x18e6fd
003beb18 0128691c FoxitReader_Lib_Full+0x18637a
003beed0 013aefa8 FoxitReader_Lib_Full+0x18691c
通过检查栈上的参数,我们可以看出第一个是图片文件的路径,第二个是将要写入的临时PDF文件。请注意,由于ASLR,下面显示的地址可能与上述模块列表有所不同。[table][tr][td]
1
2
3
4
5
6
7[/td][td]
0032e6f0 6a01 push 1
0032e6f2 6a00 push 0
0032e6f4 51 push ecx ; path to temp PDF file
0032e6f5 8bc8 mov ecx,eax
0032e6f7 8b4604 mov eax,dword ptr [esi+4]
0032e6fa 52 push edx ; path to JPEG image
0032e6fb ffd0 call eax
通过在Foxit调用该方法时动态修改参数,我们可以打开任意其他图片。然后通过恢复调用之间的上下文(尤其是x86寄存器),可以快速重复地调用该转换函数。幸运的是,堆上的内容不需要每次恢复。
这种方法可用通过多种方式实现自动化。我们可以使用Pintool,但是为了优化我决定写一个特定的工具。
为此,我写了一个小调试器,可以通过传递一个图片作为参数来启动Foxit Reader,并且断点在ConvertToPDF_x86.dll的图片转换函数的对应调用处,以便在下一步中回放上下文。[table][tr][td]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[/td][td]
CONTEXT ctx;
...
case EXCEPTION_DEBUG_EVENT:
{
EXCEPTION_DEBUG_INFO& exception = debug_event.u.Exception;
switch (exception.ExceptionRecord.ExceptionCode)
{
case STATUS_BREAKPOINT:
...
if (IsMyBp())
{
SaveContext(&ctx);
...
RunFuzzing(&ctx);
...
}
}
}
然后调试器注入一个DLL到Foxit内存中(通过RunFuzzing()实现),并设置要传给被调用函数的参数。[table][tr][td]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22[/td][td]
while(TRUE)
{
corrupt(image);
// call the fonction
_asm
{
push 1
push 0
lea edi, pdf_path
push edi;
lea edi, image_path
push edi;
mov edi, val_edi
mov esi, val_esi
mov ecx, val_ecx
mov ebx, val_ebx
mov eax, val_eax
mov edx, val_edx
call eax
}
}
在 Intel Xeon E3-1230v3 (3.3 GHz) 机器上,基于该Fuzzing方法,我们达到了150~300 份测试每秒的效果。重要的是,请注意,该Fuzzing必须在Foxit的进程中执行,手动调用该DLL插件将不会生效。
Fuzzing结果
即使是简单的位翻转,也会有很多crash快速产生,其中一些可以被利用。在进行了3天的Fuzzing后,发现了下面的这些crash。[table][tr][td]
1
2
3
4
5[/td][td]
eax=11ba0020 ebx=25000007 ecx=ec54a4e6 edx=11ba0020 esi=11544060 edi=25000007
eip=5cc76ff3 esp=003c8b10 ebp=003c8b18 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
ConvertToPDF_x86!CreateFXPDFConvertor+0x2ba793:
5cc76ff3 8a19 mov bl,byte ptr [ecx] ds:002b:ec54a4e6=??[table][tr][td]
1
2
3
4
5[/td][td]
eax=1e7df002 ebx=1e7df000 ecx=1e7df002 edx=1e7df000 esi=1c7bdfc0 edi=1e7e0ff8
eip=6735d9a6 esp=00399750 ebp=00399750 iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010287
ConvertToPDF_x86!CreateFXPDFConvertor+0x192eb6:
6735d9a6 0fb601 movzx eax,byte ptr [ecx] ds:002b:1e7df002=??[table][tr][td]
1
2
3
4
5[/td][td]
eax=7b2e0ee2 ebx=1c59cfc8 ecx=00000001 edx=52cf0002 esi=00000000 edi=1f20fff8
eip=67e399e8 esp=035f9854 ebp=035f985c iopl=0 nv up ei ng nz ac pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010297
ConvertToPDF_x86!CreateFXPDFConvertor+0x2deef8:
67e399e8 8808 mov byte ptr [eax],cl ds:002b:7b2e0ee2=??[table][tr][td]
1
2
3
4
5[/td][td]
eax=00000000 ebx=44436fb0 ecx=61f3dbf7 edx=431e1078 esi=00000000 edi=44438fb8
eip=620ba719 esp=00309efc ebp=00309f20 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
ConvertToPDF_x86!CreateFXPDFConvertor+0x2dfc29:
620ba719 837e0800 cmp dword ptr [esi+8],0 ds:002b:00000008=????????[table][tr][td]
1
2
3
4
5[/td][td]
eax=00000000 ebx=56bc8fb8 ecx=67fae147 edx=42551078 esi=00000000 edi=00000000
eip=6812b468 esp=00219788 ebp=002197b8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210246
ConvertToPDF_x86!CreateFXPDFConvertor+0x2e0978:
6812b468 397e08 cmp dword ptr [esi+8],edi ds:002b:00000008=????????[table][tr][td]
1
2
3
4
5[/td][td]
eax=00000000 ebx=000002fa ecx=00000060 edx=44b57f7f esi=003f9d5c edi=44b57fbf
eip=69885b61 esp=003f9d08 ebp=003f9d1c iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210206
ConvertToPDF_x86!CreateFXPDFConvertor+0x1bb071:
69885b61 8a5c0302 mov bl,byte ptr [ebx+eax+2] ds:002b:000002fc=??
你可以在这里下载(http://www.hdwsec.fr/en/blog/foxit_crashes.zip)
Conclusion(结论)
这种方法可以用于任意软件,只要在调用目标函数(或一组函数)前能够轻松地再现软件的状态。在我看来这也是需要克服的最大障碍。
ConvertToPDF_x86的例子是非常简单的,但是在许多其他情况下,需要注意内存分配、释放和全局状态的改变(或初始化程序)。针对这个目的Pintool就变得非常有用,而且很可能是一个有趣的进一步研究的方向。
请注意,我们可以通过hook插件的读/写访问来优化该Fuzzing方法,从而避免执行过程中在磁盘上写入任何文件。
References:
[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
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
|