【漏洞分析】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文件中直接看到,这里展示的计算前的输入数据。
【漏洞分析】Adobe Acrobat和Reader整数溢出漏洞(CVE-2012-0774)_第1张图片
需要说明的是漏洞出发的关键数据猜测是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; // edi@2
  _DWORD *v2; // eax@3
  int v3; // edx@3
  unsigned int v4; // ecx@3
  int v5; // edi@5
  int result; // eax@8

  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

【漏洞分析】Adobe Acrobat和Reader整数溢出漏洞(CVE-2012-0774)_第2张图片

你可能感兴趣的:(安全漏洞,二进制安全)