来源:http://blog.vulnhunt.com/index.php/2011/12/12/cve-2011-2462-pdf-0day-analysis/
Author: instruder of Code Audit Labs of vulnhunt.com
测试pdf 版本:9.4.0
测试系统:win7
0 Affected Prodects
软件版本:<=adobe reader 9.4.6
CVE ID :2011-2462
1 crash info
eax=52520026 ebx=1e282ea8 ecx=00000024 edx=00000000 esi=00000000 edi=00000000
eip=1a73f2e3 esp=0012f4fc ebp=0012f548 iopl=0 nv up ei ng nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010286
rt3d!QUAT::QUAT+0×5cf:
1a73f2e3 80b8fc09000000 cmp byte ptr +0×9fb (000009fc)[eax],0 ds:0023:52520A22=??
2 Analysis
这是个pdf 0day漏洞没有任何漏洞描述的相关细节,只知道是u3d格式文件出了问题。用已有的010脚本查看u3d格式也没有发现什么异常。 只能一步步跟踪分析。
从上面的crash info中,必须要找出是什么原因导致eax变成了非法的值,从而触发崩溃
出问题的地方是在u3d格式的node节点出,当显示pdf时,e3_NODE__ChildsDraw函数进行绘制视图
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
C in rt3d.dllint __stdcall e3_NODE__ChildsDraw(struc_1 *a1, int a2, int a3, int a4){ struc_1 *node; // esi@1 int result; // eax@2 for ( node = (struc_1 *)a1->first_node; node; node = (struc_1 *)node->next_node ) { result = (*(int (__stdcall **)(_DWORD, _DWORD, _DWORD, _DWORD))(node->cobject + 0xC4))(node, a2, a3, a4);// rt3d!e3_NODE::Draw if ( result < 0 ) return result; } return 1;} |
e3_NODE::Draw函数中会调用sub_ 101819E7(命名为Take_Fill_Node)函数,该函数会申请sizeof(struct1)* node_count大小的内存,sizeof(struct1)=0xa0 ,然后循环(这里总共5个节点,从0-4)将将node+0×68处的一个对象指针赋给申请的内存结构中。此时这个对象指针+0×54偏移处已经是被修改的非法值52520026,因此需要知道这个对象是从哪来的。
node+0×68的对象指针从哪来的呢,这里就要看node节点的分配情况。从rt3d.dll中看到有关于e3_NoDE:类,其中有e3_NODE__AddChild和e3_NODE__Create等节点操作函数,很自然的在节点的分配出下断点。
|
1
2
3
4
5
|
bu !rt3d+165CCA ".if(1){.echo addchild;gc}"bu !rt3d+181A56 ".if(1){.echo malloc base;db eax;}"bu !rt3d+168050 ".if(1){.echo create new child node;r eax;gc}"bu rt3d!e3_NODE::ChildsDraw+0x19 ".if(1){.echo ChildsDraw childnode ;r esi;dd esi+0x48} l4"bu !rt3d+166EB0 ".if(1){.echo call Take_Fill_Node;dd esp l4;dd poi(esp+4)+0x48}" |
node节点的分配情况
|
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
|
create new child nodeeax=03217ac8 --allocate root nodeaddchildModLoad: 668a0000 66a63000 C:\Windows\system32\d3d9.dllModLoad: 70be0000 70be6000 C:\Windows\system32\d3d8thk.dllModLoad: 6b400000 6b421000 C:\Windows\system32\vm3dum.dllModLoad: 67ed0000 67fd5000 C:\Windows\system32\d3d8.dll*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Adobe Reader 9.4.0\Reader 9.0\Reader\plug_ins3d\3difr.x3d -create new child nodeeax=0321c918 --allocate node1 ---second breakaddchildcreate new child nodeeax=0321d3b8 --allocate node2addchildcreate new child nodeeax=0321d488 --allocate node3addchildcreate new child nodeeax=0321d558 --allocate node4addchildcreate new child nodeeax=0321d628 --allocate node5addchildModLoad: 69fa0000 6a00c000 C:\Program Files\Adobe Reader 9.4.0\Reader 9.0\Reader\AdobeXMP.dllModLoad: 6f8d0000 70350000 C:\Windows\system32\ieframe.dllModLoad: 718a0000 718dc000 C:\Windows\system32\OLEACC.dllADOBE_READLOGGER_CMD:PAUSE_LOGModLoad: 6b3d0000 6b3f1000 C:\Windows\system32\vm3dum.dllChildsDraw childnodeesi=03217ac8 ---root node03217b10 0321c918 00000000 00000000 00000000ChildsDraw childnodeesi=0321c918 ---node 10321c960 00000000 03217ac8 0321d3b8 0321d3b8ChildsDraw childnodeesi=0321d3b8 ---node 20321d400 00000000 00000000 0321d488 0321d488ChildsDraw childnodeesi=0321d488 ---node 30321d4d0 00000000 00000000 0321d558 0321d558ChildsDraw childnodeesi=0321d558 ---node 40321d5a0 00000000 00000000 0321d628 0321d628ChildsDraw childnodeesi=0321d628 ---node 50321d670 00000000 00000000 00000000 00000000call Take_Fill_Node0016e860 0321d628 03213ba0 0016e87c 00000000 ---node5 *(node5+0x68)offset4803213be8 00000000 0321ba70 00000000 0000000003213bf8 00000000 41700000 00000000 0000000003213c08 3f800000 3f800000 00000000 0000000003213c18 00000011 00000000 18bd34db 8800000003213c28 0321c788 00000000 00000000 0000000003213c38 00000000 00000000 00000000 0000000003213c48 00000000 00000000 00000000 0000000003213c58 00000000 00000000 00000000 00000000call Take_Fill_Node0016e9b4 0321d558 03213870 0016e9d0 00000000 ---node4 *(node4+0x68)offset48032138b8 00000000 0321b9e0 00000000 00000000032138c8 00000000 41200000 00000000 00000000032138d8 3f800000 3f800000 00000000 00000000032138e8 00000011 00000000 18bd3441 88000000032138f8 0321c788 00000000 00000000 0000000003213908 00000000 00000000 00000000 0000000003213918 00000000 00000000 00000000 0000000003213928 00000000 00000000 00000000 00000000call Take_Fill_Node0016eb08 0321d488 032135c8 03213298 00000000 ---node3 *(node3+0x68)offset4803213610 00000000 0321b950 00000000 0000000003213620 00000000 00000000 00000000 0000000003213630 3f800000 3f800000 00000000 0000000003213640 00000011 00000000 18bd3596 8800000003213650 0321c788 00000000 00000000 0000000003213660 00000000 00000000 00000000 0000000003213670 00000000 00000000 00000000 0000000003213680 00000000 00000000 00000000 00000000call Take_Fill_Node0016ec5c 0321d3b8 03213320 03213298 00000000 ---node2 *(node2+0x68)offset4803213368 00000000 0321b8c0 00000000 0000000003213378 00000000 00000000 00000000 0000000003213388 3f800000 3f800000 00000000 0000000003213398 00000011 00000000 18bd352b 88000000032133a8 0321c788 00000000 00000000 00000000032133b8 00000000 00000000 00000000 00000000032133c8 00000000 00000000 00000000 00000000032133d8 00000000 00000000 00000000 00000000call Take_Fill_Node0016edb0 0321c918 03213fe0 032140f0 00000000 ---node1 *(node1+0x68)offset4803214028 0321d1e8 0321c788 00000000 0000001403214038 00000000 00000000 00000000 0000000003214048 03208ff8 00000014 0320c008 0321417803214058 0321bdd0 00000000 18bd3b53 8800000003214068 0321c918 00000000 00000000 0000000003214078 00000000 00000000 00000000 0000000003214088 00000000 00000000 00000000 0000000003214098 00000000 00000000 00000000 00000000eax=00000000 ebx=00000000 ecx=03216d58 edx=0016ecc0 esi=03216d58 edi=00000004eip=68881a6b esp=0016eda0 ebp=0016eee4 iopl=0 nv up ei pl nz ac pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216rt3d!e3_LAYER::DeleteThis+0x351:68881a6b 69ffa0000000 imul edi,edi,0A0h0:000> dd 0321d1e8+540321d23c 52520026 13b80100 00140307 00000000 ---52520026 非法的值0321d24c 00000000 00000000 1e080000 003003220321d25c 00000000 00000000 00000000 000000000321d26c 00000000 00000000 00000000 000000000321d27c 63380000 00000306 64680000 000003060321d28c b3bc0000 00240206 00000000 000300000321d29c 00000000 00000000 00000000 000000000321d2ac 00000000 00000000 fa3a0000 4d24c105 |
初步从上面的打印日志来看,是第一个node节点出了问题unkown_class=*(node1+0×68) ; *(*(unkown_class+0×48)+0×54)=0×52520026
Node+0×68是什么时候初始化的呢,恢复虚拟机快照,重新来过,在第一个node子节点分配成功后断下来 然后下 ba w 1 (node+0×68)的访问断点。
(这里分享个调试的技巧 可以用虚拟机来保存开始调试时候的状态,这里以后重新调试的时候直接恢复虚拟机快照,堆分配的地址都是一样的,可以直接下访问断点。)
|
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
|
char __userpurge e3_NODE__SetObject(int a1, int node, int a3){ int v3; // eax@1 int v4; // ebx@2 int v6; // [sp-4h] [bp-Ch]@2 v3 = *(_DWORD *)(node + 0x68); if ( a3 != v3 ) { v6 = a1; v4 = *(_DWORD *)(node + 0x68); if ( v3 ) (*(void (__stdcall **)(int, int))(*(_DWORD *)v3 + 48))(v3, node); *(_DWORD *)(node + 0x68) = a3; a3=unkown_class 这里进行的初始化 if ( a3 ) { (*(void (__stdcall **)(int, int))(*(_DWORD *)a3 + 44))(a3, node); (*(void (__stdcall **)(_DWORD))(**(_DWORD **)(node + 104) + 4))(*(_DWORD *)(node + 104)); } (*(void (__stdcall **)(int, signed int, int, int))(*(_DWORD *)node + 52))(node, 1006, v4, v6); if ( v4 ) (*(void (__stdcall **)(int))(*(_DWORD *)v4 + 8))(v4); (*(void (__cdecl **)(int))(*(_DWORD *)node + 224))(node); sub_1013C568(*(_DWORD *)(node + 32)); } return 1;} |
将a3赋给node+0×68偏移处,此时*(a3+48)+54已经是非法值了
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
eax=00000000 ebx=00000000 ecx=03372b58 edx=688d078c esi=03166560 edi=03373360eip=68855496 esp=002dd5b0 ebp=03373360 iopl=0 nv up ei pl nz na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206rt3d!e3_NODE::SetObject+0x24:68855496 7410 je rt3d!e3_NODE::SetObject+0x36 (688554a8) [br=0]0:000> dd 03373360+54033733b4 52520034 57b80100 00140337 00000000 ------此时已经是52520034 了033733c4 00000000 00000000 86580000 00300337033733d4 00000000 00000000 00000000 00000000033733e4 00000000 00000000 00000000 00000000033733f4 98580000 00000337 98f00000 0000033703373404 bef40000 00240329 00000000 0003000003373414 00000000 00000000 00000000 0000000003373424 00000000 00000000 00000000 00000000 |
继续往上追
asm in 3difr.x3d
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
text:10002DBD mov edi, [esp+8+arg_0].text:10002DC1 mov esi, [esp+8+arg_4].text:10002DC5 mov edx, [edi].text:10002DC7 mov eax, [edx+0C8h].text:10002DCD push esi ; esi 为某个对象首地址.text:10002DCE push edi.text:10002DCF call eax //e3_NODE__SetObject 3difr!E3DLLFunc+0xb3fxt:1000415B push edx.text:1000415C push eax ////---.text:1000415D push ebp.text:1000415E push esi.text:1000415F call sub_10002D00.text:10004164 add esp, 10h |
bu 3difr!E3DLLFunc+0xb3f
bu !3difr+415F
bu !3difr+401F
bu !3difr+2b91 “.if(1){db poi(poi(esp))}”
流程太复杂 前面追踪的都不太记得了。。。
//猜测那个03373360 也是一个OBJ对象,因此直接在这里下断点 这里是obj分配内存然后初始化的地方。()
bu !rt3d+158DF8
这里为什么会猜测这个03373360是以OBJ对象呢,看下面
|
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
|
Rt3d!dll.text:101594DD sub_101594DD proc near ; DATA XREF: .rdata:101DFA20o.text:101594DD.text:101594DD arg_0 = dword ptr 4.text:101594DD arg_4 = dword ptr 8.text:101594DD.text:101594DD push esi.text:101594DE push edi.text:101594DF push 158h ; unsigned int.text:101594E4 call ??2@YAPAXI@Z ; operator new(uint) 分配一个OBJ对象eax=033784a8 ebx=033751c8 ecx=00000158 edx=03378608 esi=033751c8 edi=00000000eip=688494e9 esp=002ddd40 ebp=002de0c8 iopl=0 nv up ei pl nz na po nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202rt3d!QUAT::QUAT+0xcb8d:688494e9 85c0 test eax,eax0:000> dd 033784a8+54033784fc bf7fffff 00000000 00000000 00000000 刚申请时的内存里面填充了随机的数据0337850c bf7fffff 00000000 3f7fffff 000000000337851c 00000000 13000013 0029590f 0337f5700337852c 01fff998 00000001 00000003 000000000337853c 00000001 00000001 00000002 000000060337854c 00000004 00000001 00000000 000000020337855c 00000008 00000000 00000000 000000010337856c 00000002 00000009 00000001 00000001.text:101594E9 test eax, eax.text:101594EB mov edi, [esp+0Ch+arg_0].text:101594EF pop ecx.text:101594F0 jz short loc_10159500.text:101594F2 push dword ptr [edi+20h].text:101594F5 mov ecx, eax.text:101594F7 call sub_10158DF8.text:101594FC mov esi, eax.text:101594FE jmp short loc_10159502.text:10159500 ; ---------------------------------------------------------------------------.text:10159500.text:10159500 loc_10159500: ; CODE XREF: sub_101594DD+13j.text:10159500 xor esi, esi.text:10159502.text:10159502 loc_10159502: ; CODE XREF: sub_101594DD+21j.text:10159502 push 0.text:10159504 push [esp+0Ch+arg_4].text:10159508 mov ecx, edi.text:1015950A push esi.text:1015950B call sub_10155AA3 从参数一对象中直接拷贝了0x54偏移的成员给予这个OBJ 因此此时需要追踪这个参数一对象什么时候初始化的+54偏移成员变量,而这个参数一 就是 03373360 ,因此猜测也是一个OBJ对象.text:10159510 test eax, eax.text:10159512 jge short loc_10159528.text:10159514 test esi, esi.text:10159516 jz short loc_10159526.text:10159518 mov ecx, esi.text:1015951A call sub_10155E10.text:1015951F push esi ; void *.text:10159520 call ??3@YAXPAX@Z ; operator delete(void *).text:10159525 pop ecx.text:10159526.text:10159526 loc_10159526: ; CODE XREF: sub_101594DD+39j.text:10159526 xor esi, esi.text:10159528.text:10159528 loc_10159528: ; CODE XREF: sub_101594DD+35j.text:10159528 pop edi.text:10159529 mov eax, esi.text:1015952B pop esi.text:1015952C retn 8.text:1015952C sub_101594DD endp |
Rt3d!dll //这里进行OBJ对象的初始化 OBJ对象大小0×158
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int __thiscall sub_10158DF8(void *OBJ, int a2){ int Temp_OBJ; // esi@1 Temp_OBJ = (int)OBJ; e3_OBJECT__e3_OBJECT(OBJ); *(_DWORD *)Temp_OBJ = &off_101DF9BC; e3_GENERIC__Init(Temp_OBJ, 0x158u); if ( a2 ) sub_1014D0F6(Temp_OBJ, a2); *(_DWORD *)(Temp_OBJ + 0x50) = 7; *(_BYTE *)(Temp_OBJ + 0x58) = 0; *(_BYTE *)(Temp_OBJ + 0x59) = 1; return Temp_OBJ;} |
在分配OBJ对象之后 ,此时在这下访问断点ba w 1 03373360+0×54
|
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
|
addchildBreakpoint 9 hiteax=52520034 ebx=00717498 ecx=00747a70 edx=007479f0 esi=00000024 edi=03373360eip=69d9b785 esp=002dd4f8 ebp=01ff0708 iopl=0 nv up ei pl zr na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=000002463difr!E3DLLFunc+0x94f5:69d9b785 e86e460200 call 3difr!e3_SORTEDCOLLECTION::Create+0xc4 (69dbfdf8)//上一条指令修改了03373360+0x540:000> dd 03373360+54033733b4 52520034 56000100 00140337 00000000033733c4 00000000 00000000 69b00000 00300337033733d4 00000000 00000000 00000000 00000000033733e4 00000000 00000000 00000000 00000000033733f4 a7a00000 00000337 a8380000 0000033703373404 bef40000 00240329 00000000 0003000003373414 00000000 00000000 00000000 0000000003373424 00000000 00000000 00000000 00000000.text:1000B759 mov ecx, [esp+78h+var_5C].text:1000B75D push edi.text:1000B75E call sub_10008780.text:1000B763 mov ebx, eax.text:1000B765 mov eax, [esp+78h+var_60].text:1000B769 cmp dword ptr [eax+18h], 1.text:1000B76D jnz short loc_1000B7B7.text:1000B76F test ebx, ebx.text:1000B771 jz short loc_1000B799.text:1000B773 cmp dword ptr [ebx], 1.text:1000B776 jnz short loc_1000B799.text:1000B778 mov ecx, [ebx+4].text:1000B77B mov edx, [esp+78h+var_58].text:1000B77F mov eax, [ecx].text:1000B781 push edx ; void *.text:1000B782 mov [edi+54h], eax.text:1000B785 call ??_V@YAXPAX@Z ; operator delete[](void *)0:000> db ecx00747a70 34 00 52 52 52 00 80 3f-b7 48 9c 4a 64 4d 00 88 4.RRR..?.H.JdM..00747a80 42 6f 78 30 31 52 58 00-a9 48 9c 4a 00 00 00 88 Box01RX..H.J....00747a90 42 6f 78 30 31 52 58 00-ab 48 9c 4a 00 00 00 8c Box01RX..H.J....00747aa0 90 64 16 03 00 00 00 00-ad 48 9c 4a 00 00 00 8c .d.......H.J....00747ab0 e0 c6 36 03 58 e8 29 03-af 48 9c 4a 00 00 00 8c ..6.X.)..H.J....00747ac0 00 00 00 00 ec 41 0e 02-a1 48 9c 4a 00 00 00 88 .....A...H.J....00747ad0 c0 63 16 03 f0 63 16 03-a3 48 9c 4a 64 4d 00 88 .c...c...H.JdM..00747ae0 70 00 72 00 63 00 00 00-a5 48 9c 4a 00 00 00 88 p.r.c....H.J.... |
这里突然想到了一个跟踪数据流的好办法 对于地址不固定的堆来说(哈哈)利用前面的虚拟机快照 直接对 00747a70 下访问断点ba w 1 00747a70 ba w 1 033684c8
第二次断下后
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Asm in 3difr.text:100045CE push edx ; Src.text:100045CF push eax ; Dst.text:100045D0 mov [esp+34h+var_4], 0FFFFFFFFh.text:100045D8 call memcpyedx指向// 0337343a 52 52 52 52 52 01 00 00-00 a6 04 a8 96 b9 3f c5 RRRRR.........?.// 0337344a 43 b2 df 2a 31 b5 56 93-40 00 01 00 00 00 00 00 C..*1.V.@.......// 0337345a 00 05 00 52 52 52 52 52-01 00 00 00 01 00 2e 01 ...RRRRR........// 0337346a 00 76 00 00 00 00 45 ff-ff ff 23 00 00 00 00 00 .v....E...#.....// 0337347a 00 00 09 00 43 43 43 43-42 6f 78 30 31 02 00 00 ....CCCCBox01...// 0337348a 00 00 00 00 00 01 00 00-00 00 00 00 00 06 00 42 ...............B// 0337349a 6f 02 00 00 00 00 16 ff-ff ff 30 00 00 00 00 00 o.........0.....// 033734aa 00 00 01 00 52 01 00 00-00 a6 04 a8 96 b9 3f c5 ....R.........?.拷贝长度是0x5 |
在继续
|
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 gBreakpoint 9 hit0:000> reax=00550034 ebx=0000001a ecx=00000056 edx=00000055 esi=00776940 edi=00747a68eip=77262d75 esp=002dd41c ebp=002dd450 iopl=0 ov up ei pl nz na po nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000a02ntdll!RtlpLowFragHeapFree+0xa6:77262d75 2b7df4 sub edi,dword ptr [ebp-0Ch] ss:0023:002dd444=007478a80:000> kbChildEBP RetAddr Args to Child002dd450 77262ce8 00747a70 00717570 00000000 ntdll!RtlpLowFragHeapFree+0xa6 //00747a70指向的内存被释放002dd468 757cc3d4 007e0000 00000000 00747a70 ntdll!RtlFreeHeap+0x105002dd47c 71664c39 007e0000 00000000 00747a70 kernel32!HeapFree+0x14002dd4c8 69da181d 00747a70 00000000 002dde98 MSVCR80!free+0xcdWARNING: Stack unwind information not available. Following frames may be wrong.002dd518 69d9372b 00000000 002dde98 00000002 3difr!E3DLLFunc+0xf58d002dd530 69da039a 002dde90 176fc977 002dde90 3difr!E3DLLFunc+0x149b002dd550 77262fe7 77262e82 00000020 176fc953 3difr!E3DLLFunc+0xe10a002dd5d4 687219e8 03373360 0000017c 69d92f36 ntdll!RtlpLowFragHeapAllocFromContext+0xaec00000000 00000000 00000000 00000000 00000000 rt3d!V4CUnloadRT+0x2b278此时0:000> dd 00747a7000747a70 52520034 3f800052 4a9c48b7 88004d6400747a80 30786f42 00585231 4a9c48a9 8800000000747a90 30786f42 00585231 4a9c48ab 8c00000000747aa0 03166490 00000000 4a9c48ad 8c00000000747ab0 0336c6e0 0329e858 4a9c48af 8c00000000747ac0 00000000 020e41ec 4a9c48a1 8800000000747ad0 031663c0 031663f0 4a9c48a3 88004d6400747ae0 00720070 00000063 4a9c48a5 88000000 |
内存释放掉之后 下面又重新申请了这个地方的内存00747a70
|
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
|
10009DEB or ecx, eax.text:10009DED push ecx ; unsigned int.text:10009DEE call j_??2@YAPAXI@Z ; operator new(uint).text:10009DF3 add esp, 4.text:10009DF6 test esi, esi.text:10009DF8 mov [ebp+4], eax //eax = 00747a70.text:10009DFB jbe loc_10009E89.text:10009E01.text:10009E01 loc_10009E01: ; CODE XREF: sub_10009D00+183j.text:10009E01 push 1.text:10009E03 push 4.text:10009E05 mov ecx, edi.text:10009E07 call sub_10002A00.text:10009E0C test eax, eax.text:10009E0E jz short loc_10009E7E.text:10009E10 mov eax, [eax].text:10009E12 test eax, eax.text:10009E14 jbe short loc_10009E7E.text:10009E16 mov [esp+28h+var_10], eax.text:10009E1A lea ebx, [ebx+0].text:10009E20.text:10009E20 loc_10009E20: ; CODE XREF: sub_10009D00+178j.text:10009E20 mov ecx, edi.text:10009E22 call sub_10004520.text:10009E27 mov esi, eax.text:10009E29 mov eax, [esi].text:10009E2B test eax, eax.text:10009E2D jz short loc_10009E34.text:10009E2F cmp byte ptr [eax], 0.text:10009E32 jnz short loc_10009E38.text:10009E34.text:10009E34 loc_10009E34: ; CODE XREF: sub_10009D00+12Dj.text:10009E34 xor eax, eax.text:10009E36 jmp short loc_10009E45.text:10009E38 ; ---------------------------------------------------------------------------.text:10009E38.text:10009E38 loc_10009E38: ; CODE XREF: sub_10009D00+132j.text:10009E38 mov eax, [esi+4].text:10009E3B push 0 ; float.text:10009E3D push eax ; wchar_t *.text:10009E3E mov ecx, edi.text:10009E40 call sub_100084B0.text:10009E45.text:10009E45 loc_10009E45: ; CODE XREF: sub_10009D00+136j.text:10009E45 mov ecx, [ebp+4].text:10009E48 mov [ecx+ebx*4], eax.text:10009E4B mov eax, [esi].text:10009E4D test eax, eax.text:10009E4F jz short loc_10009E5A.text:10009E51 push eax ; void *.text:10009E52 call ??_V@YAXPAX@Z ; operator delete[](void *).text:10009E57 add esp, 4.text:10009E5A.text:10009E5A loc_10009E5A: ; CODE XREF: sub_10009D00+14Fj.text:10009E5A mov eax, [esi+4].text:10009E5D test eax, eax |
|
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
|
c in 3difi v10 = sub_10002A00(4, 1); if ( v10 ) { v11 = *(_DWORD *)v10; v10=03373493 if ( v11 ) //这里v11=0 直接跳过了初始化 导致后面使用了已经释放掉的内存 { v18 = v11; do { v14 = sub_10004520(v2); v13 = v14; v12 = *(_DWORD *)v14; if ( v12 && *(_BYTE *)v12 ) v15 = sub_100084B0(*(wchar_t **)(v13 + 4), 0.0); else v15 = 0; *(_DWORD *)(*(_DWORD *)(v5 + 4) + 4 * v1) = v15;// 这里初始化刚刚分配的内存 if ( *(_DWORD *)v13 ) operator delete__(*(void **)v13); if ( *(_DWORD *)(v13 + 4) ) operator delete__(*(void **)(v13 + 4)); operator delete((void *)v13); } while ( v18-- != 1 ); v7 = v17; } } ++v1; }while ( v1 < v7 ); |
Summary
从上面的分析可以知道,漏洞成因是对新分配的内存没有正确的初始化,导致重用了之前分配的内存空间,而刚好之前分配的内存空间的数据来自文件offset =0×10a 。而未初始化的变量刚好是某个对象的首地址,从而有机会导致任意代码执行。
The Final Reason
这里分析为什么上面的初始化被绕过
对10002A00函数下断点
Bu !3difr+2a00
|
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
|
eax=00747a70 ebx=00000000 ecx=002dde98 edx=00680048 esi=00000001 edi=002dde98eip=69d92a00 esp=002dd4e8 ebp=00717498 iopl=0 nv up ei pl nz na po nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=000002023difr!E3DLLFunc+0x770:69d92a00 56 push esi0:000> dd ecx+40002dded8 00000133 00000000 ffffff14 0000017c //133是偏移002ddee8 0000011c 00000000 00000001 031ea1b8002ddef8 03299108 03298c28 03372378 033723a8002ddf08 033723d8 03372408 03372438 0329be18002ddf18 0329be58 00000000 00000000 031ea398002ddf28 00000000 002de6e0 69dc0deb 00000000002ddf38 6887e073 00000001 002de678 0336b970002ddf48 03363920 00000001 002de678 0336b9700:000> dd ecx+34002ddecc 03373360 ffffff45 00000024 00000133 //03373360 指向文件中offset=30h002ddedc 00000000 ffffff14 0000017c 0000011c002ddeec 00000000 00000001 031ea1b8 03299108002ddefc 03298c28 03372378 033723a8 033723d8002ddf0c 03372408 03372438 0329be18 0329be58002ddf1c 00000000 00000000 031ea398 00000000002ddf2c 002de6e0 69dc0deb 00000000 6887e073002ddf3c 00000001 002de678 0336b970 033639200:000>0:000> db 0337336003373360 09 00 43 43 43 43 42 6f-78 30 31 00 00 00 00 00 ..CCCCBox01.....03373370 00 00 00 00 05 00 00 00-22 ff ff ff 5e 00 00 00 ........"...^...03373380 00 00 00 00 09 00 43 43-43 43 42 6f 78 30 31 01 ......CCCCBox01.03373390 00 00 00 00 00 00 00 81-3f 00 00 00 00 00 00 00 ........?.......033733a0 00 00 00 00 00 00 00 00-00 00 00 81 3f 00 00 00 ............?...033733b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 81 ................033733c0 3f 00 00 00 00 54 8a 55-c0 a2 02 7c c2 00 00 00 ?....T.U...|....033733d0 00 00 00 81 3f 07 00 42-6f 78 30 31 52 58 01 00 ....?..Box01RX..0:000> db 03373360 +13303373493 00 00 00 00 06 00 42 6f-02 00 00 00 00 16 ff ff ......Bo........033734a3 ff 30 00 00 00 00 00 00-00 01 00 52 01 00 00 00 .0.........R....033734b3 a6 04 a8 96 b9 3f c5 43-b2 df 2a 31 b5 56 93 40 .....?.C..*1.V.@033734c3 00 01 00 00 00 00 00 00-01 00 52 01 00 00 00 01 ..........R.....033734d3 00 2e 01 00 76 00 00 00-00 00 00 00 00 00 00 00 ....v...........033734e3 00 00 00 00 00 ee 0d f6-58 2d 59 29 08 80 2e 35 ........X-Y)...5033734f3 03 68 f0 2c 03 0c 00 00-00 c0 d0 e0 f0 98 66 b6 .h.,..........f.03373503 49 00 00 00 80 1e 00 00-00 00 00 00 00 05 00 04 I............... |
将shader_list_count改成1 发现漏洞就不触发了,上面那地方就可以正常初始化了。
010检测该漏洞
Shader_list_count!=0
Sls.shader_count=0
Exploit
自己分析去
POC
REF http://www.9bplus.com/file/tester.pdf

评论关闭。