Files
metasploit-gs/modules/post/windows/recon/computer_browser_discovery.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

158 lines
5.2 KiB
Ruby
Raw Normal View History

2011-11-03 03:00:51 +00:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2011-11-03 03:00:51 +00:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Post
include Msf::Auxiliary::Report
2013-08-30 16:28:54 -05:00
2021-09-10 12:53:39 +01:00
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Recon Computer Browser Discovery',
'Description' => %q{
This module uses railgun to discover hostnames and IPs on the network.
2011-11-17 07:47:26 -06:00
LTYPE should be set to one of the following values: WK (all workstations), SVR (all servers),
SQL (all SQL servers), DC (all Domain Controllers), DCBKUP (all Domain Backup Servers),
2017-09-17 16:00:04 -04:00
NOVELL (all Novell servers), PRINTSVR (all Print Que servers), MASTERBROWSER (all Master Browsers),
2011-11-17 07:47:26 -06:00
WINDOWS (all Windows hosts), or UNIX (all Unix hosts).
2021-09-10 12:53:39 +01:00
},
'License' => MSF_LICENSE,
'Author' => [ 'mubix' ],
'Platform' => [ 'win' ],
2021-10-06 13:43:31 +01:00
'SessionTypes' => [ 'meterpreter' ],
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
stdapi_net_resolve_host
stdapi_railgun_api
stdapi_railgun_memread
]
}
}
2021-09-10 12:53:39 +01:00
)
)
2013-08-30 16:28:54 -05:00
2011-11-06 21:23:21 +00:00
register_options(
[
2021-09-10 12:53:39 +01:00
OptString.new('LTYPE', [true, 'Account informations (type info for known types)', 'WK']), # Enum would be a better choice
OptString.new('DOMAIN', [false, 'Domain to perform lookups on, default is current domain', nil]),
OptBool.new('SAVEHOSTS', [true, 'Save Discovered Hosts to the Database', false])
2021-09-10 12:53:39 +01:00
]
)
2011-11-03 03:00:51 +00:00
end
2013-08-30 16:28:54 -05:00
2021-09-10 12:53:39 +01:00
def parse_netserverenum(startmem, count)
2011-11-03 03:00:51 +00:00
base = 0
sys_list = []
2021-09-10 12:53:39 +01:00
mem = client.railgun.memread(startmem, 24 * count)
2013-08-30 16:28:54 -05:00
2023-02-08 13:47:34 +00:00
count.times do |_i|
2011-11-03 03:00:51 +00:00
x = {}
2023-02-08 13:47:34 +00:00
x[:platform_id] = mem[(base + 0), 4].unpack('V*')[0]
cnameptr = mem[(base + 4), 4].unpack('V*')[0]
x[:major_ver] = mem[(base + 8), 4].unpack('V*')[0]
x[:minor_ver] = mem[(base + 12), 4].unpack('V*')[0]
x[:type] = mem[(base + 16), 4].unpack('V*')[0]
commentptr = mem[(base + 20), 4].unpack('V*')[0]
2021-09-10 12:53:39 +01:00
x[:cname] = client.railgun.memread(cnameptr, 27).split("\0\0")[0].split("\0").join
x[:comment] = client.railgun.memread(commentptr, 255).split("\0\0")[0].split("\0").join
2011-11-03 03:00:51 +00:00
sys_list << x
2023-02-08 13:47:34 +00:00
base += 24
2011-11-03 03:00:51 +00:00
vprint_status("Identified: #{x[:cname]} - #{x[:comment]}")
2023-02-08 13:47:34 +00:00
end
2011-11-03 03:00:51 +00:00
return sys_list
end
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
def run
### MAIN ###
client = session
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
domain = nil
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
# Default = SV_TYPE_NT
# Servers = SV_TYPE_ALL
# Workstations = SV_TYPE_WORKSTATION
# Domain Controllers = SV_TYPE_DOMAINCTRL
# Novell Server = SV_TYPE_NOVELL
# Terminal Servers = SV_TYPE_TERMINALSERVER
# SQL Servers = SV_TYPE_SQLSERVER
lookuptype = 1
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
case datastore['LTYPE']
2023-02-08 13:47:34 +00:00
when 'WK' then lookuptype = '1'.hex
when 'SVR' then lookuptype = '2'.hex
when 'SQL' then lookuptype = '4'.hex
when 'DC' then lookuptype = '8'.hex
when 'DCBKUP' then lookuptype = '10'.hex
when 'TIME' then lookuptype = '20'.hex
when 'NOVELL' then lookuptype = '80'.hex
when 'PRINTSVR' then lookuptype = '200'.hex
when 'MASTERBROWSER' then lookuptype = '40000'.hex
when 'WINDOWS' then lookuptype = '400000'.hex
when 'UNIX' then lookuptype = '800'.hex
when 'LOCAL' then lookuptype = '40000000'.hex
2011-11-03 03:00:51 +00:00
end
2013-08-30 16:28:54 -05:00
if session.arch == ARCH_X64
2011-11-03 03:00:51 +00:00
nameiterator = 8
size = 64
addrinfoinmem = 32
else
nameiterator = 4
size = 32
addrinfoinmem = 24
end
2013-08-30 16:28:54 -05:00
2021-09-10 12:53:39 +01:00
result = client.railgun.netapi32.NetServerEnum(nil, 101, 4, -1, 4, 4, lookuptype, datastore['DOMAIN'], 0)
2015-01-05 11:50:51 -06:00
2011-11-03 03:00:51 +00:00
if result['totalentries'] == 0
2023-02-08 13:47:34 +00:00
print_error('No systems found of that type')
2011-11-03 03:00:51 +00:00
return
end
2017-07-19 11:46:39 +01:00
print_good("Found #{result['totalentries']} systems.")
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
endofline = 0
i = nameiterator
2021-09-10 12:53:39 +01:00
netview = parse_netserverenum(result['bufptr'], result['totalentries'])
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
## get IP for host
begin
netview.each do |x|
vprint_status("Looking up IP for #{x[:cname]}")
print '.'
2013-09-24 21:58:04 +01:00
result = client.net.resolve.resolve_host(x[:cname])
2023-02-08 13:47:34 +00:00
if result[:ip].nil? || result[:ip].blank?
print_error("There was an error resolving the IP for #{x[:cname]}")
2011-11-03 03:00:51 +00:00
next
2013-09-24 21:58:04 +01:00
else
2021-09-10 12:53:39 +01:00
x[:ip] = result[:ip]
2011-11-03 03:00:51 +00:00
end
end
rescue ::Exception => e
print_error(e)
print_status('Windows 2000 and prior does not support getaddrinfo')
end
2013-08-30 16:28:54 -05:00
2021-09-10 12:53:39 +01:00
netview = netview.sort_by { |e| e[:type] }
2013-08-30 16:28:54 -05:00
2016-08-10 13:30:09 -05:00
results = Rex::Text::Table.new(
2011-11-03 03:00:51 +00:00
'Header' => 'Netdiscovery Results',
'Indent' => 2,
'Columns' => ['TYPE', 'IP', 'COMPUTER NAME', 'VERSION', 'COMMENT']
)
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
netview.each do |x|
results << [x[:type], x[:ip], x[:cname], "#{x[:major_ver]}.#{x[:minor_ver]}", x[:comment]]
2023-02-08 13:47:34 +00:00
report_host(host: x[:ip]) if datastore['SAVEHOSTS'] && !x[:ip].empty?
2011-11-03 03:00:51 +00:00
end
print_status(results.to_s)
2023-02-08 13:47:34 +00:00
store_loot('discovered.hosts', 'text/plain', session, results.to_s, 'discovered_hosts.txt', 'Computer Browser Discovered Hosts')
2013-08-30 16:28:54 -05:00
2011-11-03 03:00:51 +00:00
print_status('If none of the IP addresses show up you are running this from a Win2k or older system')
print_status("If a host doesn't have an IP it either timed out or only has an IPv6 address assinged to it")
end
end