Skip to content

Commit 02b2435

Browse files
committed
Adds mixin and test module
1 parent 764fe05 commit 02b2435

File tree

12 files changed

+393
-26
lines changed

12 files changed

+393
-26
lines changed

lib/msf/core/post/dns.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf::Post::DNS
4+
end
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# -*- coding: binary -*-
2+
3+
require 'rex/post/meterpreter/extensions/stdapi/constants'
4+
5+
module Msf
6+
class Post
7+
module DNS
8+
###
9+
#
10+
# This module resolves session DNS
11+
#
12+
###
13+
module ResolveHost
14+
# Takes the host name and resolves the IP
15+
#
16+
# @param [String] host
17+
# @param [Integer] family AF_INET for IPV4 and AF_INET6 for IPV6
18+
# @return [Hash] The resolved IPs
19+
def resolve_host(host, family)
20+
if client.respond_to?(:net) && client.commands.include?(Rex::Post::Meterpreter::Extensions::Stdapi::COMMAND_ID_STDAPI_NET_RESOLVE_HOST)
21+
resolved_host = client.net.resolve.resolve_host(host, family)
22+
resolved_host.reject { |k, _v| k == :ip }
23+
else
24+
ips = []
25+
data = cmd_exec("nslookup #{host}")
26+
if data =~ /Name/
27+
# Remove unnecessary data and get the section with the addresses
28+
returned_data = data.split(/Name:/)[1..]
29+
# check each element of the array to see if they are IP
30+
returned_data.each do |entry|
31+
ip_list = entry.gsub(/\r\n\t |\r\n|Aliases:|Addresses:|Address:/, ' ').split(' ') - [host]
32+
filtered_ips = filter_ips(ip_list, family)
33+
ips = filtered_ips unless filtered_ips.empty?
34+
end
35+
# If nslookup responds with "no answer", fall back to resolving via host command
36+
elsif data =~ /No answer/
37+
data = cmd_exec("host #{host}")
38+
if data =~ /has address/
39+
# Remove unnecessary data and get the section with the addresses
40+
returned_data = data.split("\n")[...-1]
41+
# check each element of the array to see if they are IP
42+
ip_list = returned_data.map { |entry| entry.split(' ').last }
43+
filtered_ips = filter_ips(ip_list, family)
44+
ips = filtered_ips unless filtered_ips.empty?
45+
end
46+
end
47+
{ hostname: host, ips: ips }
48+
end
49+
end
50+
51+
# Takes the host and family and returns the IP address if it matches the appropriate family
52+
# Needed to handle request that fallback to nslookup or host, as they return both IPV4 and IPV6.
53+
#
54+
# @param [Array] ips
55+
# @param [Integer] family
56+
# @return [Array] ips
57+
def filter_ips(ips, family)
58+
filtered_ips = []
59+
ips.each do |ip|
60+
if family == AF_INET
61+
filtered_ips << ip if !!(ip =~ Resolv::IPv4::Regex)
62+
elsif family == AF_INET6
63+
filtered_ips << ip if !!(ip =~ Resolv::IPv6::Regex)
64+
end
65+
end
66+
67+
filtered_ips
68+
end
69+
end
70+
end
71+
end
72+
end

modules/post/windows/gather/enum_computers.rb

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
# Current source: https://github.com/rapid7/metasploit-framework
44
##
55

6+
require 'rex/post/meterpreter/extensions/stdapi/constants'
7+
68
class MetasploitModule < Msf::Post
79
include Msf::Post::File
810
include Msf::Post::Windows::Accounts
911
include Msf::Post::Windows::Registry
12+
include Msf::Post::DNS::ResolveHost
1013

1114
def initialize(info = {})
1215
super(
@@ -58,36 +61,19 @@ def run
5861

5962
# Takes the host name and makes use of nslookup to resolve the IP
6063
#
61-
# @param [String] host Hostname
64+
# @param [Object] hostname
65+
# @param [Object] family
6266
# @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
67+
def gethost(hostname, family)
68+
## get IP for host
69+
vprint_status("Looking up IP for #{hostname}")
70+
resolve_host(hostname, family)
8571
end
8672

8773
def get_domain_computers
8874
computer_list = []
8975
divisor = "-------------------------------------------------------------------------------\r\n"
90-
net_view_response = cmd_exec('net view')
76+
net_view_response = cmd_exec("cmd.exe", "/c net view")
9177
unless net_view_response.include?(divisor)
9278
print_error("The net view command failed with: #{net_view_response}")
9379
return []
@@ -104,6 +90,7 @@ def get_domain_computers
10490
end
10591

10692
def list_computers(domain, hosts)
93+
meterpreter_dns_resolving_errors = []
10794
tbl = Rex::Text::Table.new(
10895
'Header' => 'List of identified Hosts.',
10996
'Indent' => 1,
@@ -115,12 +102,28 @@ def list_computers(domain, hosts)
115102
]
116103
)
117104
hosts.each do |hostname|
118-
hostip = resolve_host(hostname)
119-
tbl << [domain, hostname, hostip]
105+
hostipv4 = gethost(hostname, AF_INET)
106+
hostipv6 = gethost(hostname, AF_INET6)
107+
108+
if hostipv4[:ips].empty?
109+
meterpreter_dns_resolving_errors << "IPV4: #{hostname} could not be resolved"
110+
else
111+
tbl << [domain, hostname, hostipv4[:ips].join(',')]
112+
end
113+
114+
if hostipv6[:ips].empty?
115+
meterpreter_dns_resolving_errors << "IPV6: #{hostname} could not be resolved" if hostipv6[:ips].empty?
116+
else
117+
tbl << [domain, hostname, hostipv6[:ips].join(',')] unless hostipv6[:ips].nil?
118+
end
120119
end
121120

