CVE-2012-0158分析

0x00 CVE-2012-0158 调试过程

首先给WinExec下断点

1
2
3
4
5
6
7
8
9
10
11
12
bp Kernel32!Winexec
7c8623ad 8bff mov edi,edi // 断在此处
7c8623af 55 push ebp
7c8623b0 8bec mov ebp,esp
7c8623b2 83ec54 sub esp,54h
7c8623b5 53 push ebx
7c8623b6 56 push esi
7c8623b7 57 push edi
7c8623b8 6a11 push 11h
7c8623ba 59 pop ecx
7c8623bb 33c0 xor eax,eax
7c8623bd 33f6 xor esi,esi

其中WinExec的定义如下:
1
UINT WinExec(LPCSTR lpCmdLine, UINT uCmdShow);

此时的栈帧

低地址

WinExec的返回地址 
lpCmdLine      
uCmdShow 
FunA调用 WinExec

高地址

1
2
3
4
5
6
7
8
9
10
0:000> dd esp
001215d0 0012189a 08d9f0a8 00000000 08d9f0a8
001215e0 0001c000 00000340 00121638 00121ac0
001215f0 0d403db0 08d9ffe8 0001c000 00000001
00121600 275c8a0a 08d9ffe8 0d403db0 0001c000
00121610 00000000 08d2e008 0d403d98 00002d26
00121620 00002d26 0d401550 00002841 0002159e
00121630 00000000 00000340 00000000 001216b1
00121640 1005c48b c7000001 4d032400 005ae908

0012189a 是WinExec的返回地址
08d9f0a8 是lpCmdLine
00000000 是uCmdShow

0:000> db 08d9f0a8
08d9f0a8 43 3a 5c 44 6f 63 75 6d-65 6e 74 73 20 61 6e 64 C:\Documents and
08d9f0b8 20 53 65 74 74 69 6e 67-73 5c 41 64 6d 69 6e 69 Settings\Admini
08d9f0c8 73 74 72 61 74 6f 72 5c-61 2e 65 78 65 00 00 00 strator\a.exe…

1
2
3
4
5
6
7
8
9
0:000> u 0012189a
0012189a eb22 jmp 001218be
0012189c 6a01 push 1
0012189e 6a00 push 0
001218a0 6a00 push 0
001218a2 ff75f4 push dword ptr [ebp-0Ch]
001218a5 6a00 push 0
001218a7 e814feffff call 001216c0
001218ac 0555000000 add eax,55h

kb命令可以显示放在栈上的前三个参数
kp命令可以根据符号文件中的函数原型信息来自动
0:000> kv
ChildEBP RetAddr Args to Child
001215cc 0012189a 08d9f0a8 00000000 08d9f0a8 kernel32!WinExec (FPO: [Non-Fpo])
WARNING: Frame IP not in any known module. Following frames may be wrong.
001215fc 275c8a0a 08d9ffe8 0d403db0 0001c000 0x12189a
00121638 001216b1 1005c48b c7000001 4d032400 MSCOMCTL!DllGetClassObject+0x41cc6
00000000 00000000 00000000 00000000 00000000 0x1216b1

通过IDA逆向MSCOMCTL.OCX,发现其导出函数DllGetClassObject的起始地址为0x27586d44
0x27586D44 + 0x41cc6 = 0x275c8a0a
0x275c8a0a 位于函数sub_275c89c7(int a1,BSTR bstrString)中
即函数sub_275c89c7就是包含漏洞的函数

