[原創]Adobe reader 漏洞CVE-2009-4324初步分析

仙果發表於2010-01-10
文章名稱: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

MSDN上關於setjmp的解釋不甚理解,所以就在《UNIX環境高階程式設計》中文版中查詢到相關的介紹,
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.-.....


0x4.總結
到此,CVE-2009-4324的初步分析就到這裡,可以看出程式在23811216處引用了已經被釋放的記憶體,
造成漏洞可以很容易的被利用,
其中還有很多需要理解的地方
1.SetJmp函式是何作用
2.ACPushExceptionFrame 的執行流程如何
3.對此漏洞的形成原因還有待進一步理解

CVE-2009-4324初步分析.pdf
poc.pdf
info.rar
上傳的附件:

相關文章