Added smb_enumshares.
parent
27ef12bafe
commit
51c488a5ea
|
@ -33,6 +33,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'hdm',
|
||||
'nebulus',
|
||||
'sinn3r',
|
||||
'altonjx',
|
||||
'r3dy'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
|
@ -44,7 +45,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('DIR_SHARE', [true, 'Show all the folders and files', false ]),
|
||||
OptBool.new('SpiderShares', [false, 'Spider shares recursively', false]),
|
||||
OptBool.new('VERBOSE', [true, 'Show detailed information when spidering', true]),
|
||||
OptBool.new('SpiderProfiles', [false, 'Spider only user profiles when share = C$', true]),
|
||||
OptInt.new('LogSpider', [false, '1 = CSV, 2 = table (txt), 3 = one liner (txt)', 3]),
|
||||
OptInt.new('MaxDepth', [true, 'Max number of subdirectories to spider', 999]),
|
||||
OptBool.new('USE_SRVSVC_ONLY', [true, 'List shares only with SRVSVC', false ])
|
||||
], self.class)
|
||||
|
||||
|
@ -75,7 +80,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
t.strftime("%m-%d-%Y %H:%M:%S")
|
||||
end
|
||||
|
||||
def eval_host(ip, share)
|
||||
def eval_host(ip, share, subdir="")
|
||||
read = write = false
|
||||
|
||||
# srvsvc adds a null byte that needs to be removed
|
||||
|
@ -132,7 +137,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
return read,write,msg,nil if skip
|
||||
|
||||
rfd = self.simple.client.find_first("\\")
|
||||
rfd = self.simple.client.find_first("#{subdir}\\*")
|
||||
read = true if rfd != nil
|
||||
|
||||
# Test writable
|
||||
|
@ -276,57 +281,148 @@ class Metasploit3 < Msf::Auxiliary
|
|||
shares
|
||||
end
|
||||
|
||||
def profile_options(ip, share)
|
||||
usernames = []
|
||||
old_dirs = ['My Documents','Desktop']
|
||||
new_dirs = ['Desktop','Documents','Downloads','Music','Pictures','Videos']
|
||||
subdirs = []
|
||||
begin
|
||||
read,write,type,files = eval_host(ip, share, "Documents and Settings")
|
||||
files.each do |f|
|
||||
if f[0] != "." and f[0] != ".."
|
||||
usernames.push(f[0])
|
||||
end
|
||||
end
|
||||
|
||||
# Return usernames along with their profile directories.
|
||||
usernames.each do |username|
|
||||
old_dirs.each do |dir|
|
||||
subdirs.push("Documents and Settings\\#{username}\\#{dir}")
|
||||
end
|
||||
end
|
||||
rescue
|
||||
read,write,type,files = eval_host(ip, share, "Users")
|
||||
files.each do |f|
|
||||
if f[0] != "." and f[0] != ".."
|
||||
usernames.push(f[0])
|
||||
end
|
||||
end
|
||||
|
||||
# Return usernames along with their profile directories.
|
||||
usernames.each do |username|
|
||||
new_dirs.each do |dir|
|
||||
subdirs.push("Users\\#{username}\\#{dir}")
|
||||
end
|
||||
end
|
||||
end
|
||||
return subdirs
|
||||
end
|
||||
|
||||
def get_files_info(ip, rport, shares, info)
|
||||
|
||||
read = false
|
||||
write = false
|
||||
|
||||
# Creating a separate file for each IP address's results.
|
||||
detailed_tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Spidered results for #{ip}.",
|
||||
'Indent' => 1,
|
||||
'Columns' => [ 'IP Address', 'Type', 'Share', 'Path', 'Name', 'Created', 'Accessed', 'Written', 'Changed', 'Size' ]
|
||||
)
|
||||
|
||||
logdata = ""
|
||||
|
||||
list = shares.collect {|e| e[0]}
|
||||
list.each do |x|
|
||||
read,write,type,files = eval_host(ip, x)
|
||||
if files and (read or write)
|
||||
header = "#{ip}:#{rport}"
|
||||
if simple.client.default_domain and simple.client.default_name
|
||||
header << " \\\\#{simple.client.default_domain}"
|
||||
end
|
||||
header << "\\#{simple.client.default_name}\\#{x}" if simple.client.default_name
|
||||
header << " (#{type})" if type
|
||||
header << " Readable" if read
|
||||
header << " Writable" if write
|
||||
if x.strip == "ADMIN$"
|
||||
next
|
||||
end
|
||||
if not datastore['VERBOSE']
|
||||
print_status("#{ip}:#{rport} - Spidering #{x}.")
|
||||
end
|
||||
subdirs = [""]
|
||||
if x.strip() == "C$" and datastore['SpiderProfiles']
|
||||
subdirs = profile_options(ip, x)
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => header,
|
||||
'Indent' => 1,
|
||||
'Columns' => [ 'Type', 'Name', 'Created', 'Accessed', 'Written', 'Changed', 'Size' ]
|
||||
)
|
||||
|
||||
f_types = {
|
||||
1 => 'RO', 2 => 'HIDDEN', 4 => 'SYS', 8 => 'VOL',
|
||||
16 => 'DIR', 32 => 'ARC', 64 => 'DEV', 128 => 'FILE'
|
||||
}
|
||||
|
||||
files.each do |file|
|
||||
if file[0] and file[0] != '.' and file[0] != '..'
|
||||
info = file[1]['info']
|
||||
fa = f_types[file[1]['attr']] # Item type
|
||||
fname = file[0] # Filename
|
||||
tcr = to_unix_time(info[3], info[2]) # Created
|
||||
tac = to_unix_time(info[5], info[4]) # Accessed
|
||||
twr = to_unix_time(info[7], info[6]) # Written
|
||||
tch = to_unix_time(info[9], info[8]) # Changed
|
||||
sz = info[12] + info[13] # Size
|
||||
|
||||
# Filename is too long for the UI table, cut it.
|
||||
fname = "#{fname[0, 35]}..." if fname.length > 35
|
||||
|
||||
tbl << [fa || 'Unknown', fname, tcr, tac, twr, tch, sz]
|
||||
while subdirs.length > 0
|
||||
depth = subdirs[0].count("\\")
|
||||
if datastore['SpiderProfiles'] and x == "C$"
|
||||
if depth-2 > datastore['MaxDepth']
|
||||
subdirs.shift
|
||||
next
|
||||
end
|
||||
else
|
||||
if depth > datastore['MaxDepth']
|
||||
subdirs.shift
|
||||
next
|
||||
end
|
||||
end
|
||||
read,write,type,files = eval_host(ip, x, subdirs[0])
|
||||
if files and (read or write)
|
||||
if files.length < 3
|
||||
subdirs.shift
|
||||
next
|
||||
end
|
||||
header = "#{ip}:#{rport}"
|
||||
if simple.client.default_domain and simple.client.default_name
|
||||
header << " \\\\#{simple.client.default_domain}"
|
||||
end
|
||||
header << "\\#{x.sub("C$","C$\\")}" if simple.client.default_name
|
||||
header << subdirs[0]
|
||||
|
||||
print_good(tbl.to_s)
|
||||
unless tbl.rows.empty?
|
||||
p = store_loot('smb.shares', 'text/csv', ip, tbl.to_csv)
|
||||
print_good("#{x} info saved in: #{p.to_s}")
|
||||
pretty_tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => header,
|
||||
'Indent' => 1,
|
||||
'Columns' => [ 'Type', 'Name', 'Created', 'Accessed', 'Written', 'Changed', 'Size' ]
|
||||
)
|
||||
|
||||
f_types = {
|
||||
1 => 'RO', 2 => 'HIDDEN', 4 => 'SYS', 8 => 'VOL',
|
||||
16 => 'DIR', 32 => 'ARC', 64 => 'DEV', 128 => 'FILE'
|
||||
}
|
||||
|
||||
files.each do |file|
|
||||
if file[0] and file[0] != '.' and file[0] != '..'
|
||||
info = file[1]['info']
|
||||
fa = f_types[file[1]['attr']] # Item type
|
||||
fname = file[0] # Filename
|
||||
tcr = to_unix_time(info[3], info[2]) # Created
|
||||
tac = to_unix_time(info[5], info[4]) # Accessed
|
||||
twr = to_unix_time(info[7], info[6]) # Written
|
||||
tch = to_unix_time(info[9], info[8]) # Changed
|
||||
sz = info[12] + info[13] # Size
|
||||
|
||||
# Filename is too long for the UI table, cut it.
|
||||
fname = "#{fname[0, 35]}..." if fname.length > 35
|
||||
|
||||
# Add subdirectories to list to use if SpiderShare is enabled.
|
||||
if fa == "DIR" or (fa == nil and sz == 0)
|
||||
subdirs.push(subdirs[0] + "\\" + fname)
|
||||
end
|
||||
|
||||
pretty_tbl << [fa || 'Unknown', fname, tcr, tac, twr, tch, sz]
|
||||
detailed_tbl << ["#{ip}", fa || 'Unknown', "#{x}", subdirs[0] + "\\", fname, tcr, tac, twr, tch, sz]
|
||||
logdata << "#{ip}\\#{x.sub("C$","C$\\")}#{subdirs[0]}\\#{fname}\n"
|
||||
|
||||
end
|
||||
end
|
||||
vprint_good(pretty_tbl.to_s)
|
||||
end
|
||||
subdirs.shift
|
||||
end
|
||||
print_status("#{ip}:#{rport} - Spider #{x} complete.") unless datastore['VERBOSE'] == true
|
||||
end
|
||||
unless detailed_tbl.rows.empty?
|
||||
if datastore['LogSpider'] == 1
|
||||
p = store_loot('smb.enumshares', 'text/csv', ip, detailed_tbl.to_csv)
|
||||
print_good("#{ip} - info saved in: #{p.to_s}")
|
||||
elsif datastore['LogSpider'] == 2
|
||||
p = store_loot('smb.enumshares', 'text', ip, detailed_tbl)
|
||||
print_good("#{ip} - info saved in: #{p.to_s}")
|
||||
elsif datastore['LogSpider'] == 3
|
||||
p = store_loot('smb.enumshares', 'text', ip, logdata)
|
||||
print_good("#{ip} - info saved in: #{p.to_s}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -363,7 +459,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
if shares.empty?
|
||||
print_status("#{ip}:#{rport} - No shares collected")
|
||||
else
|
||||
shares_info = shares.map{|x| "#{ip}: #{x[0]} - (#{x[1]}) #{x[2]}" }.join(", ")
|
||||
shares_info = shares.map{|x| "#{ip}:#{rport} - #{x[0]} - (#{x[1]}) #{x[2]}" }.join(", ")
|
||||
shares_info.split(", ").each { |share|
|
||||
print_good share
|
||||
}
|
||||
|
@ -376,7 +472,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
:update => :unique_data
|
||||
)
|
||||
|
||||
if datastore['DIR_SHARE']
|
||||
if datastore['SpiderShares']
|
||||
get_files_info(ip, rport, shares, info)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue