1. 程式人生 > >【漏洞分析】Adobe Acrobat和Reader整數溢位漏洞(CVE-2012-0774)

【漏洞分析】Adobe Acrobat和Reader整數溢位漏洞(CVE-2012-0774)

0x00 前言

總體來說坑不多,但是對於windbg沒有watchpoint功能這一點,真的是很坑。

0x01 簡介

Adobe Acrobat和Reader在True Type Font (TTF)處理的實現上存在整數溢位漏洞,攻擊者可利用此漏洞執行任意程式碼。
受影響軟體版本:
Adobe Reader 9.4.[0-5]
Adobe Reader 9.3.[0-4]
Adobe Reader 9.2
Adobe Reader 9.1.[0-3]
更多詳情,請參考【bid-52951

0x02 漏洞原理

True Type Font字型檔案中使用預定義的指令集控制字型hinting,當執行到MINDEX指令時,被操作的陣列長度n溢位成超大值,導致陣列寫越界。

MINDEX指令:對size為n的陣列進行迴圈左移一位。

0x03 漏洞分析

執行環境:

版本
作業系統 windows 7 sp1 32bit
偵錯程式 windbg 6.12 32 bit
漏洞軟體 AdbeRdr940_zh_CN.exe
檔案檢視器 010editor
反編譯工具 IDA

poc 如下圖所示,問題數值n是由多個值經過計算得到的,無法在poc檔案中直接看到,這裡展示的計算前的輸入資料。
在這裡插入圖片描述


需要說明的是漏洞出發的關鍵資料猜測是fuzz出來的,所以,010editor在解析到SimpleGlyph[10]的資料時報異常,沒有顯示出來。途中藍色選中的資料就在這片黑色領域中。
報錯資訊如下:
010editor報錯資訊

windbg不用開page heap,因為不是堆溢位。執行poc,檢視報錯:

eax=65ee622c ebx=00000000 ecx=65eef000 edx=3fffdc8a esi=65eef004 edi=00004141
eip=65cb79ce esp=0016cd9c ebp=0016ce30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Adobe\Reader 9.0\Reader\CoolType.dll - 
CoolType+0x79ce:
65cb79ce 8919            mov     dword ptr [ecx],ebx  ds:0023:65eef000=00000000

寫入的目標地址是65eef000

檢視記憶體屬性

0:000> !address 65eef000                  
Failed to map Heaps (error 80004005)
Usage:                  Image
Allocation Base:        65cb0000
Base Address:           65eef000
End Address:            65f0f000
Region Size:            00020000
Type:                   01000000	MEM_IMAGE
State:                  00001000	MEM_COMMIT
Protect:                00000002	PAGE_READONLY
More info:              lmv m CoolType
More info:              !lmi CoolType
More info:              ln 0x65eef000

目標地址Protect屬性是PAGE_READONLY,表示只讀。向只讀地址寫入資料,估計是寫越界了。

回溯函式呼叫棧

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0016ce30 65cbade0 0c6fcbb8 65ee5a28 0c6fce16 CoolType+0x79ce
0016ce60 65cb4e44 0c6fcbb8 65ee5a28 0c6fce16 CoolType+0xade0
0016cea0 65cb587c 0c6fca38 0c6fcbb8 65ee5a28 CoolType+0x4e44
0016cf44 65cb5c36 05eb6aa4 05eb6bfc 05eb6bb4 CoolType+0x587c
0016cfa0 65cb5cc8 05eb6aa4 05eb6bfc 05eb6bb4 CoolType+0x5c36
0016cff0 65cb3a69 05eb6aa4 05eb6bfc 05eb6bb4 CoolType+0x5cc8
0016d058 65cb3b36 0016d15c 0016d08c 00000001 CoolType+0x3a69
0016d1b8 65ccbb43 098df390 00000000 0016d204 CoolType+0x3b36
00000000 00000000 00000000 00000000 00000000 CoolType+0x1bb43

檢視當前函式 CoolType+0x79ce

int __cdecl sub_800798B(int a1)
{
  unsigned int v1; // [email protected]
  _DWORD *v2; // [email protected]
  int v3; // [email protected]
  unsigned int v4; // [email protected]
  int v5; // [email protected]
  int result; // [email protected]

  if ( (unsigned int)(dword_82323E0 - 4) < *(_DWORD *)dword_82323EC
    || (v1 = *(_DWORD *)(dword_82323EC + 340), dword_82323E0 - 4 >= v1)
    || (v2 = (_DWORD *)(dword_82323E0 - 4),
        v3 = *(_DWORD *)(dword_82323E0 - 4),
        v4 = dword_82323E0 - 4 - 4 * *(_DWORD *)(dword_82323E0 - 4),
        v4 < *(_DWORD *)dword_82323EC)
    || v4 >= v1 )
  {
    result = dword_8232438;
    dword_8232434 = 4368;
  }
  else
  {
    v5 = *(_DWORD *)v4;
    if ( v3 > 0 )
    {
      do
      {
        --v3;
        *(_DWORD *)v4 = *(_DWORD *)(v4 + 4); //在此處崩潰
        v4 += 4;
      }
      while ( v3 );
      --v2;
    }
    *v2 = v5;
    dword_82323E0 = (int)(v2 + 1);
    result = a1;
  }
  return result;
}

