CVE-2010-2883Adobe Reader和Acrobat CoolType.dll棧緩衝區溢位漏洞分析

Ox9A82發表於2016-07-28

     Adobe Acrobat和Reader都是美國Adobe公司開發的非常流行的PDF檔案閱讀器。 

      基於Window和Mac OS X的Adobe Reader和Acrobat 9.4之前的9.x版本,8.2.5之前的8.x版本的CoolType.dll中存在基於棧的緩衝區溢位漏洞。遠端攻擊者可藉助帶有TTF字型 Smart INdependent Glyphlets (SING)表格中超長欄位的PDF檔案執行任意程式碼或者導致拒絕服務(應用程式崩潰)。

  泉哥是上來直接就定位到漏洞函式了,我感覺這樣有點“上帝視角”了,對於我們來說可能定位漏洞關鍵點還是要用除錯去說話的。所以這裡我是用poc去根據除錯推出的漏洞崩潰點。沒有去搜尋SING的處理函式。開啟poc後,crash資訊如下。

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=4a8a08c6 ebx=0012e584 ecx=4a8a08c6 edx=07016aac esi=0012e584 edi=0ab37ed0
eip=070013b1 esp=0012e3d4 ebp=0012e454 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Adobe\Reader 8.0\Reader\BIB.dll - 
BIB+0x13b1:
070013b1 ff491c          dec     dword ptr [ecx+1Ch]  ds:0023:4a8a08e2=????????

通過對此處下斷點可以發現這裡是一個被頻繁呼叫的地方,所以我們不下中斷的斷點,改用條件記錄斷點,記錄的內容是 dc esp l1,即記錄一下是那個函式呼叫的它,之所以這樣是擔心棧溢位會搞壞回溯資訊。等到crash後再來看下棧回溯。

0:000> kp
ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
002cddc0 67371261 BIB+0x1400
002cde44 da55d18a CoolType+0x1261
002cde48 4a82a714 0xda55d18a
002cde4c 0c0c0c0c 0x4a82a714
002cde50 df6f2606 0xc0c0c0c
002cde54 2787e915 0xdf6f2606
002cde58 1129d97f 0x2787e915
002cde5c 9b7ba307 0x1129d97f
002cde60 f9d13efb 0x9b7ba307
002cde64 f977c1f6 0xf9d13efb
002cde68 dc7bf416 0xf977c1f6
002cde6c de535b4a 0xdc7bf416
002cde70 cd8e6928 0xde535b4a
002cde74 57e3bf18 0xcd8e6928
002cde78 c834489b 0x57e3bf18
002cde7c 2c6dae69 0xc834489b
002cde80 e89428e8 0x2c6dae69
002cde84 e1c8adfd 0xe89428e8
002cde88 2a25abf1 0xe1c8adfd
002cde8c d7900451 0x2a25abf1

 根據上面的資訊可以看到其實這個時候的棧已經被破壞的很厲害了,比如da55d18a明顯是一個錯誤的地址。記錄斷點的值和棧回溯的結果是一樣的,確實是67371261這個位置呼叫了crash函式,而這個地址也是正好在CoolType模組中,符合漏洞的描述。

070013f2 55              push    ebp
070013f3 8bec            mov     ebp,esp
070013f5 51              push    ecx
070013f6 51              push    ecx
070013f7 8d411c          lea     eax,[ecx+1Ch]
070013fa 8945f8          mov     dword ptr [ebp-8],eax
070013fd 8b45f8          mov     eax,dword ptr [ebp-8]
07001400 f0ff08          lock dec dword ptr [eax]     ds:0023:4a8a08e2=????????

如上是BIB.dll崩潰函式中的反彙編,我們可以看出之所以會發生crash是因為ecx的值有問題。為此我們在BIB的上層函式中來追蹤ecx的值的來源。最後發現了ecx是由一條pop ecx;指令來的,那麼我們只需要看下棧裡的資料是誰寫的就可以知道了是哪裡出現的問題了。

這麼做是基於一個基本的事實:

  1. 這是一個棧溢位
  2. ecx值來自於棧中
  3. ecx值導致異常
  4. 由1、2、3推匯出ecx的值是溢位寫的資料

那麼我們就來除錯著看看

在上面那個地址下斷後,單步下來卻發現原來呼叫的並不是這個crash函式而是經過了一個jmp,如下,但是我們不管call的是誰,總之對取值的棧下斷就可以。

eax=4a8a08c6 ebx=0012e634 ecx=0012e504 edx=07018bfc esi=0012e634 edi=07813f3c
eip=07005caf esp=0012e484 ebp=0012e504 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
BIB!BIBInitialize4+0x1efc:
07005caf 8b4c2404        mov     ecx,dword ptr [esp+4] ss:0023:0012e488=4a8a08c6
0:000> p
eax=4a8a08c6 ebx=0012e634 ecx=4a8a08c6 edx=07018bfc esi=0012e634 edi=07813f3c
eip=07005cb3 esp=0012e484 ebp=0012e504 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
BIB!BIBInitialize4+0x1f00:
07005cb3 e93ab7ffff      jmp     BIB+0x13f2 (070013f2)

我們找到了要斷的棧地址,如下所示

