CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/gather/enum_computers.rb
Views: 11655
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::File
8
include Msf::Post::Windows::Accounts
9
include Msf::Post::Windows::Registry
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Windows Gather Enumerate Computers',
16
'Description' => %q{
17
This module will enumerate computers included in the primary Active Directory domain.
18
},
19
'License' => MSF_LICENSE,
20
'Author' => [ 'Joshua Abraham <jabra[at]rapid7.com>'],
21
'Platform' => [ 'win'],
22
'SessionTypes' => %w[meterpreter powershell shell],
23
'Notes' => {
24
'Stability' => [CRASH_SAFE],
25
'Reliability' => [],
26
'SideEffects' => []
27
},
28
'Compat' => {
29
'Meterpreter' => {
30
'Commands' => %w[
31
stdapi_net_resolve_host
32
]
33
}
34
}
35
)
36
)
37
end
38
39
def run
40
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
41
print_status("Running module against #{hostname} (#{session.session_host})")
42
43
domain = get_domain_name
44
45
fail_with(Failure::Unknown, 'Could not retrieve domain name. Is the host part of a domain?') unless domain
46
47
netbios_domain_name = domain.split('.').first.upcase
48
49
hostname_list = get_domain_computers
50
51
if hostname_list.empty?
52
print_error('No computers found')
53
return
54
end
55
56
list_computers(netbios_domain_name, hostname_list)
57
end
58
59
# Takes the host name and makes use of nslookup to resolve the IP
60
#
61
# @param [String] host Hostname
62
# @return [String] ip The resolved IP
63
def resolve_host(host)
64
vprint_status("Looking up IP for #{host}")
65
return host if Rex::Socket.dotted_ip?(host)
66
67
ip = []
68
data = cmd_exec("nslookup #{host}")
69
if data =~ /Name/
70
# Remove unnecessary data and get the section with the addresses
71
returned_data = data.split(/Name:/)[1]
72
# check each element of the array to see if they are IP
73
returned_data.gsub(/\r\n\t |\r\n|Aliases:|Addresses:|Address:/, ' ').split(' ').each do |e|
74
if Rex::Socket.dotted_ip?(e)
75
ip << e
76
end
77
end
78
end
79
80
if ip.blank?
81
'Not resolvable'
82
else
83
ip.join(', ')
84
end
85
end
86
87
def get_domain_computers
88
computer_list = []
89
divisor = "-------------------------------------------------------------------------------\r\n"
90
net_view_response = cmd_exec('net view')
91
unless net_view_response.include?(divisor)
92
print_error("The net view command failed with: #{net_view_response}")
93
return []
94
end
95
96
raw_list = net_view_response.split(divisor)[1]
97
raw_list.sub!(/The command completed successfully\./, '')
98
raw_list.gsub!(/\\\\/, '')
99
raw_list.split(' ').each do |m|
100
computer_list << m
101
end
102
103
computer_list
104
end
105
106
def list_computers(domain, hosts)
107
tbl = Rex::Text::Table.new(
108
'Header' => 'List of identified Hosts.',
109
'Indent' => 1,
110
'Columns' =>
111
[
112
'Domain',
113
'Hostname',
114
'IPs',
115
]
116
)
117
hosts.each do |hostname|
118
hostip = resolve_host(hostname)
119
tbl << [domain, hostname, hostip]
120
end
121
122
print_line("\n#{tbl}\n")
123
124
report_note(
125
host: session,
126
type: 'domain.hosts',
127
data: tbl.to_csv
128
)
129
end
130
end
131
132