-
-
[原创] cve-2012-0158漏洞分析
-
2016-11-10 10:45 4240
-
参考《漏洞战争》分析下,记下自己的心得,主要还是汇编代码比较麻烦。
环境是xpsp3+word2003(11.8324.8324):
打开windbg、word软件,windbg附加word软件进程,word打开poc.doc文件,发现windbg已经断下,eip指向0x41414141,说明已经发生了溢出,eip被控制了。
看一下栈回溯:
说明栈回溯已经被破坏掉了,看一下栈中的信息:
根据相关资料,可以知道这个漏洞就是在组件mscomctl.ocx中的,所以275a273d MSCOMCTL!DllGetClassObject+0xb456保存的可能是返回地址,查看一下这个地址之前的汇编代码:
可以看到漏洞很可能出现在0x275a2738地址call的函数里边。
反编译一下函数MSCOMCTL!DllGetClassObject+0xb1b9 :
我们将该函数MSCOMCTL!DllGetClassObject+0xb1b9命名为vul。
将调用vul的函数命名为vul_parent:
查看一下调用函数:
函数0x275a26fa就是函数vul_parent,查看一下完整汇编代码。
重新加载poc.doc,因为mscomctl.ocx是word在加载poc.doc的时候才加载的,需要在加载mscomctl.ocx的时候断下来,然后才可以在函数vul_parent上下断点。
操作如下:
打开windbg、word软件,windbg附加word软件进程,sxe ld mscomctl.ocx,g,word打开poc.doc文件,windbg成功在加载MSCOMCTL.OCX时断下:
在函数vul_parent下断并运行,成功在函数vul_parent 断下:
首先记录一些重要数据,
可以看到在vul_parent函数内部,ebp=0x001216fc,在栈上分配了0x14大小的空间
在vul函数下断点并运行:
此时可以看到ebp=0x001216c8
在0x275a24fe下断点,并且运行:
可以看到此时edi=0x001216f4,ecx=0x000020a0,刚才分析过在vul_parent函数中,ebp=0x001216fc,说明此时如果ecx=4时,esi+0xc正好覆盖了函数返回地址,而此时ecx远远大于4,说明覆盖了返回地址,导致了溢出,此时如果直接运行可以看到eip=0x41414141,已经被我们控制了
现在的问题就是ecx,edi,esi是有什么控制的,我们在地址0x275a24fe往上查找(即内存低址)
SHR ECX,2即逻辑右移四位,相当于除以四,说明在这条指令前是要移动的字节数,这条指令后是要移动的dword数,在0x275a24e8 call dword ptr [ecx+0Ch]之后,可以看到ecx=edi,edi=dword ptr [ebp+8]即函数vul的第一个参数,esi=dword ptr [ebp+c],即函数vul的第二个参数,我们重新运行程序,在0x275a2738和0x275a24e8上分别下断(需要在0x275a2738上下断,不然可能会多次断下):
可以看到函数vul的参数信息:
可以看到第三个参数 poi(esp+0x8)=00008282=0x000020a0*4
第一个参数poi(esp)就是后来275a24fe rep movs dword ptr es:[edi],dword ptr [esi]中edi的值
单步跟进
查看执行0x275a24b6 call dword ptr [eax+0Ch] 前后各寄存器的值及栈中的数据:
可以看到函数执行前后vul函数的三个参数没有发生变化(ebp+8 ebp+c ebp+0x10)
注意这几个值: edi=esi=0
继续单步跟进:
此时调用的是在堆上分配内存的函数RtlAllocateHeap,函数定义:
可以看到在堆上分配大小为0x8282的内存,此处的0x8282即来自edi也就是vul函数的第三个参数。
继续单步:
此处eax就是分配内存的首地址
继续单步走:
分析一下这个函数使mso组件中的,第一个参数是对象地址,第二个参数是刚才在堆上分配的内存首地址,第三个参数分配内存的大小,第四个参数是0x0,可以看到这个函数可能就是往刚才分配的内存上写数据(数据来源是从poc.doc上读取的数据),注意此时edi=0x8282,poi(ebp+8)=001216f4 poi(ebp+c)=03646008,此处的poi(ebp+c)的值是0x275a24d9 mov dword ptr [ebp+0Ch],eax传入的, 即堆上分配的内存。
单步走一下:
函数执行成功返回0,堆分配内存中新写入了数据,这些数据来自poc.doc文件
经过上边分析,我们总结一下,在函数vul中,275a24fe rep movs dword ptr es:[edi],dword ptr [esi] ,此处ecx来自->275a24fb shr ecx,2 ->0x275a24f4 mov ecx,edi->0x275a24bd mov edi,dword ptr [ebp+10h] ->vul的第三个参数,说明vul函数的第三个参数除以四就是ecx
esi来自->275a24f1 mov esi,dword ptr [ebp+0Ch]->275a24d9 mov dword ptr [ebp+0Ch],eax ->275a24d1 call dword ptr [MSCOMCTL+0x1168 (27581168)] 说明esi来自堆分配的一块大小为0x8282的内存,内存被函数275a24e8 call dword ptr [ecx+0Ch] 写入poc.doc中的数据
edi来自275a24f6 mov edi,dword ptr [ebp+8] 即函数vul的第一个参数
上边已经分析完了函数vul,我们继续分析vul_parent函数,从0x275a2738往上分析(即内存低址):
函数vul的第一个参数来自0x275a2737 push eax ->275a2733 lea eax,[ebp-8] 即函数vul_parent的第一个参数,此时是在ebp低0x8的地址处,如果此时复制的长度超过0x8,就会覆盖ebp,如果超过0xc,就会覆盖到vul_parent的返回地址,就可以造成栈溢出
看一下275a2726 837df408 cmp dword ptr [ebp-0Ch],8 有个条件判断语句,如果函数vul_parent的第二个参数小于8的话,就跳转,大于等于8的话就继续执行,此处的vul_parent的第二个参数正好是vul函数中275a24fe rep movs dword ptr es:[edi],dword ptr [esi] 复制时ecx*4的值,由于这个错误的判断 ,正好造成了栈溢出。
vul函数的第三个参数来自0x275a2730 push dword ptr [ebp-0Ch] 我们来重点分析一下这个参数是来自哪里
在0x275a270d处调用vul函数,第一个参数来自ebp-14h,即写入的地址,第三个参数是0xc,即写入的字节数,从ebp-14h到ebp-8h,此时正好覆盖了275a2730 push dword ptr [ebp-0Ch] 的内存,说明0x275a270d调用的vul函数写入的数据覆盖了0x275a2738处调用vul函数的第三个参数的数据,也就是poc.doc(0x275a270d调用的vul函数调用了poc.doc中的数据)中的数据最终改写了275a24fe rep movs dword ptr es:[edi],dword ptr [esi] 中ecx的值。
最后总结一下:
在vul_parent第一次调用函数vul,写入0xc的数据,写入的数据内存正好覆盖了第二次调用函数vul的第三个参数的值,这个值决定了vul复制数据的字节数,本来vul_parent只分配了0x14的栈空间,第一次已经用去了0xc的大小,还有0x8的空间,如果此时第二次调用vul的第三个参数大于8就可以覆盖ebp,甚至函数vul_parent的返回地址
所有问题的症结就在于
275a2726 837df408 cmp dword ptr [ebp-0Ch],8
1. 275a272a 0f822f030300 jb MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
有个条件判断语句写错了,应该是判断当 dword ptr [ebp-0Ch]大于8的时候应该跳转结束,这里正好写反了。
其实用IDA分析一下更简单
环境是xpsp3+word2003(11.8324.8324):
打开windbg、word软件,windbg附加word软件进程,word打开poc.doc文件,发现windbg已经断下,eip指向0x41414141,说明已经发生了溢出,eip被控制了。
0:009> g
(15c.510): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=024957b8 ecx=7c93005d edx=00140608 esi=0022ed4c edi=00000000
eip=41414141 esp=0012170c ebp=00000000 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
41414141 ?? ???
看一下栈回溯:
0:000> kvn
# ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 00121708 00000000 00000000 00000000 00000000 0x41414141
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00121708 00000000 00000000 00000000 00000000 0x41414141
说明栈回溯已经被破坏掉了,看一下栈中的信息:
dps esp-0x50:
0:000> dps esp-0x50
001216bc 0022ed4c
001216c0 024957b8
001216c4 00008282
001216c8 001216fc
001216cc 275a273d MSCOMCTL!DllGetClassObject+0xb456
001216d0 001216f4
001216d4 001c8008
001216d8 00008282
001216dc 00000000
001216e0 0022ed4c
001216e4 024957b8
001216e8 6a626f43
001216ec 00000064
001216f0 00008282
001216f4 00000000
001216f8 00000000
001216fc 00000000
00121700 41414141
00121704 00000000
00121708 00000000
0012170c 00000000
00121710 00000000
00121714 00000000
根据相关资料,可以知道这个漏洞就是在组件mscomctl.ocx中的,所以275a273d MSCOMCTL!DllGetClassObject+0xb456保存的可能是返回地址,查看一下这个地址之前的汇编代码:
0:000> ub 275a273d
MSCOMCTL!DllGetClassObject+0xb439:
275a2720 0f8539030300 jne MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
275a2726 837df408 cmp dword ptr [ebp-0Ch],8
275a272a 0f822f030300 jb MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
275a2730 ff75f4 push dword ptr [ebp-0Ch]
275a2733 8d45f8 lea eax,[ebp-8]
275a2736 53 push ebx
275a2737 50 push eax
275a2738 e863fdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
可以看到漏洞很可能出现在0x275a2738地址call的函数里边。
反编译一下函数MSCOMCTL!DllGetClassObject+0xb1b9 :
0:000> uf MSCOMCTL!DllGetClassObject+0xb1b9
MSCOMCTL!DllGetClassObject+0xb1b9:
275a24a0 55 push ebp
275a24a1 8bec mov ebp,esp
275a24a3 51 push ecx
275a24a4 53 push ebx
275a24a5 8b5d0c mov ebx,dword ptr [ebp+0Ch]
275a24a8 56 push esi
275a24a9 33f6 xor esi,esi
275a24ab 8b03 mov eax,dword ptr [ebx]
275a24ad 57 push edi
275a24ae 56 push esi
275a24af 8d4dfc lea ecx,[ebp-4]
275a24b2 6a04 push 4
275a24b4 51 push ecx
275a24b5 53 push ebx
275a24b6 ff500c call dword ptr [eax+0Ch]
275a24b9 3bc6 cmp eax,esi
275a24bb 7c78 jl MSCOMCTL!DllGetClassObject+0xb24e (275a2535)
MSCOMCTL!DllGetClassObject+0xb1d6:
275a24bd 8b7d10 mov edi,dword ptr [ebp+10h]
275a24c0 397dfc cmp dword ptr [ebp-4],edi
275a24c3 0f8533150300 jne MSCOMCTL!DllGetClassObject+0x3c715 (275d39fc)
MSCOMCTL!DllGetClassObject+0xb1e2:
275a24c9 57 push edi
275a24ca 56 push esi
275a24cb ff3520e06227 push dword ptr [MSCOMCTL!DllUnregisterServer+0x2dfe8 (2762e020)]
275a24d1 ff1568115827 call dword ptr [MSCOMCTL+0x1168 (27581168)]
275a24d7 3bc6 cmp eax,esi
275a24d9 89450c mov dword ptr [ebp+0Ch],eax
275a24dc 0f8424150300 je MSCOMCTL!DllGetClassObject+0x3c71f (275d3a06)
MSCOMCTL!DllGetClassObject+0xb1fb:
275a24e2 8b0b mov ecx,dword ptr [ebx]
275a24e4 56 push esi
275a24e5 57 push edi
275a24e6 50 push eax
275a24e7 53 push ebx
275a24e8 ff510c call dword ptr [ecx+0Ch]
275a24eb 8bf0 mov esi,eax
275a24ed 85f6 test esi,esi
275a24ef 7c31 jl MSCOMCTL!DllGetClassObject+0xb23b (275a2522)
MSCOMCTL!DllGetClassObject+0xb20a:
275a24f1 8b750c mov esi,dword ptr [ebp+0Ch]
275a24f4 8bcf mov ecx,edi
275a24f6 8b7d08 mov edi,dword ptr [ebp+8]
275a24f9 8bc1 mov eax,ecx
275a24fb c1e902 shr ecx,2
275a24fe f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
275a2500 8bc8 mov ecx,eax
275a2502 8b4510 mov eax,dword ptr [ebp+10h]
275a2505 83e103 and ecx,3
275a2508 6a00 push 0
275a250a 8d5003 lea edx,[eax+3]
275a250d 83e2fc and edx,0FFFFFFFCh
275a2510 2bd0 sub edx,eax
275a2512 f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
275a2514 8b0b mov ecx,dword ptr [ebx]
275a2516 52 push edx
275a2517 68e03f6327 push offset MSCOMCTL!DllUnregisterServer+0x33fa8 (27633fe0)
275a251c 53 push ebx
275a251d ff510c call dword ptr [ecx+0Ch]
275a2520 8bf0 mov esi,eax
MSCOMCTL!DllGetClassObject+0xb23b:
275a2522 ff750c push dword ptr [ebp+0Ch]
275a2525 6a00 push 0
275a2527 ff3520e06227 push dword ptr [MSCOMCTL!DllUnregisterServer+0x2dfe8 (2762e020)]
275a252d ff1574115827 call dword ptr [MSCOMCTL+0x1174 (27581174)]
275a2533 8bc6 mov eax,esi
MSCOMCTL!DllGetClassObject+0xb24e:
275a2535 5f pop edi
275a2536 5e pop esi
275a2537 5b pop ebx
275a2538 c9 leave
275a2539 c3 ret
MSCOMCTL!DllGetClassObject+0x3c715:
275d39fc b8ffff0080 mov eax,8000FFFFh
275d3a01 e92febfcff jmp MSCOMCTL!DllGetClassObject+0xb24e (275a2535)
MSCOMCTL!DllGetClassObject+0x3c71f:
275d3a06 b80e000780 mov eax,8007000Eh
275d3a0b e925ebfcff jmp MSCOMCTL!DllGetClassObject+0xb24e (275a2535)
我们将该函数MSCOMCTL!DllGetClassObject+0xb1b9命名为vul。
将调用vul的函数命名为vul_parent:
查看一下调用函数:
0:000> ub 275a273d l20
MSCOMCTL!DllGetClassObject+0xb407:
275a26ee 59 pop ecx
275a26ef 7c02 jl MSCOMCTL!DllGetClassObject+0xb40c (275a26f3)
275a26f1 33c0 xor eax,eax
275a26f3 5f pop edi
275a26f4 5e pop esi
275a26f5 5b pop ebx
275a26f6 c9 leave
275a26f7 c20800 ret 8
275a26fa 55 push ebp
275a26fb 8bec mov ebp,esp
275a26fd 83ec14 sub esp,14h
275a2700 53 push ebx
275a2701 8b5d0c mov ebx,dword ptr [ebp+0Ch]
275a2704 56 push esi
275a2705 57 push edi
275a2706 6a0c push 0Ch
275a2708 8d45ec lea eax,[ebp-14h]
275a270b 53 push ebx
275a270c 50 push eax
275a270d e88efdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
275a2712 83c40c add esp,0Ch
275a2715 85c0 test eax,eax
275a2717 7c6c jl MSCOMCTL!DllGetClassObject+0xb49e (275a2785)
275a2719 817dec436f626a cmp dword ptr [ebp-14h],6A626F43h
275a2720 0f8539030300 jne MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
275a2726 837df408 cmp dword ptr [ebp-0Ch],8
275a272a 0f822f030300 jb MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
275a2730 ff75f4 push dword ptr [ebp-0Ch]
275a2733 8d45f8 lea eax,[ebp-8]
275a2736 53 push ebx
275a2737 50 push eax
275a2738 e863fdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
函数0x275a26fa就是函数vul_parent,查看一下完整汇编代码。
0:000> uf 275a26fa
MSCOMCTL!DllGetClassObject+0xb413:
275a26fa 55 push ebp
275a26fb 8bec mov ebp,esp
275a26fd 83ec14 sub esp,14h
275a2700 53 push ebx
275a2701 8b5d0c mov ebx,dword ptr [ebp+0Ch]
275a2704 56 push esi
275a2705 57 push edi
275a2706 6a0c push 0Ch
275a2708 8d45ec lea eax,[ebp-14h]
275a270b 53 push ebx
275a270c 50 push eax
275a270d e88efdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
275a2712 83c40c add esp,0Ch
275a2715 85c0 test eax,eax
275a2717 7c6c jl MSCOMCTL!DllGetClassObject+0xb49e (275a2785)
MSCOMCTL!DllGetClassObject+0xb432:
275a2719 817dec436f626a cmp dword ptr [ebp-14h],6A626F43h
275a2720 0f8539030300 jne MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
MSCOMCTL!DllGetClassObject+0xb43f:
275a2726 837df408 cmp dword ptr [ebp-0Ch],8
275a272a 0f822f030300 jb MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
MSCOMCTL!DllGetClassObject+0xb449:
275a2730 ff75f4 push dword ptr [ebp-0Ch]
275a2733 8d45f8 lea eax,[ebp-8]
275a2736 53 push ebx
275a2737 50 push eax
275a2738 e863fdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
275a273d 8bf0 mov esi,eax
275a273f 83c40c add esp,0Ch
275a2742 85f6 test esi,esi
275a2744 7c3d jl MSCOMCTL!DllGetClassObject+0xb49c (275a2783)
MSCOMCTL!DllGetClassObject+0xb45f:
275a2746 837df800 cmp dword ptr [ebp-8],0
275a274a 8b7d08 mov edi,dword ptr [ebp+8]
275a274d 742a je MSCOMCTL!DllGetClassObject+0xb492 (275a2779)
MSCOMCTL!DllGetClassObject+0xb468:
275a274f 83650c00 and dword ptr [ebp+0Ch],0
275a2753 8d450c lea eax,[ebp+0Ch]
275a2756 53 push ebx
275a2757 50 push eax
275a2758 e82f000000 call MSCOMCTL!DllGetClassObject+0xb4a5 (275a278c)
275a275d 8bf0 mov esi,eax
275a275f 59 pop ecx
275a2760 85f6 test esi,esi
275a2762 59 pop ecx
275a2763 7c1e jl MSCOMCTL!DllGetClassObject+0xb49c (275a2783)
MSCOMCTL!DllGetClassObject+0xb47e:
275a2765 ff750c push dword ptr [ebp+0Ch]
275a2768 8d4fdc lea ecx,[edi-24h]
275a276b e81a52feff call MSCOMCTL+0x798a (2758798a)
275a2770 ff750c push dword ptr [ebp+0Ch]
275a2773 ff1540155827 call dword ptr [MSCOMCTL+0x1540 (27581540)]
MSCOMCTL!DllGetClassObject+0xb492:
275a2779 837dfc00 cmp dword ptr [ebp-4],0
275a277d 0f85e6020300 jne MSCOMCTL!DllGetClassObject+0x3b782 (275d2a69)
MSCOMCTL!DllGetClassObject+0xb49c:
275a2783 8bc6 mov eax,esi
MSCOMCTL!DllGetClassObject+0xb49e:
275a2785 5f pop edi
275a2786 5e pop esi
275a2787 5b pop ebx
275a2788 c9 leave
275a2789 c20800 ret 8
MSCOMCTL!DllGetClassObject+0x3b778:
275d2a5f b8ffff0080 mov eax,8000FFFFh
275d2a64 e91cfdfcff jmp MSCOMCTL!DllGetClassObject+0xb49e (275a2785)
MSCOMCTL!DllGetClassObject+0x3b782:
275d2a69 83c714 add edi,14h
275d2a6c 53 push ebx
275d2a6d 57 push edi
275d2a6e e8ebfdfcff call MSCOMCTL!DllGetClassObject+0xb577 (275a285e)
275d2a73 59 pop ecx
275d2a74 8bf0 mov esi,eax
275d2a76 59 pop ecx
275d2a77 e907fdfcff jmp MSCOMCTL!DllGetClassObject+0xb49c (275a2783)
重新加载poc.doc,因为mscomctl.ocx是word在加载poc.doc的时候才加载的,需要在加载mscomctl.ocx的时候断下来,然后才可以在函数vul_parent上下断点。
操作如下:
打开windbg、word软件,windbg附加word软件进程,sxe ld mscomctl.ocx,g,word打开poc.doc文件,windbg成功在加载MSCOMCTL.OCX时断下:
(900.e64): Break instruction exception - code 80000003 (first chance)
eax=7ffd4000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c92120e esp=039fffcc ebp=039ffff4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
ntdll!DbgBreakPoint:
7c92120e cc int 3
0:004> sxe ld mscomctl.ocx
0:004> g
ModLoad: 27580000 27686000 C:\WINDOWS\system32\MSCOMCTL.OCX
eax=00000000 ebx=00000000 ecx=07d50000 edx=7c92e514 esi=00000000 edi=00000000
eip=7c92e514 esp=00120194 ebp=00120288 iopl=0 nv up ei ng nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000296
ntdll!KiFastSystemCallRet:
7c92e514 c3 ret
在函数vul_parent下断并运行,成功在函数vul_parent 断下:
(7f0.8bc): Break instruction exception - code 80000003 (first chance)
eax=7ffd3000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c92120e esp=0396ffcc ebp=0396fff4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
ntdll!DbgBreakPoint:
7c92120e cc int 3
0:004> sxe ld mscomctl.ocx
0:004> g
ModLoad: 27580000 27686000 C:\WINDOWS\system32\MSCOMCTL.OCX
eax=00000000 ebx=00000000 ecx=07e10000 edx=7c92e514 esi=00000000 edi=00000000
eip=7c92e514 esp=00120194 ebp=00120288 iopl=0 nv up ei ng nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000296
ntdll!KiFastSystemCallRet:
7c92e514 c3 ret
0:000> bp 0x275a26fa
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\MSCOMCTL.OCX -
0:000> bl
0 e 275a26fa 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0xb413
0:000> g
Breakpoint 0 hit
eax=034336ec ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a26fa esp=00121700 ebp=00121724 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
MSCOMCTL!DllGetClassObject+0xb413:
275a26fa 55 push ebp
首先记录一些重要数据,
Breakpoint 0 hit
eax=034336ec ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a26fa esp=00121700 ebp=00121724 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
MSCOMCTL!DllGetClassObject+0xb413:
275a26fa 55 push ebp
0:000> dd esp
00121700 275e727b 034336ec 023a57b8 00000000
00121710 034336c8 0023f2d8 275a688f 00000001
00121720 00121744 00121744 275e75c2 034336ec
00121730 023a57b8 023a57b8 736d7449 00000064
00121740 275b0000 001217c4 275ca175 0023f4d0
00121750 023a57b8 0023f328 0023f2d8 06a9569c
00121760 abcdef01 00050000 01655d98 00000007
00121770 80000008 80000005 00000000 2758310b
0:000> p
eax=034336ec ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a26fb esp=001216fc ebp=00121724 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
MSCOMCTL!DllGetClassObject+0xb414:
275a26fb 8bec mov ebp,esp
0:000> p
eax=034336ec ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a26fd esp=001216fc ebp=001216fc iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
MSCOMCTL!DllGetClassObject+0xb416:
275a26fd 83ec14 sub esp,14h
0:000> p
eax=034336ec ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a2700 esp=001216e8 ebp=001216fc iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
MSCOMCTL!DllGetClassObject+0xb419:
275a2700 53 push ebx
可以看到在vul_parent函数内部,ebp=0x001216fc,在栈上分配了0x14大小的空间
在vul函数下断点并运行:
275a2700 53 push ebx
0:000> bp 275a24a0
0:000> bl
0 e 275a26fa 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0xb413
1 e 275a24a0 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0xb1b9
0:000> g
Breakpoint 1 hit
eax=001216e8 ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a24a0 esp=001216cc ebp=001216fc iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
MSCOMCTL!DllGetClassObject+0xb1b9:
275a24a0 55 push ebp
0:000> p
eax=001216e8 ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a24a1 esp=001216c8 ebp=001216fc iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
MSCOMCTL!DllGetClassObject+0xb1ba:
275a24a1 8bec mov ebp,esp
0:000> p
eax=001216e8 ebx=023a57b8 ecx=275b0b08 edx=00000001 esi=034336ec edi=00000000
eip=275a24a3 esp=001216c8 ebp=001216c8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
MSCOMCTL!DllGetClassObject+0xb1bc:
275a24a3 51 push ecx
此时可以看到ebp=0x001216c8
在0x275a24fe下断点,并且运行:
0:000> g
Breakpoint 2 hit
eax=00008282 ebx=023a57b8 ecx=000020a0 edx=00000000 esi=03446008 edi=001216f4
eip=275a24fe esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl nz na pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000207
MSCOMCTL!DllGetClassObject+0xb217:
275a24fe f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:000> dd esi
03446008 00000000 00000000 00000000 41414141
03446018 00000000 00000000 00000000 00000000
03446028 00000000 00000000 00000000 00000000
03446038 00000000 00000000 00000000 00000000
03446048 00000000 00000000 00000000 00000000
03446058 00000000 00000000 00000000 00000000
03446068 00000000 00000000 00000000 00000000
03446078 00000000 00000000 00000000 00000000
可以看到此时edi=0x001216f4,ecx=0x000020a0,刚才分析过在vul_parent函数中,ebp=0x001216fc,说明此时如果ecx=4时,esi+0xc正好覆盖了函数返回地址,而此时ecx远远大于4,说明覆盖了返回地址,导致了溢出,此时如果直接运行可以看到eip=0x41414141,已经被我们控制了
现在的问题就是ecx,edi,esi是有什么控制的,我们在地址0x275a24fe往上查找(即内存低址)
SHR ECX,2即逻辑右移四位,相当于除以四,说明在这条指令前是要移动的字节数,这条指令后是要移动的dword数,在0x275a24e8 call dword ptr [ecx+0Ch]之后,可以看到ecx=edi,edi=dword ptr [ebp+8]即函数vul的第一个参数,esi=dword ptr [ebp+c],即函数vul的第二个参数,我们重新运行程序,在0x275a2738和0x275a24e8上分别下断(需要在0x275a2738上下断,不然可能会多次断下):
0:000> bp 0x275a2738
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\MSCOMCTL.OCX -
0:000> bl
0 e 275a2738 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0xb451
0:000> g
Breakpoint 0 hit
eax=001216f4 ebx=023a57b8 ecx=7c93005d edx=00140608 esi=0679cd5c edi=00000000
eip=275a2738 esp=001216d0 ebp=001216fc iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
MSCOMCTL!DllGetClassObject+0xb451:
275a2738 e863fdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
0:000> dd esp
001216d0 001216f4 023a57b8 00008282 00000000
001216e0 0679cd5c 023a57b8 6a626f43 00000064
001216f0 00008282 00121744 275876c7 00121724
00121700 275e727b 0679cd5c 023a57b8 00000000
00121710 0679cd38 036520d8 275a688f 00000001
00121720 00121744 00121744 275e75c2 0679cd5c
00121730 023a57b8 023a57b8 736d7449 00000064
00121740 275b0000 001217c4 275ca175 036522d0
可以看到函数vul的参数信息:
可以看到第三个参数 poi(esp+0x8)=00008282=0x000020a0*4
第一个参数poi(esp)就是后来275a24fe rep movs dword ptr es:[edi],dword ptr [esi]中edi的值
单步跟进
0:000> p
eax=7699dd78 ebx=023a57b8 ecx=001216c4 edx=00140608 esi=00000000 edi=00000000
eip=275a24b4 esp=001216b0 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1cd:
275a24b4 51 push ecx
0:000> p
eax=7699dd78 ebx=023a57b8 ecx=001216c4 edx=00140608 esi=00000000 edi=00000000
eip=275a24b5 esp=001216ac ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1ce:
275a24b5 53 push ebx
0:000> p
eax=7699dd78 ebx=023a57b8 ecx=001216c4 edx=00140608 esi=00000000 edi=00000000
eip=275a24b6 esp=001216a8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1cf:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll -
275a24b6 ff500c call dword ptr [eax+0Ch] ds:0023:7699dd84=30ed7be6
0:000> ln 30ed7be6
(30ed7b91) mso!Ordinal1077+0x55 | (30ed7d09) mso!Ordinal6286
0:000> dd esp l10
001216a8 023a57b8 001216c4 00000004 00000000
001216b8 00000000 0679cd5c 023a57b8 7c93005d
001216c8 001216fc 275a273d 001216f4 023a57b8
001216d8 00008282 00000000 0679cd5c 023a57b8
查看执行0x275a24b6 call dword ptr [eax+0Ch] 前后各寄存器的值及栈中的数据:
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00000000
eip=275a24b9 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1d2:
275a24b9 3bc6 cmp eax,esi
0:000> dd esp l10
001216b8 00000000 0679cd5c 023a57b8 00008282
001216c8 001216fc 275a273d 001216f4 023a57b8
001216d8 00008282 00000000 0679cd5c 023a57b8
001216e8 6a626f43 00000064 00008282 00121744
可以看到函数执行前后vul函数的三个参数没有发生变化(ebp+8 ebp+c ebp+0x10)
注意这几个值: edi=esi=0
继续单步跟进:
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00000000
eip=275a24bb esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1d4:
275a24bb 7c78 jl MSCOMCTL!DllGetClassObject+0xb24e (275a2535) [br=0]
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00000000
eip=275a24bd esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1d6:
275a24bd 8b7d10 mov edi,dword ptr [ebp+10h] ss:0023:001216d8=00008282
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24c0 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1d9:
275a24c0 397dfc cmp dword ptr [ebp-4],edi ss:0023:001216c4=00008282
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24c3 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1dc:
275a24c3 0f8533150300 jne MSCOMCTL!DllGetClassObject+0x3c715 (275d39fc) [br=0]
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24c9 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1e2:
275a24c9 57 push edi
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24ca esp=001216b4 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1e3:
275a24ca 56 push esi
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24cb esp=001216b0 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1e4:
275a24cb ff3520e06227 push dword ptr [MSCOMCTL!DllUnregisterServer+0x2dfe8 (2762e020)] ds:0023:2762e020=00140000
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24d1 esp=001216ac ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb1ea:
275a24d1 ff1568115827 call dword ptr [MSCOMCTL+0x1168 (27581168)] ds:0023:27581168={ntdll!RtlAllocateHeap (7c9300c4)}
0:000> dd esp
001216ac 00140000 00000000 00008282 00000000
001216bc 0679cd5c 023a57b8 00008282 001216fc
001216cc 275a273d 001216f4 023a57b8 00008282
001216dc 00000000 0679cd5c 023a57b8 6a626f43
001216ec 00000064 00008282 00121744 275876c7
001216fc 00121724 275e727b 0679cd5c 023a57b8
0012170c 00000000 0679cd38 036520d8 275a688f
0012171c 00000001 00121744 00121744 275e75c2
此时调用的是在堆上分配内存的函数RtlAllocateHeap,函数定义:
PVOID RtlAllocateHeap( _In_ PVOID HeapHandle,_In_opt_ ULONG Flags, _In_ SIZE_T Size);
可以看到在堆上分配大小为0x8282的内存,此处的0x8282即来自edi也就是vul函数的第三个参数。
继续单步:
0:000> p
eax=03646008 ebx=023a57b8 ecx=7c9301db edx=00140608 esi=00000000 edi=00008282
eip=275a24d7 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1f0:
275a24d7 3bc6 cmp eax,esi
0:000> r eax
eax=03646008
0:000> dd eax
03646008 baadf00d baadf00d baadf00d baadf00d
03646018 baadf00d baadf00d baadf00d baadf00d
03646028 baadf00d baadf00d baadf00d baadf00d
03646038 baadf00d baadf00d baadf00d baadf00d
03646048 baadf00d baadf00d baadf00d baadf00d
03646058 baadf00d baadf00d baadf00d baadf00d
03646068 baadf00d baadf00d baadf00d baadf00d
03646078 baadf00d baadf00d baadf00d baadf00d
此处eax就是分配内存的首地址
继续单步走:
0:000> p
eax=03646008 ebx=023a57b8 ecx=7c9301db edx=00140608 esi=00000000 edi=00008282
eip=275a24d9 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1f2:
275a24d9 89450c mov dword ptr [ebp+0Ch],eax ss:0023:001216d4=023a57b8
0:000> p
eax=03646008 ebx=023a57b8 ecx=7c9301db edx=00140608 esi=00000000 edi=00008282
eip=275a24dc esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1f5:
275a24dc 0f8424150300 je MSCOMCTL!DllGetClassObject+0x3c71f (275d3a06) [br=0]
0:000> p
eax=03646008 ebx=023a57b8 ecx=7c9301db edx=00140608 esi=00000000 edi=00008282
eip=275a24e2 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1fb:
275a24e2 8b0b mov ecx,dword ptr [ebx] ds:0023:023a57b8={ole32!CExposedStream::`vftable' (7699dd78)}
0:000> p
eax=03646008 ebx=023a57b8 ecx=7699dd78 edx=00140608 esi=00000000 edi=00008282
eip=275a24e4 esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1fd:
275a24e4 56 push esi
0:000> p
eax=03646008 ebx=023a57b8 ecx=7699dd78 edx=00140608 esi=00000000 edi=00008282
eip=275a24e5 esp=001216b4 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1fe:
275a24e5 57 push edi
0:000> p
eax=03646008 ebx=023a57b8 ecx=7699dd78 edx=00140608 esi=00000000 edi=00008282
eip=275a24e6 esp=001216b0 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb1ff:
275a24e6 50 push eax
0:000> p
eax=03646008 ebx=023a57b8 ecx=7699dd78 edx=00140608 esi=00000000 edi=00008282
eip=275a24e7 esp=001216ac ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb200:
275a24e7 53 push ebx
0:000> p
eax=03646008 ebx=023a57b8 ecx=7699dd78 edx=00140608 esi=00000000 edi=00008282
eip=275a24e8 esp=001216a8 ebp=001216c8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MSCOMCTL!DllGetClassObject+0xb201:
275a24e8 ff510c call dword ptr [ecx+0Ch] ds:0023:7699dd84=30ed7be6
0:000> ln 0ed7be6
0:000> ln 30ed7be6
(30ed7b91) mso!Ordinal1077+0x55 | (30ed7d09) mso!Ordinal6286
0:000> dd esp
001216a8 023a57b8 03646008 00008282 00000000
001216b8 00000000 0679cd5c 023a57b8 00008282
001216c8 001216fc 275a273d 001216f4 03646008
001216d8 00008282 00000000 0679cd5c 023a57b8
001216e8 6a626f43 00000064 00008282 00121744
001216f8 275876c7 00121724 275e727b 0679cd5c
00121708 023a57b8 00000000 0679cd38 036520d8
00121718 275a688f 00000001 00121744 00121744
分析一下这个函数使mso组件中的,第一个参数是对象地址,第二个参数是刚才在堆上分配的内存首地址,第三个参数分配内存的大小,第四个参数是0x0,可以看到这个函数可能就是往刚才分配的内存上写数据(数据来源是从poc.doc上读取的数据),注意此时edi=0x8282,poi(ebp+8)=001216f4 poi(ebp+c)=03646008,此处的poi(ebp+c)的值是0x275a24d9 mov dword ptr [ebp+0Ch],eax传入的, 即堆上分配的内存。
单步走一下:
0:000> p
eax=00000000 ebx=023a57b8 ecx=0012181c edx=00000000 esi=00000000 edi=00008282
eip=275a24eb esp=001216b8 ebp=001216c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSCOMCTL!DllGetClassObject+0xb204:
275a24eb 8bf0 mov esi,eax
0:000> dd 03646008
03646008 00000000 00000000 00000000 41414141
03646018 00000000 00000000 00000000 00000000
03646028 00000000 00000000 00000000 00000000
03646038 00000000 00000000 00000000 00000000
函数执行成功返回0,堆分配内存中新写入了数据,这些数据来自poc.doc文件
经过上边分析,我们总结一下,在函数vul中,275a24fe rep movs dword ptr es:[edi],dword ptr [esi] ,此处ecx来自->275a24fb shr ecx,2 ->0x275a24f4 mov ecx,edi->0x275a24bd mov edi,dword ptr [ebp+10h] ->vul的第三个参数,说明vul函数的第三个参数除以四就是ecx
esi来自->275a24f1 mov esi,dword ptr [ebp+0Ch]->275a24d9 mov dword ptr [ebp+0Ch],eax ->275a24d1 call dword ptr [MSCOMCTL+0x1168 (27581168)] 说明esi来自堆分配的一块大小为0x8282的内存,内存被函数275a24e8 call dword ptr [ecx+0Ch] 写入poc.doc中的数据
edi来自275a24f6 mov edi,dword ptr [ebp+8] 即函数vul的第一个参数
上边已经分析完了函数vul,我们继续分析vul_parent函数,从0x275a2738往上分析(即内存低址):
275a270d e88efdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
1. 275a2712 83c40c add esp,0Ch
2. 275a2715 85c0 test eax,eax
3. 275a2717 7c6c jl MSCOMCTL!DllGetClassObject+0xb49e (275a2785)
4.
5. MSCOMCTL!DllGetClassObject+0xb432:
6. 275a2719 817dec436f626a cmp dword ptr [ebp-14h],6A626F43h
7. 275a2720 0f8539030300 jne MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
8.
9. MSCOMCTL!DllGetClassObject+0xb43f:
10. 275a2726 837df408 cmp dword ptr [ebp-0Ch],8
11. 275a272a 0f822f030300 jb MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
12.
13. MSCOMCTL!DllGetClassObject+0xb449:
14. 275a2730 ff75f4 push dword ptr [ebp-0Ch]
15. 275a2733 8d45f8 lea eax,[ebp-8]
16. 275a2736 53 push ebx
17. 275a2737 50 push eax
18. 275a2738 e863fdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
函数vul的第一个参数来自0x275a2737 push eax ->275a2733 lea eax,[ebp-8] 即函数vul_parent的第一个参数,此时是在ebp低0x8的地址处,如果此时复制的长度超过0x8,就会覆盖ebp,如果超过0xc,就会覆盖到vul_parent的返回地址,就可以造成栈溢出
看一下275a2726 837df408 cmp dword ptr [ebp-0Ch],8 有个条件判断语句,如果函数vul_parent的第二个参数小于8的话,就跳转,大于等于8的话就继续执行,此处的vul_parent的第二个参数正好是vul函数中275a24fe rep movs dword ptr es:[edi],dword ptr [esi] 复制时ecx*4的值,由于这个错误的判断 ,正好造成了栈溢出。
vul函数的第三个参数来自0x275a2730 push dword ptr [ebp-0Ch] 我们来重点分析一下这个参数是来自哪里
1. 275a26fa 55 push ebp
2. 275a26fb 8bec mov ebp,esp
3. 275a26fd 83ec14 sub esp,14h
4. 275a2700 53 push ebx
5. 275a2701 8b5d0c mov ebx,dword ptr [ebp+0Ch]
6. 275a2704 56 push esi
7. 275a2705 57 push edi
8. 275a2706 6a0c push 0Ch
9. 275a2708 8d45ec lea eax,[ebp-14h]
10. 275a270b 53 push ebx
11. 275a270c 50 push eax
12. 275a270d e88efdffff call MSCOMCTL!DllGetClassObject+0xb1b9 (275a24a0)
13. 275a2712 83c40c add esp,0Ch
在0x275a270d处调用vul函数,第一个参数来自ebp-14h,即写入的地址,第三个参数是0xc,即写入的字节数,从ebp-14h到ebp-8h,此时正好覆盖了275a2730 push dword ptr [ebp-0Ch] 的内存,说明0x275a270d调用的vul函数写入的数据覆盖了0x275a2738处调用vul函数的第三个参数的数据,也就是poc.doc(0x275a270d调用的vul函数调用了poc.doc中的数据)中的数据最终改写了275a24fe rep movs dword ptr es:[edi],dword ptr [esi] 中ecx的值。
最后总结一下:
在vul_parent第一次调用函数vul,写入0xc的数据,写入的数据内存正好覆盖了第二次调用函数vul的第三个参数的值,这个值决定了vul复制数据的字节数,本来vul_parent只分配了0x14的栈空间,第一次已经用去了0xc的大小,还有0x8的空间,如果此时第二次调用vul的第三个参数大于8就可以覆盖ebp,甚至函数vul_parent的返回地址
所有问题的症结就在于
275a2726 837df408 cmp dword ptr [ebp-0Ch],8
1. 275a272a 0f822f030300 jb MSCOMCTL!DllGetClassObject+0x3b778 (275d2a5f)
有个条件判断语句写错了,应该是判断当 dword ptr [ebp-0Ch]大于8的时候应该跳转结束,这里正好写反了。
其实用IDA分析一下更简单
[培训]《安卓高级研修班(网课)》月薪三万计划,掌 握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
赞赏
他的文章
看原图