0:000> t
eax=4a8a08c6 ebx=0012e634 ecx=0012e504 edx=07018bfc esi=0012e634 edi=08a23f3c
eip=07005caf esp=0012e484 ebp=0012e504 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
BIB!BIBInitialize4+0x1efc:
07005caf 8b4c2404        mov     ecx,dword ptr [esp+4] ss:0023:0012e488=4a8a08c6
0:000> dd esp
0012e484  08001261 4a8a08c6 0012e744 00000000
0012e494  0803dbb3 0012e504 f6e349d1 00000004
0012e4a4  0012e6fc 00000000 08a21ea0 08a21d20
0012e4b4  0ab25000 0ab24ffc 0012e4ec 781474d8
0012e4c4  08a21d20 0ab25000 000001fc 00000004
0012e4d4  0012e72c 0012e6fc 0012e744 08a22158
0012e4e4  00001ddf 00000000 00000000 00a30a0f
0012e4f4  0012e49c 0012e738 0818436d 00000002
0:000> ? esp+4
Evaluate expression: 1238152 = 0012e488

 我們對這個地方下寫入記錄斷點

ba w 1 0800125b ".echo 寫入:;r eip;g"

得到如下結果

eip=009ffee5
eip=009ffd45
eip=070013f6
eip=00e62c2e
eip=00e62ce6
eip=08047fff
eip=08047fff
eip=08047fff
eip=08047fff
eip=08047fff
eip=08047fff
eip=08047fff
eip=08047fff
eip=08084060
eip=781473a6
eip=08021708
eip=08021a28
eip=08001249
eip=0800125b

看一下0800125b地址結果發現居然是一個push eax,在IDA中跟入這個地址,原來這個eax也是來自於上層的ecx。那麼我們怎麼知道是誰呼叫了sub_8001243呢?

.text:08001243 sub_8001243     proc near               ; CODE XREF: sub_8001952+1Bp
.text:08001243                                         ; sub_8016AF9+2F1p ...
.text:08001243
.text:08001243 arg_0           = dword ptr  4
.text:08001243
.text:08001243                 push    esi
.text:08001244                 push    edi
.text:08001245                 push    [esp+8+arg_0]
.text:08001249                 mov     esi, ecx
.text:0800124B                 call    dword_8231220
.text:08001251                 mov     edi, eax
.text:08001253                 mov     eax, [esi]
.text:08001255                 test    eax, eax
.text:08001257                 pop     ecx
.text:08001258                 jz      short loc_8001262
.text:0800125A                 push    eax
.text:0800125B                 call    dword_8231224

08001243下條件記錄斷點,bp 08001243 "dd esp l1;g"。結果得到的結果是0803DBAE這個地址的呼叫。我們在IDA中看一下,果然0803DBAE就是SING的處理函式。strcat函式造成了棧的溢位,致使實參被覆蓋,而ecx正是來自於這個實參,導致了子函式呼叫的crash。我們對strcat下斷來看下到底是怎麼一回事。

0:000> dc esp
0012e494  0012e504 034097d0 1bcfe9a8 00000004  ......@.........
0012e4a4  0012e6fc 00000000 08083184 1bcfe87c  .........1..|...
0012e4b4  0823a650 0012e6fc 00000000 0012e4b0  P.#.............
0012e4c4  0012e560 0817516c 00000000 08083184  `...lQ.......1..
0012e4d4  0012e72c 0012e6fc 0012e744 034097c0  ,.......D.....@.
0012e4e4  00001ddf 00000000 00000000 00e50a0f  ................
0012e4f4  0012e49c 0012e738 0818436d 00000002  ....8...mC......
0012e504  0012e500 0012e6dc 00000000 1bcfe9c0  ................
0:000> ? ebp
Evaluate expression: 1238276 = 0012e504

原來是試圖往一個0位元組空間的棧區域複製0.0。。。這個肯定會溢位。再來看下源字串是什麼玩意。因為漏洞描述中已經給出了是內嵌的TTF的問題,那麼就直接用pdfstreamdumper把ttf檔案dump出來

根據除錯的結果搜尋一下

0:000> r
eax=0012e504 ebx=0012e634 ecx=00000000 edx=0823a650 esi=00000000 edi=0012e744
eip=0803dba1 esp=0012e494 ebp=0012e504 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
CoolType+0x3dba1:
0803dba1 e802391300      call    CoolType!CTCleanup+0x231d3 (081714a8)
0:000> dd esp l2
0012e494  0012e504 034097d0
0:000> db 034097d0
034097d0  98 66 51 e6 ab 53 8b e7-14 a7 82 4a 0c 0c 0c 0c  .fQ..S.....J....
034097e0  16 0a 12 37 7a 8c e7 36-3f dc a9 03 a1 e1 cf cb  ...7z..6?.......
034097f0  7b 78 91 c5 8b 8c f7 5f-3d c8 2f 90 40 d3 35 1e  {x....._=./.@.5.
03409800  24 0b 45 5f 64 6d 61 0a-1d 5b 9e 6c 2e f6 6a eb  $.E_dma..[.l..j.
03409810  89 fb 3e cc 65 83 1a 2b-d3 90 68 1b fe 63 ed da  ..>.e..+..h..c..
03409820  39 ca 41 28 86 9a 6b b3-cc 51 c7 d5 d9 2a 2c 0f  9.A(..k..Q...*,.
03409830  61 ef 51 b4 15 34 4c 5e-cd b9 f3 26 ce 89 71 48  a.Q..4L^...&..qH
03409840  1f 25 37 4f ad 28 5d 90-b8 53 ba 57 1c e7 86 7d  .%7O.(]..S.W...}

搞定!

  

 

相關文章