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..75ee2a3c7460 --- /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, 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, family) + 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..14c780e10c2d 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, family) + ## get IP for host + vprint_status("Looking up IP for #{hostname}") + resolve_host(hostname, family) 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 [] @@ -104,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, @@ -115,12 +99,29 @@ def list_computers(domain, hosts) ] ) hosts.each do |hostname| - hostip = resolve_host(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',