Skip to content

Commit

Permalink
Makes improvement to enum_computers module
Browse files Browse the repository at this point in the history
  • Loading branch information
cgranleese-r7 committed Sep 20, 2023
1 parent 4065d01 commit 11eb569
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 44 deletions.
4 changes: 4 additions & 0 deletions lib/msf/core/post/dns.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: binary -*-

module Msf::Post::DNS
end
48 changes: 48 additions & 0 deletions lib/msf/core/post/dns/resolve_host.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# -*- coding: binary -*-

module Msf
class Post
module DNS
###
#
# This module resolves session DNS
#
###
module ResolveHost
# Takes the host name and makes use of nsloopup to resolve the IP
#
# @param [String] host Node for the ruby `send` method
# @return [String, nil] ip The resolved IP
def resolve_host(host)
ip = nil

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)

return if result[:ip].blank?

ip = result[:ip]
else
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
end

if ip.nil?
print_error("Could not resolve IP for #{host}")
else
ip
end
end
end
end
end
end
85 changes: 41 additions & 44 deletions modules/post/windows/gather/enum_computers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@

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(
update_info(
info,
'Name' => 'Windows Gather Enumerate Computers',
'Description' => %q{
This module will enumerate computers included in the primary Domain.
This module will enumerate computers included in the primary Active Directory domain.
},
'License' => MSF_LICENSE,
'Author' => [ 'Joshua Abraham <jabra[at]rapid7.com>'],
'Platform' => [ 'win'],
'SessionTypes' => [ 'meterpreter' ],
'SessionTypes' => %w[meterpreter powershell shell],
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [],
'SideEffects' => []
},
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
Expand All @@ -31,74 +37,65 @@ def initialize(info = {})
)
end

# Run Method for when run command is issued
def run
print_status("Running module against #{sysinfo['Computer']}") if !sysinfo.nil?
domain = get_domain
if !domain.empty?
hostname_list = get_domain_computers
list_computers(domain, hostname_list)
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
print_status("Running module against #{hostname} (#{session.session_host})")

domain = get_domain_name

fail_with(Failure::Unknown, 'Could not retrieve domain name. Is the host part of a domain?') unless domain

netbios_domain_name = domain.split('.').first.upcase

hostname_list = get_domain_computers

if hostname_list.empty?
print_error('No computers found')
return
end

list_computers(netbios_domain_name, hostname_list)
end

def gethost(hostname)
## get IP for host
vprint_status("Looking up IP for #{hostname}")
result = client.net.resolve.resolve_host(hostname)

return nil if result[:ip].nil? || result[:ip].blank?

return result[:ip]
resolve_host(hostname)
end

# List Members of a domain group
def get_domain_computers
computer_list = []
devisor = "-------------------------------------------------------------------------------\r\n"
raw_list = cmd_exec('net view').split(devisor)[1]
if raw_list =~ /The command completed successfully/
raw_list.sub!(/The command completed successfully\./, '')
raw_list.gsub!(/\\\\/, '')
raw_list.split(' ').each do |m|
computer_list << m
end
end

return computer_list
end
return [] unless raw_list.include?('The command completed successfully')

# Gets the Domain Name
def get_domain
domain = ''
begin
subkey = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History'
v_name = 'DCName'
domain_dc = registry_getvaldata(subkey, v_name)
dom_info = domain_dc.split('.')
domain = dom_info[1].upcase
rescue StandardError
print_error('This host is not part of a domain.')
raw_list.sub!(/The command completed successfully\./, '')
raw_list.gsub!(/\\\\/, '')
raw_list.split(' ').each do |m|
computer_list << m
end
return domain

computer_list
end

def list_computers(domain, hosts)
tbl = Rex::Text::Table.new(
'Header' => 'List of Domain Hosts for the primary Domain.',
'Header' => 'List of identified Hosts.',
'Indent' => 1,
'Columns' =>
[
'Domain',
'Hostname',
'IPs',
]
[
'Domain',
'Hostname',
'IPs',
]
)
hosts.each do |hostname|
hostip = gethost(hostname)
tbl << [domain, hostname, hostip]
end
results = tbl.to_s
print_line("\n" + results + "\n")

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

report_note(
host: session,
Expand Down

0 comments on commit 11eb569

Please sign in to comment.