該函式是MINDEX指令的實現-size為n的陣列做迴圈左移一位,在記憶體中找陣列邊界時,n也就是程式碼中的v3溢位成超大值,導致寫越界。
sub_800798B函式之前已經寫了一篇比較詳細文章做說明【傳送門】。

65cb798b a1e023ee65      mov     eax,dword ptr [CoolType!CTCleanup+0xe3ad6 (65ee23e0)] // 函式入口,這裡下斷點
65cb7990 8b0dec23ee65    mov     ecx,dword ptr [CoolType!CTCleanup+0xe3ae2 (65ee23ec)]
65cb7996 53              push    ebx
65cb7997 56              push    esi
65cb7998 8b31            mov     esi,dword ptr [ecx]
65cb799a 8d50fc          lea     edx,[eax-4]
65cb799d 3bd6            cmp     edx,esi
65cb799f 57              push    edi
65cb79a0 7245            jb      CoolType+0x79e7 (65cb79e7)
65cb79a2 8bb954010000    mov     edi,dword ptr [ecx+154h]
65cb79a8 3bd7            cmp     edx,edi
65cb79aa 733b            jae     CoolType+0x79e7 (65cb79e7)
65cb79ac 83c0fc          add     eax,0FFFFFFFCh
65cb79af 8b10            mov     edx,dword ptr [eax]
65cb79b1 8bda            mov     ebx,edx
65cb79b3 c1e302          shl     ebx,2
65cb79b6 8bc8            mov     ecx,eax
65cb79b8 2bcb            sub     ecx,ebx
65cb79ba 3bce            cmp     ecx,esi
65cb79bc 7229            jb      CoolType+0x79e7 (65cb79e7)
65cb79be 3bcf            cmp     ecx,edi
65cb79c0 7325            jae     CoolType+0x79e7 (65cb79e7)
65cb79c2 85d2            test    edx,edx
65cb79c4 8b39            mov     edi,dword ptr [ecx]
65cb79c6 7e0f            jle     CoolType+0x79d7 (65cb79d7)
65cb79c8 4a              dec     edx //陣列大小n自減,也就是反彙編中的v3自減操作
65cb79c9 8d7104          lea     esi,[ecx+4]
65cb79cc 8b1e            mov     ebx,dword ptr [esi]
65cb79ce 8919            mov     dword ptr [ecx],ebx  ds:0023:65eef000=00000000
65cb79d0 8bce            mov     ecx,esi
65cb79d2 75f4            jne     CoolType+0x79c8 (65cb79c8)
65cb79d4 83e804          sub     eax,4
65cb79d7 8938            mov     dword ptr [eax],edi
65cb79d9 83c004          add     eax,4
65cb79dc a3e023ee65      mov     dword ptr [CoolType!CTCleanup+0xe3ad6 (65ee23e0)],eax
65cb79e1 8b442410        mov     eax,dword ptr [esp+10h]
65cb79e5 eb0f            jmp     CoolType+0x79f6 (65cb79f6)

在函式入口出下斷點

0:000>bp 65cb798b

可以看到這個值n在進入sub_800798B函式不久v3改變成0x40000001,並開始do-while迴圈,有人見過0x40000001這麼大的陣列嗎?顯然這是一個bug。

跟進v3變數,在儲存地址65ee622c下寫斷點

0:000> ba w4 65ee622c

追蹤到v3的值的計算過程
0x3FFF0003 + 0x7FFF + 0x7FFF = 0x40000001

根據這段輸入定位到poc.pdf中的關鍵資料位置

41 41 41 41 41 41 00 03 00 00 00 40 42 41 02 7F FF 7F FF 63 60 41 04 FF E8 00 00 00 00 00 00 43 B0 01 61 42 43 78 41 02 7F FF 7F FF 60 60

0x04 小結

  1. 能初步定位問題出在glyf表,並通過官方文件理解這段資料的意義很重要;
  2. windbg沒有watchpoint,在觀測65ee622c地址的資料變化時,只能靠人眼和記憶了,所以泉哥的分析用的Immunity Debugger;
  3. 這種資料是指令集的反彙編程式碼開始比較難看。在想llvm和jit是不是也會有這樣的bug。

0x05 參考文獻

http://pwdme.cc/2017/11/05/cve-2012-0774/
https://developer.apple.com/fonts/TrueType-Reference-Manual/RM07/appendixA.html
https://docs.microsoft.com/en-us/typography/opentype/spec/tt_instructions
https://android.googlesource.com/platform/external/freetype/+/f720f0dbcf012d6c984dbbefa0875ef9840458c6/src/truetype/ttinterp.c

在這裡插入圖片描述