2011-11-10 03:13:57 -06:00
|
|
|
##
|
2017-07-24 06:26:21 -07:00
|
|
|
# This module requires Metasploit: https://metasploit.com/download
|
2013-10-15 13:50:46 -05:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2011-11-10 03:13:57 -06:00
|
|
|
##
|
|
|
|
|
|
2016-03-08 14:02:44 +01:00
|
|
|
class MetasploitModule < Msf::Post
|
2013-09-05 13:41:25 -05:00
|
|
|
include Msf::Post::File
|
2023-09-20 12:11:21 +01:00
|
|
|
include Msf::Post::Windows::Accounts
|
2013-09-05 13:41:25 -05:00
|
|
|
include Msf::Post::Windows::Registry
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2021-09-10 12:53:39 +01:00
|
|
|
def initialize(info = {})
|
|
|
|
|
super(
|
|
|
|
|
update_info(
|
|
|
|
|
info,
|
|
|
|
|
'Name' => 'Windows Gather Enumerate Computers',
|
|
|
|
|
'Description' => %q{
|
2023-09-20 12:11:21 +01:00
|
|
|
This module will enumerate computers included in the primary Active Directory domain.
|
2013-09-05 13:41:25 -05:00
|
|
|
},
|
2021-09-10 12:53:39 +01:00
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
|
'Author' => [ 'Joshua Abraham <jabra[at]rapid7.com>'],
|
|
|
|
|
'Platform' => [ 'win'],
|
2023-09-20 12:11:21 +01:00
|
|
|
'SessionTypes' => %w[meterpreter powershell shell],
|
|
|
|
|
'Notes' => {
|
|
|
|
|
'Stability' => [CRASH_SAFE],
|
|
|
|
|
'Reliability' => [],
|
|
|
|
|
'SideEffects' => []
|
|
|
|
|
},
|
2021-10-06 13:43:31 +01:00
|
|
|
'Compat' => {
|
|
|
|
|
'Meterpreter' => {
|
|
|
|
|
'Commands' => %w[
|
|
|
|
|
stdapi_net_resolve_host
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-09-10 12:53:39 +01:00
|
|
|
)
|
|
|
|
|
)
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2013-09-05 13:41:25 -05:00
|
|
|
def run
|
2023-09-20 12:11:21 +01:00
|
|
|
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
|
|
|
|
|
print_status("Running module against #{hostname} (#{session.session_host})")
|
|
|
|
|
|
|
|
|
|
domain = get_domain_name
|
|
|
|
|
|
|
|
|
|
fail_with(Failure::Unknown, 'Could not retrieve domain name. Is the host part of a domain?') unless domain
|
|
|
|
|
|
|
|
|
|
netbios_domain_name = domain.split('.').first.upcase
|
|
|
|
|
|
|
|
|
|
hostname_list = get_domain_computers
|
|
|
|
|
|
|
|
|
|
if hostname_list.empty?
|
|
|
|
|
print_error('No computers found')
|
|
|
|
|
return
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2023-09-20 12:11:21 +01:00
|
|
|
|
|
|
|
|
list_computers(netbios_domain_name, hostname_list)
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2023-10-02 16:21:12 +01:00
|
|
|
# Takes the host name and makes use of nslookup to resolve the IP
|
2023-09-21 13:44:39 +01:00
|
|
|
#
|
|
|
|
|
# @param [String] host Hostname
|
|
|
|
|
# @return [String] ip The resolved IP
|
|
|
|
|
def resolve_host(host)
|
|
|
|
|
vprint_status("Looking up IP for #{host}")
|
|
|
|
|
return host if Rex::Socket.dotted_ip?(host)
|
|
|
|
|
|
|
|
|
|
ip = []
|
2023-10-02 16:21:12 +01:00
|
|
|
data = cmd_exec("nslookup #{host}")
|
|
|
|
|
if data =~ /Name/
|
|
|
|
|
# Remove unnecessary data and get the section with the addresses
|
|
|
|
|
returned_data = data.split(/Name:/)[1]
|
|
|
|
|
# check each element of the array to see if they are IP
|
|
|
|
|
returned_data.gsub(/\r\n\t |\r\n|Aliases:|Addresses:|Address:/, ' ').split(' ').each do |e|
|
|
|
|
|
if Rex::Socket.dotted_ip?(e)
|
|
|
|
|
ip << e
|
2023-09-21 13:44:39 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if ip.blank?
|
|
|
|
|
'Not resolvable'
|
|
|
|
|
else
|
|
|
|
|
ip.join(', ')
|
|
|
|
|
end
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2023-02-08 13:47:34 +00:00
|
|
|
def get_domain_computers
|
2013-09-05 13:41:25 -05:00
|
|
|
computer_list = []
|
2023-10-12 10:59:29 +01:00
|
|
|
divisor = "-------------------------------------------------------------------------------\r\n"
|
|
|
|
|
net_view_response = cmd_exec('net view')
|
|
|
|
|
unless net_view_response.include?(divisor)
|
|
|
|
|
print_error("The net view command failed with: #{net_view_response}")
|
|
|
|
|
return []
|
|
|
|
|
end
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2023-10-12 10:59:29 +01:00
|
|
|
raw_list = net_view_response.split(divisor)[1]
|
2023-09-20 12:11:21 +01:00
|
|
|
raw_list.sub!(/The command completed successfully\./, '')
|
|
|
|
|
raw_list.gsub!(/\\\\/, '')
|
|
|
|
|
raw_list.split(' ').each do |m|
|
|
|
|
|
computer_list << m
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2023-09-20 12:11:21 +01:00
|
|
|
|
|
|
|
|
computer_list
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2021-09-10 12:53:39 +01:00
|
|
|
def list_computers(domain, hosts)
|
2016-08-10 13:30:09 -05:00
|
|
|
tbl = Rex::Text::Table.new(
|
2023-09-20 12:11:21 +01:00
|
|
|
'Header' => 'List of identified Hosts.',
|
2021-09-10 12:53:39 +01:00
|
|
|
'Indent' => 1,
|
2013-09-05 13:41:25 -05:00
|
|
|
'Columns' =>
|
2023-09-20 12:11:21 +01:00
|
|
|
[
|
|
|
|
|
'Domain',
|
|
|
|
|
'Hostname',
|
|
|
|
|
'IPs',
|
|
|
|
|
]
|
2021-09-10 12:53:39 +01:00
|
|
|
)
|
2013-09-05 13:41:25 -05:00
|
|
|
hosts.each do |hostname|
|
2023-09-21 13:44:39 +01:00
|
|
|
hostip = resolve_host(hostname)
|
2021-09-10 12:53:39 +01:00
|
|
|
tbl << [domain, hostname, hostip]
|
2013-09-05 13:41:25 -05:00
|
|
|
end
|
2023-09-20 12:11:21 +01:00
|
|
|
|
|
|
|
|
print_line("\n#{tbl}\n")
|
2011-11-10 03:13:57 -06:00
|
|
|
|
2013-09-05 13:41:25 -05:00
|
|
|
report_note(
|
2023-02-08 13:47:34 +00:00
|
|
|
host: session,
|
|
|
|
|
type: 'domain.hosts',
|
|
|
|
|
data: tbl.to_csv
|
2013-09-05 13:41:25 -05:00
|
|
|
)
|
|
|
|
|
end
|
2011-11-10 03:13:57 -06:00
|
|
|
end
|