@@ -27,7 +27,7 @@ def initialize(info = {})
2727 directories, files, time stamps, etc.
2828
2929 By default, a RubySMB net_share_enum_all request is done in order to retrieve share information,
30- which uses SRVSVC.
30+ which uses SRVSVC, otherwise will use Rex SMB .
3131 } ,
3232 'Author' => [
3333 'hdm' ,
@@ -298,18 +298,22 @@ def run_host(ip)
298298 self . simple = session . simple_client
299299 enum_shares ( session . address )
300300 else
301- [ { port : SMB1_PORT } , { port : SMB2_3_PORT } ] . each do |info |
302- vprint_status ( "Connecting to the server..." )
301+ [
302+ # Force RubySMB library for SMB1 mode
303+ # (Windows server 2019 has issues, but Samba 3.0.20/metasploitable2 is fine with SMB1 & RubySMB)
304+ { port : SMB1_PORT , versions : [ 1 ] , backend : :ruby_smb , label : 'SMB v1' } ,
305+ # @smcintyre-r7: The Rex client doesn't support SMB versions 2 and 3
306+ #{ port: SMB2_3_PORT, versions: [1, 2, 3], backend: :rex, label: 'SMB v1/2/3' },
307+ # Use Rex SMB library fallback for SMB1 mode
308+ { port : SMB1_PORT , versions : [ 1 ] , backend : :rex , label : 'SMB v1' } ,
309+ ] . each do |info |
310+ # Update line prefix, as port changes
311+ remove_instance_variable ( :@print_prefix ) if instance_variable_defined? ( :@print_prefix )
303312 # Assign @rport so that it is accessible via the rport method in this module,
304313 # as well as making it accessible to the module mixins
305314 @rport = info [ :port ]
306- if rport == SMB1_PORT
307- # force library in smb1 mode otherwise simple.client is a
308- # `Rex::Proto::SMB::Client` that does not supply `net_share_enum_all`
309- connect ( versions : [ 1 ] , backend : :ruby_smb )
310- else
311- connect ( versions : [ 1 , 2 , 3 ] )
312- end
315+ vprint_status ( "Connecting using #{ info [ :label ] } via #{ info [ :backend ] } " )
316+ connect ( versions : info [ :versions ] , backend : info [ :backend ] )
313317 smb_login
314318 shares = enum_shares ( ip )
315319 next if shares . nil? || shares . empty?
@@ -342,22 +346,31 @@ def enum_shares(ip)
342346 shares = [ ]
343347
344348 begin
345- # Return all shares if `Shares` option has not been set
346- if datastore [ 'Share' ] . nil?
347- shares = simple . client . net_share_enum_all ( ip )
348- else
349+ # RubySMB
350+ if simple . client . respond_to? ( :net_share_enum_all )
351+ # Return all shares if `Shares` option has not been set
352+ if datastore [ 'Share' ] . nil?
353+ shares = simple . client . net_share_enum_all ( ip )
349354 # Return specific share if the `Share` option has been set
350- simple . client . net_share_enum_all ( ip ) . each { |share | shares = [ share ] if share [ :name ] == datastore [ 'Share' ] }
351- # Return an error if `Share` option has been set but no matches were found
352- if shares . empty?
353- print_error ( "No shares match #{ datastore [ 'Share' ] } " )
355+ else
356+ simple . client . net_share_enum_all ( ip ) . each { |share | shares = [ share ] if share [ :name ] == datastore [ 'Share' ] }
354357 end
358+ # Rex SMB: smb_netshareenumall tries SRVSVC then falls back to LANMAN
359+ else
360+ raw = smb_netshareenumall
361+ shares = raw . map { |s | { name : s [ 0 ] , type : s [ 1 ] , comment : s [ 2 ] } }
362+ shares = shares . select { |s | s [ :name ] == datastore [ 'Share' ] } if datastore [ 'Share' ]
355363 end
364+ # Return an error if `Share` option has been set but no matches were found
365+ print_error ( "No shares match #{ datastore [ 'Share' ] } " ) if shares . empty?
356366 rescue RubySMB ::Error ::UnexpectedStatusCode => e
357367 print_error ( "Error when trying to enumerate shares - #{ e . status_code . name } " )
358368 return
359369 rescue RubySMB ::Error ::InvalidPacket => e
360- print_error ( "Invalid packet received when trying to enumerate shares - #{ e } " )
370+ vprint_error ( "Invalid packet received when trying to enumerate shares - #{ e } " )
371+ return
372+ rescue Rex ::Proto ::SMB ::Exceptions ::ErrorCode => e
373+ print_error ( "Error when trying to enumerate shares - #{ e . message } " )
361374 return
362375 end
363376
@@ -383,7 +396,11 @@ def enum_shares(ip)
383396 )
384397
385398 if datastore [ 'SpiderShares' ]
386- get_files_info ( ip , shares )
399+ if simple . client . is_a? ( RubySMB ::Client )
400+ get_files_info ( ip , shares )
401+ else
402+ print_warning ( 'This is not available for this server (unable to use RubySMB)' )
403+ end
387404 end
388405 end
389406
0 commit comments