Added smb_enumshares.

bug/bundler_fix
Alton Johnson 2014-07-24 21:11:18 -05:00
parent 27ef12bafe
commit 51c488a5ea
1 changed files with 141 additions and 45 deletions

View File

@ -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