CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/multi/recon/reverse_lookup.rb
Views: 1904
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::Common
8
include Msf::Exploit::Deprecated
9
moved_from 'post/windows/gather/reverse_lookup'
10
moved_from 'post/windows/recon/resolve_ip'
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Reverse Lookup IP Addresses',
17
'Description' => %q{
18
This module reverse resolves an IP address or IP address range to hostnames.
19
},
20
'License' => MSF_LICENSE,
21
'Author' => [ 'mubix' ],
22
'Platform' => %w[win unix linux osx solaris bsd],
23
'SessionTypes' => %w[meterpreter powershell shell],
24
'Notes' => {
25
'Stability' => [CRASH_SAFE],
26
'Reliability' => [],
27
'SideEffects' => []
28
},
29
'Compat' => {
30
'Meterpreter' => {
31
'Commands' => %w[
32
stdapi_railgun_api
33
stdapi_railgun_memread
34
]
35
}
36
}
37
)
38
)
39
register_options([
40
OptAddress.new('ADDRESS', [ false, 'IP address to resolve']),
41
OptAddressRange.new('RANGE', [ false, 'IP address range to resolve'])
42
])
43
end
44
45
def resolve_ip(ip)
46
return unless Rex::Socket.dotted_ip?(ip)
47
48
session.platform == 'windows' ? win_resolve_ip(ip) : unix_resolve_ip(ip)
49
end
50
51
def unix_resolve_ip(ip)
52
return unless Rex::Socket.dotted_ip?(ip)
53
54
res = cmd_exec("host #{ip}")
55
56
return if res.blank?
57
58
hostname = res.split("\n").first.split(' ').last
59
60
if hostname.blank? || !hostname.ends_with?('.')
61
print_error("Failed to resolve #{ip}")
62
return
63
end
64
65
hostname.chomp('.')
66
end
67
68
def win_resolve_ip(ip)
69
return unless Rex::Socket.dotted_ip?(ip)
70
71
case session.type
72
when 'powershell'
73
host = cmd_exec("[System.Net.Dns]::GetHostEntry('#{ip}').HostName").to_s
74
75
if host.blank?
76
print_error("Failed to resolve #{ip}")
77
return
78
end
79
80
return host
81
when 'meterpreter'
82
ip_ino = Rex::Socket.addr_aton(ip)
83
84
result = client.railgun.ws2_32.gethostbyaddr(ip_ino, ip_ino.size, 2)
85
86
if result.blank? || result['return'] == 0
87
print_error("Failed to resolve #{ip}")
88
return
89
end
90
91
memtext = client.railgun.memread(result['return'], 255)
92
93
unless memtext.include?(ip_ino)
94
print_error("Failed to resolve #{ip}")
95
return
96
end
97
98
host = memtext.split(ip_ino)[1].split("\00")[0]
99
100
if host.blank?
101
print_error("Failed to resolve #{ip}")
102
return
103
end
104
105
return host
106
else
107
fail_with(Failure::BadConfig, "Unsupported sesssion type #{session.type}")
108
end
109
rescue Rex::Post::Meterpreter::RequestError, Errno::ETIMEDOUT
110
print_error("Failed to resolve #{ip}")
111
nil
112
end
113
114
def run
115
address = datastore['ADDRESS']
116
range = datastore['RANGE']
117
118
fail_with(Failure::BadConfig, 'ADDRESS or RANGE option must be set.') if address.blank? && range.blank?
119
120
if session.platform == 'windows'
121
if session.type == 'meterpreter'
122
# Add ws2_32 just in case it isn't there...
123
session.railgun.ws2_32
124
125
# Check if gethostbyaddr is available
126
modhandle = session.railgun.kernel32.GetModuleHandleA('ws2_32.dll')
127
if modhandle['return'] == 0
128
fail_with(Failure::Unknown, 'WS2_32 is not available at this time, exiting')
129
end
130
131
procaddr = session.railgun.kernel32.GetProcAddress(modhandle['return'], 'gethostbyaddr')
132
if procaddr['return'] == 0
133
fail_with(Failure::Unknown, 'WS2_32 was loaded but does not have the gethostbyaddr function, exiting')
134
end
135
end
136
else
137
fail_with(Failure::NoTarget, "`host' command not found") unless command_exists?('host')
138
end
139
140
unless address.blank?
141
print_status("Resolving #{address}")
142
host = resolve_ip(address)
143
print_good("#{address} resolves to #{host}") unless host.blank?
144
end
145
146
unless range.blank?
147
rex_range = Rex::Socket::RangeWalker.new(range)
148
print_status("Resolving #{range} (#{rex_range.num_ips} hosts)")
149
rex_range.each do |ip|
150
host = resolve_ip(ip)
151
print_good("#{ip} resolves to #{host}") unless host.blank?
152
end
153
end
154
end
155
end
156
157