首先看内存地址为275c89c7处的代码

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
.text:275C89C7 push ebp
.text:275C89C8 mov ebp, esp
.text:275C89CA sub esp, 14h ; 分配0x14大小的栈空间
.text:275C89CD push ebx
.text:275C89CE mov ebx, [ebp+bstrString]
.text:275C89D1 push esi
.text:275C89D2 push edi
.text:275C89D3 push 0Ch ; dwBytes
.text:275C89D5 lea eax, [ebp+var_14]
.text:275C89D8 push ebx ; lpMem
.text:275C89D9 push eax ; int
.text:275C89DA call sub_275C876D
.text:275C89DF add esp, 0Ch ; 用掉了0x0c大小的栈空间,还剩0x8个字节
.text:275C89E2 test eax, eax
.text:275C89E4 jl short loc_275C8A52
.text:275C89E6 cmp [ebp+var_14], 6A626F43h
.text:275C89ED jnz loc_275D3085
.text:275C89F3 cmp [ebp+dwBytes], 8
.text:275C89F7 jb loc_275D3085
.text:275C89FD push [ebp+dwBytes] ; dwBytes
.text:275C8A00 lea eax, [ebp+var_8]
.text:275C8A03 push ebx ; lpMem
.text:275C8A04 push eax ; int
.text:275C8A05 call sub_275C876D ; 破坏栈空间,导致栈溢出
.text:275C8A0A mov esi, eax
.text:275C8A0C add esp, 0Ch
.text:275C8A0F test esi, esi
.text:275C8A11 jl short loc_275C8A50
.text:275C8A13 cmp [ebp+var_8], 0
.text:275C8A17 mov edi, [ebp+arg_0]
.text:275C8A1A jz short loc_275C8A46
.text:275C8A1C and [ebp+bstrString], 0
.text:275C8A20 lea eax, [ebp+bstrString]
.text:275C8A23 push ebx ; int
.text:275C8A24 push eax ; len
.text:275C8A25 call sub_275C8A59
.text:275C8A2A mov esi, eax
.text:275C8A2C pop ecx
.text:275C8A2D test esi, esi
.text:275C8A2F pop ecx
.text:275C8A30 jl short loc_275C8A50
.text:275C8A32 push [ebp+bstrString] ; strIn
.text:275C8A35 lea ecx, [edi-24h]
.text:275C8A38 call sub_27585BE7
.text:275C8A3D push [ebp+bstrString] ; bstrString
.text:275C8A40 call ds:SysFreeString
.text:275C8A46
.text:275C8A46 loc_275C8A46: ; CODE XREF: sub_275C89C7+53j
.text:275C8A46 cmp [ebp+var_4], 0
.text:275C8A4A jnz loc_275D308F
.text:275C8A50
.text:275C8A50 loc_275C8A50: ; CODE XREF: sub_275C89C7+4Aj
.text:275C8A50 ; sub_275C89C7+69j ...
.text:275C8A50 mov eax, esi
.text:275C8A52
.text:275C8A52 loc_275C8A52: ; CODE XREF: sub_275C89C7+1Dj
.text:275C8A52 ; sub_275C89C7+A6C3j
.text:275C8A52 pop edi
.text:275C8A53 pop esi
.text:275C8A54 pop ebx
.text:275C8A55 leave
.text:275C8A56 retn 8
.text:275C8A56 sub_275C89C7 endp

sxe ld:MSCOMCTL.OCX

1
2
3
4
5
6
7
8
9
10
11
12
13
275C89DA E8 8EFDFFFF call MSCOMCTL.275C876D
275C89DF 83C4 0C add esp,0xC
275C89E2 85C0 test eax,eax
275C89E4 7C 6C jl short MSCOMCTL.275C8A52
275C89E6 817D EC 436F626>cmp dword ptr ss:[ebp-0x14],0x6A626F43
275C89ED 0F85 92A60000 jnz MSCOMCTL.275D3085
275C89F3 837D F4 08 cmp dword ptr ss:[ebp-0xC],0x8
275C89F7 0F82 88A60000 jb MSCOMCTL.275D3085
275C89FD FF75 F4 push dword ptr ss:[ebp-0xC] ; MSCOMCTL.<ModuleEntryPoint>
275C8A00 8D45 F8 lea eax,dword ptr ss:[ebp-0x8]
275C8A03 53 push ebx ; MSCOMCTL.27580000
275C8A04 50 push eax
275C8A05 E8 63FDFFFF call MSCOMCTL.275C876D ; 第二次执行的时候早造成栈溢出

未完、待续