122121
print_line("\n#{tbl}\n")
123122

123+
meterpreter_dns_resolving_errors.each do | error |
124+
print_warning(error)
125+
end
126+
124127
report_note(
125128
host: session,
126129
type: 'domain.hosts',

spec/support/acceptance/command_shell/cmd.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,38 @@ module Acceptance::Session
1717
}
1818
],
1919
module_tests: [
20+
{
21+
name: 'post/test/resolve_host',
22+
platforms: [
23+
[
24+
:linux,
25+
{
26+
skip: true,
27+
reason: 'Payload not compiled for platform'
28+
}
29+
],
30+
[
31+
:osx,
32+
{
33+
skip: true,
34+
reason: 'Payload not compiled for platform'
35+
}
36+
],
37+
:windows
38+
],
39+
skipped: false,
40+
lines: {
41+
linux: {
42+
known_failures: []
43+
},
44+
osx: {
45+
known_failures: []
46+
},
47+
windows: {
48+
known_failures: []
49+
}
50+
}
51+
},
2052
{
2153
name: 'post/test/cmd_exec',
2254
platforms: [

spec/support/acceptance/command_shell/linux.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ module Acceptance::Session
4949
}
5050
}
5151
},
52+
{
53+
name: "post/test/resolve_host",
54+
platforms: [
55+
:linux,
56+
:osx,
57+
[
58+
:windows,
59+
{
60+
skip: true,
61+
reason: "Payload not compiled for platform"
62+
}
63+
]
64+
],
65+
skipped: false,
66+
lines: {
67+
linux: {
68+
known_failures: []
69+
},
70+
osx: {
71+
known_failures: []
72+
},
73+
windows: {
74+
known_failures: []
75+
}
76+
}
77+
},
5278
{
5379
name: "post/test/cmd_exec",
5480
platforms: [

spec/support/acceptance/command_shell/powershell.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,38 @@ module Acceptance::Session
1717
}
1818
],
1919
module_tests: [
20+
{
21+
name: 'post/test/resolve_host',
22+
platforms: [
23+
[
24+
:linux,
25+
{
26+
skip: true,
27+
reason: 'Payload not compiled for platform'
28+
}
29+
],
30+
[
31+
:osx,
32+
{
33+
skip: true,
34+
reason: 'Payload not compiled for platform'
35+
}
36+
],
37+
:windows
38+
],
39+
skipped: false,
40+
lines: {
41+
linux: {
42+
known_failures: []
43+
},
44+
osx: {
45+
known_failures: []
46+
},
47+
windows: {
48+
known_failures: []
49+
}
50+
}
51+
},
2052
{
2153
name: 'post/test/cmd_exec',
2254
platforms: [

spec/support/acceptance/session/java.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ module Acceptance::Session
7373
}
7474
}
7575
},
76+
{
77+
name: "post/test/resolve_host",
78+
platforms: [:linux, :osx, :windows],
79+
skipped: false,
80+
lines: {
81+
linux: {
82+
known_failures: []
83+
},
84+
osx: {
85+
known_failures: []
86+
},
87+
windows: {
88+
known_failures: []
89+
}
90+
}
91+
},
7692
{
7793
name: "post/test/cmd_exec",
7894
platforms: [:linux, :osx, :windows],

spec/support/acceptance/session/mettle.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
module Acceptance::Session
23
METTLE_METERPRETER = {
34
payloads: [
@@ -69,6 +70,32 @@ module Acceptance::Session
6970
}
7071
}
7172
},
73+
{
74+
name: "post/test/resolve_host",
75+
platforms: [
76+
:linux,
77+
:osx,
78+
[
79+
:windows,
80+
{
81+
skip: true,
82+
reason: "Payload not compiled for platform"
83+
}
84+
]
85+
],
86+
skipped: false,
87+
lines: {
88+
linux: {
89+
known_failures: []
90+
},
91+
osx: {
92+
known_failures: []
93+
},
94+
windows: {
95+
known_failures: []
96+
}
97+
}
98+
},
7299
{
73100
name: "post/test/cmd_exec",
74101
platforms: [

spec/support/acceptance/session/php.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@ module Acceptance::Session
6060
}
6161
}
6262
},
63+
{
64+
name: "post/test/resolve_host",
65+
platforms: [:linux, :osx, :windows],
66+
skipped: false,
67+
lines: {
68+
linux: {
69+
known_failures: []
70+
},
71+
osx: {
72+
known_failures: []
73+
},
74+
windows: {
75+
known_failures: [
76+
]
77+
}
78+
}
79+
},
6380
{
6481
name: "post/test/cmd_exec",
6582
platforms: [:linux, :osx, :windows],

spec/support/acceptance/session/python.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,22 @@ module Acceptance::Session
7272
}
7373
}
7474
},
75+
{
76+
name: "post/test/resolve_host",
77+
platforms: [:linux, :osx, :windows],
78+
skipped: false,
79+
lines: {
80+
linux: {
81+
known_failures: []
82+
},
83+
osx: {
84+
known_failures: []
85+
},
86+
windows: {
87+
known_failures: []
88+
}
89+
}
90+
},
7591
{
7692
name: "post/test/cmd_exec",
7793
platforms: [:linux, :osx, :windows],

0 commit comments

Comments
 (0)