From d6e59c1eacf3d10ddab17f9f7f92cf6dc84a1e78 Mon Sep 17 00:00:00 2001 From: cgranleese-r7 Date: Mon, 30 Oct 2023 13:42:27 +0000 Subject: [PATCH 1/2] Adds resolve host mixin --- lib/msf/core/post/dns.rb | 4 ++ lib/msf/core/post/dns/resolve_host.rb | 39 +++++++++++++++++++ modules/post/windows/gather/enum_computers.rb | 31 ++++----------- 3 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 lib/msf/core/post/dns.rb create mode 100644 lib/msf/core/post/dns/resolve_host.rb diff --git a/lib/msf/core/post/dns.rb b/lib/msf/core/post/dns.rb new file mode 100644 index 000000000000..3034a9f84761 --- /dev/null +++ b/lib/msf/core/post/dns.rb @@ -0,0 +1,4 @@ +# -*- coding: binary -*- + +module Msf::Post::DNS +end diff --git a/lib/msf/core/post/dns/resolve_host.rb b/lib/msf/core/post/dns/resolve_host.rb new file mode 100644 index 000000000000..5d71d6a7b886 --- /dev/null +++ b/lib/msf/core/post/dns/resolve_host.rb @@ -0,0 +1,39 @@ +# -*- coding: binary -*- + +module Msf + class Post + module DNS + ### + # + # This module resolves session DNS + # + ### + module ResolveHost + # Takes the host name and makes use of nslookup to resolve the IP + # + # @param [String] host Hostname + # @return [Array, nil] result[:ips], ips The resolved IPs + def resolve_host(host) + if client.respond_to?(:net) && client.commands.include?(Rex::Post::Meterpreter::Extensions::Stdapi::COMMAND_ID_STDAPI_NET_RESOLVE_HOST) + result = client.net.resolve.resolve_host(host) + result[:ips] + else + ips = [] + 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) + ips << e + end + end + end + ips + end + end + end + end + end +end diff --git a/modules/post/windows/gather/enum_computers.rb b/modules/post/windows/gather/enum_computers.rb index 936cbdb840b4..7eb135df861d 100644 --- a/modules/post/windows/gather/enum_computers.rb +++ b/modules/post/windows/gather/enum_computers.rb @@ -7,6 +7,7 @@ class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Accounts include Msf::Post::Windows::Registry + include Msf::Post::DNS::ResolveHost def initialize(info = {}) super( @@ -60,34 +61,16 @@ def run # # @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 = [] - 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 - end - end - end - - if ip.blank? - 'Not resolvable' - else - ip.join(', ') - end + def gethost(hostname) + ## get IP for host + vprint_status("Looking up IP for #{hostname}") + resolve_host(hostname).join(', ') end def get_domain_computers computer_list = [] divisor = "-------------------------------------------------------------------------------\r\n" - net_view_response = cmd_exec('net view') + net_view_response = cmd_exec("cmd.exe", "/c net view") unless net_view_response.include?(divisor) print_error("The net view command failed with: #{net_view_response}") return [] @@ -115,7 +98,7 @@ def list_computers(domain, hosts) ] ) hosts.each do |hostname| - hostip = resolve_host(hostname) + hostip = gethost(hostname) tbl << [domain, hostname, hostip] end From cd9020ecf17a56b046e49131edb1bfce319a8452 Mon Sep 17 00:00:00 2001 From: cgranleese-r7 Date: Tue, 7 Nov 2023 14:11:23 +0000 Subject: [PATCH 2/2] Addresses PR feedback --- lib/msf/core/post/dns/resolve_host.rb | 4 +-- modules/post/windows/gather/enum_computers.rb | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/post/dns/resolve_host.rb b/lib/msf/core/post/dns/resolve_host.rb index 5d71d6a7b886..75ee2a3c7460 100644 --- a/lib/msf/core/post/dns/resolve_host.rb +++ b/lib/msf/core/post/dns/resolve_host.rb @@ -13,9 +13,9 @@ module ResolveHost # # @param [String] host Hostname # @return [Array, nil] result[:ips], ips The resolved IPs - def resolve_host(host) + def resolve_host(host, family) if client.respond_to?(:net) && client.commands.include?(Rex::Post::Meterpreter::Extensions::Stdapi::COMMAND_ID_STDAPI_NET_RESOLVE_HOST) - result = client.net.resolve.resolve_host(host) + result = client.net.resolve.resolve_host(host, family) result[:ips] else ips = [] diff --git a/modules/post/windows/gather/enum_computers.rb b/modules/post/windows/gather/enum_computers.rb index 7eb135df861d..14c780e10c2d 100644 --- a/modules/post/windows/gather/enum_computers.rb +++ b/modules/post/windows/gather/enum_computers.rb @@ -61,10 +61,10 @@ def run # # @param [String] host Hostname # @return [String] ip The resolved IP - def gethost(hostname) + def gethost(hostname, family) ## get IP for host vprint_status("Looking up IP for #{hostname}") - resolve_host(hostname).join(', ') + resolve_host(hostname, family) end def get_domain_computers @@ -87,6 +87,7 @@ def get_domain_computers end def list_computers(domain, hosts) + meterpreter_dns_resolving_errors = [] tbl = Rex::Text::Table.new( 'Header' => 'List of identified Hosts.', 'Indent' => 1, @@ -98,12 +99,29 @@ def list_computers(domain, hosts) ] ) hosts.each do |hostname| - hostip = gethost(hostname) - tbl << [domain, hostname, hostip] + begin + hostipv4 = gethost(hostname, AF_INET) + rescue Rex::Post::Meterpreter::RequestError => e + meterpreter_dns_resolving_errors << "IPV4: #{hostname} could not be resolved - #{e}" + end + + begin + hostname = "google.com" + hostipv6 = gethost(hostname, AF_INET6) + rescue Rex::Post::Meterpreter::RequestError => e + meterpreter_dns_resolving_errors << "IPV6: #{hostname} could not be resolved - #{e}" + end + + hostipv4.each { |ip| tbl << [domain, hostname, ip] } unless hostipv4.nil? + hostipv6.each { |ip| tbl << [domain, hostname, ip] } unless hostipv6.nil? end print_line("\n#{tbl}\n") + meterpreter_dns_resolving_errors.each do | error | + print_warning(error) + end + report_note( host: session, type: 'domain.hosts',