Skip to content

Commit dbb6920

Browse files
committed
smb_enumshares: Allow for SMB1 ruby_smb & rex backends
1 parent 1d1c284 commit dbb6920

1 file changed

Lines changed: 37 additions & 20 deletions

File tree

modules/auxiliary/scanner/smb/smb_enumshares.rb

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)