2009-10-26 15:14:28 +00:00
|
|
|
# $Id$
|
2009-01-08 18:14:03 +00:00
|
|
|
#
|
|
|
|
#Meterpreter script for ping sweeps on Windows 2003, Windows Vista
|
|
|
|
#Windows 2008 and Windows XP targets using native windows commands.
|
|
|
|
#Provided by Carlos Perez at carlos_perez[at]darkoperator.com
|
2009-01-30 06:18:02 +00:00
|
|
|
#Verion: 0.1.2
|
2009-01-08 18:14:03 +00:00
|
|
|
#Note:
|
|
|
|
################## Variable Declarations ##################
|
|
|
|
@@exec_opts = Rex::Parser::Arguments.new(
|
|
|
|
"-h" => [ false, "Help menu."],
|
|
|
|
"-r" => [ true, "The target address range or CIDR identifier"],
|
2009-01-11 03:17:21 +00:00
|
|
|
"-ps" => [ false, "To Perform Ping Sweep on IP Range"],
|
2009-01-08 18:14:03 +00:00
|
|
|
"-rl" => [ false, "To Perform DNS Reverse Lookup on IP Range"],
|
2009-01-11 03:17:21 +00:00
|
|
|
"-fl" => [ false, "To Perform DNS Forward Lookup on host list and domain"],
|
|
|
|
"-hl" => [ true, "File with Host List for DNS Forward Lookup"],
|
|
|
|
"-d" => [ true, "Domain Name for DNS Forward Lookup"],
|
2009-01-30 06:18:02 +00:00
|
|
|
"-st" => [ false, "To Perform DNS lookup of MX and NS records for a domain"],
|
|
|
|
"-sr" => [ false, "To Perform Service Record DNS lookup for a domain"]
|
2009-01-08 18:14:03 +00:00
|
|
|
|
|
|
|
)
|
|
|
|
session = client
|
|
|
|
host,port = session.tunnel_peer.split(':')
|
|
|
|
|
|
|
|
# Create Filename info to be appended to downloaded files
|
|
|
|
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")+sprintf("%.5d",rand(100000))
|
|
|
|
|
|
|
|
# Create a directory for the logs
|
|
|
|
logs = ::File.join(Msf::Config.config_directory, 'logs', 'netenum', host)
|
|
|
|
|
|
|
|
# Create the log directory
|
|
|
|
::FileUtils.mkdir_p(logs)
|
|
|
|
|
|
|
|
#logfile name
|
|
|
|
dest = logs + "/" + host + filenameinfo
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# Function for performing regular lookup of MX and NS records
|
|
|
|
def stdlookup(session,domain,dest)
|
|
|
|
dest = dest + "-general-record-lookup.txt"
|
|
|
|
print_status("Getting MX and NS Records for Domain #{domain}")
|
2009-01-30 06:18:02 +00:00
|
|
|
filewrt(dest,"SOA, NS and MX Records for Domain #{domain}")
|
|
|
|
types = ["SOA","NS","MX"]
|
2009-01-08 18:14:03 +00:00
|
|
|
mxout = []
|
|
|
|
results = []
|
|
|
|
garbage = []
|
2009-01-30 06:18:02 +00:00
|
|
|
types.each do |t|
|
2009-01-08 18:14:03 +00:00
|
|
|
begin
|
2009-01-30 06:18:02 +00:00
|
|
|
r = session.sys.process.execute("nslookup -type=#{t} #{domain}", nil, {'Hidden' => true, 'Channelized' => true})
|
2009-01-08 18:14:03 +00:00
|
|
|
while(d = r.channel.read)
|
|
|
|
mxout << d
|
|
|
|
end
|
|
|
|
r.channel.close
|
|
|
|
r.close
|
2009-06-20 16:15:46 +00:00
|
|
|
results = mxout.join.split(/\n/)
|
2009-01-08 18:14:03 +00:00
|
|
|
results.each do |rec|
|
2009-01-30 06:18:02 +00:00
|
|
|
if rec.match(/\s*internet\saddress\s\=\s/)
|
|
|
|
garbage << rec.split(/\s*internet\saddress\s\=/)
|
2009-06-20 16:15:46 +00:00
|
|
|
print_status("#{garbage[0].join.sub(" "," ")} #{t} ")
|
|
|
|
filewrt(dest,garbage[0].join.sub(" "," ")+" #{t} ")
|
2009-01-30 06:18:02 +00:00
|
|
|
garbage.clear
|
|
|
|
end
|
|
|
|
garbage.clear
|
2009-01-08 18:14:03 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
rescue ::Exception => e
|
|
|
|
print_status("The following Error was encountered: #{e.class} #{e}")
|
|
|
|
end
|
2009-01-30 06:18:02 +00:00
|
|
|
end
|
2009-01-08 18:14:03 +00:00
|
|
|
end
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# Function for writing results of other functions to a file
|
|
|
|
def filewrt(file2wrt, data2wrt)
|
|
|
|
output = ::File.open(file2wrt, "a")
|
2009-06-20 16:15:46 +00:00
|
|
|
data2wrt.each_line do |d|
|
2009-01-08 18:14:03 +00:00
|
|
|
output.puts(d)
|
|
|
|
end
|
|
|
|
output.close
|
|
|
|
end
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# Function for Executing Reverse lookups
|
|
|
|
def reverselookup(session,iprange,dest)
|
|
|
|
dest = dest + "-DNS-reverse-lookup.txt"
|
|
|
|
print_status("Performing DNS Reverse Lookup for IP range #{iprange}")
|
|
|
|
filewrt(dest,"DNS Reverse Lookup for IP range #{iprange}")
|
|
|
|
iplst =[]
|
|
|
|
i, a = 0, []
|
|
|
|
begin
|
|
|
|
ipadd = Rex::Socket::RangeWalker.new(iprange)
|
|
|
|
numip = ipadd.num_ips
|
|
|
|
while (iplst.length < numip)
|
|
|
|
ipa = ipadd.next_ip
|
|
|
|
if (not ipa)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
iplst << ipa
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
iplst.each do |ip|
|
|
|
|
if i < 10
|
|
|
|
a.push(::Thread.new {
|
|
|
|
r = session.sys.process.execute("nslookup #{ip}", nil, {'Hidden' => true, 'Channelized' => true})
|
|
|
|
while(d = r.channel.read)
|
|
|
|
if d =~ /(Name)/
|
|
|
|
d.scan(/Name:\s*\S*\s/) do |n|
|
|
|
|
hostname = n.split(": ")
|
|
|
|
print_status "\t #{ip} is #{hostname[1].chomp("\n")}"
|
|
|
|
filewrt(dest,"#{ip} is #{hostname[1].chomp("\n")}")
|
|
|
|
end
|
|
|
|
break
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
r.channel.close
|
|
|
|
r.close
|
|
|
|
|
|
|
|
})
|
|
|
|
i += 1
|
|
|
|
else
|
|
|
|
sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty?
|
|
|
|
i = 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
a.delete_if {|x| not x.alive?} while not a.empty?
|
|
|
|
end
|
|
|
|
rescue ::Exception => e
|
|
|
|
print_status("The following Error was encountered: #{e.class} #{e}")
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
#-------------------------------------------------------------------------------
|
2009-01-11 03:17:21 +00:00
|
|
|
#Function for Executing Forward Lookups
|
2009-01-08 18:14:03 +00:00
|
|
|
def frwdlp(session,hostlst,domain,dest)
|
2009-01-11 03:17:21 +00:00
|
|
|
dest = dest + "-DNS-forward-lookup.txt"
|
|
|
|
print_status("Performing DNS Forward Lookup for hosts in #{hostlst} for domain #{domain}")
|
|
|
|
filewrt(dest,"DNS Forward Lookup for hosts in #{hostlst} for domain #{domain}")
|
2009-01-08 18:14:03 +00:00
|
|
|
result = []
|
|
|
|
threads = []
|
|
|
|
tmpout = []
|
|
|
|
begin
|
|
|
|
if ::File.exists?(hostlst)
|
|
|
|
::File.open(hostlst).each {|line|
|
|
|
|
threads << ::Thread.new(line) { |h|
|
|
|
|
#print_status("checking #{h.chomp}")
|
|
|
|
r = session.sys.process.execute("nslookup #{h.chomp}.#{domain}", nil, {'Hidden' => true, 'Channelized' => true})
|
|
|
|
while(d = r.channel.read)
|
|
|
|
if d =~ /(Name)/
|
|
|
|
d.scan(/Name:\s*\S*\s*Address\w*:\s*.*?.*?.*/) do |n|
|
|
|
|
tmpout << n.split
|
|
|
|
end
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
r.channel.close
|
|
|
|
r.close
|
|
|
|
}
|
|
|
|
}
|
|
|
|
threads.each { |aThread| aThread.join }
|
|
|
|
tmpout.uniq.each do |t|
|
2009-06-20 16:15:46 +00:00
|
|
|
print_status("\t#{t.join.sub(/Address\w*:/, "\t")}")
|
|
|
|
filewrt(dest,"#{t.join.sub(/Address\w*:/, "\t")}")
|
2009-01-08 18:14:03 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
else
|
|
|
|
print_status("File #{hostlst}does not exists!")
|
|
|
|
exit
|
|
|
|
end
|
|
|
|
rescue ::Exception => e
|
|
|
|
print_status("The following Error was encountered: #{e.class} #{e}")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
#Function for Executing Ping Sweep
|
|
|
|
def pingsweep(session,iprange,dest)
|
|
|
|
dest = dest + "-pingsweep.txt"
|
|
|
|
print_status("Performing ping sweep for IP range #{iprange}")
|
|
|
|
filewrt(dest,"Ping sweep for IP range #{iprange}")
|
|
|
|
iplst = []
|
|
|
|
begin
|
|
|
|
i, a = 0, []
|
|
|
|
ipadd = Rex::Socket::RangeWalker.new(iprange)
|
|
|
|
numip = ipadd.num_ips
|
|
|
|
while (iplst.length < numip)
|
|
|
|
ipa = ipadd.next_ip
|
|
|
|
if (not ipa)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
iplst << ipa
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
iplst.each do |ip|
|
|
|
|
if i < 10
|
|
|
|
a.push(::Thread.new {
|
|
|
|
r = session.sys.process.execute("ping #{ip} -n 1", nil, {'Hidden' => true, 'Channelized' => true})
|
|
|
|
while(d = r.channel.read)
|
|
|
|
if d =~ /(Reply)/
|
|
|
|
print_status "\t#{ip} host found"
|
|
|
|
filewrt(dest,"#{ip} host found")
|
|
|
|
r.channel.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
r.channel.close
|
|
|
|
r.close
|
|
|
|
|
|
|
|
})
|
|
|
|
i += 1
|
|
|
|
else
|
|
|
|
sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty?
|
|
|
|
i = 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
a.delete_if {|x| not x.alive?} while not a.empty?
|
|
|
|
end
|
|
|
|
rescue ::Exception => e
|
|
|
|
print_status("The following Error was encountered: #{e.class} #{e}")
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
#-------------------------------------------------------------------------------
|
2009-01-30 06:18:02 +00:00
|
|
|
#Function for enumerating srv records
|
|
|
|
def srvreclkp(session,domain,dest)
|
|
|
|
dest = dest + "-srvenum.txt"
|
|
|
|
srout = []
|
|
|
|
garbage = []
|
|
|
|
srvrcd = [
|
|
|
|
"_gc._tcp.","_kerberos._tcp.", "_kerberos._udp.","_ldap._tcp.","_test._tcp.",
|
|
|
|
"_sips._tcp.","_sip._udp.","_sip._tcp.","_aix._tcp.","_aix._tcp.","_finger._tcp.",
|
|
|
|
"_ftp._tcp.","_http._tcp.","_nntp._tcp.","_telnet._tcp.","_whois._tcp."]
|
|
|
|
print_status("Performing SRV Record Enumeration for #{domain}")
|
|
|
|
filewrt(dest,"SRV Record Enumeration for #{domain}")
|
|
|
|
srvrcd.each do |srv|
|
|
|
|
r = session.sys.process.execute("nslookup -query=srv #{srv}#{domain}", nil, {'Hidden' => true, 'Channelized' => true})
|
|
|
|
while(d = r.channel.read)
|
|
|
|
srout << d
|
|
|
|
end
|
|
|
|
r.channel.close
|
|
|
|
r.close
|
2009-06-20 16:15:46 +00:00
|
|
|
results = srout.join.split(/\n/)
|
2009-01-30 06:18:02 +00:00
|
|
|
results.each do |rec|
|
|
|
|
if rec.match(/\s*internet\saddress\s\=\s/)
|
|
|
|
garbage << rec.split(/\s*internet\saddress\s\=/)
|
2009-06-20 16:15:46 +00:00
|
|
|
print_status("\tfor #{srv}#{domain} #{garbage[0].join.sub(" "," ")}")
|
|
|
|
filewrt(dest,"for #{srv}#{domain} #{garbage[0].join.sub(" "," ")}")
|
2009-01-30 06:18:02 +00:00
|
|
|
garbage.clear
|
|
|
|
end
|
|
|
|
garbage.clear
|
|
|
|
srout.clear
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
#-------------------------------------------------------------------------------
|
2009-01-08 18:14:03 +00:00
|
|
|
#Function to print message during run
|
|
|
|
def message(dest)
|
|
|
|
print_status "Network Enumerator Meterpreter Script "
|
|
|
|
print_status "Log file being saved in #{dest}"
|
|
|
|
end
|
|
|
|
################## MAIN ##################
|
|
|
|
|
|
|
|
# Variables for Options
|
|
|
|
stdlkp = nil
|
|
|
|
range = nil
|
|
|
|
pngsp = nil
|
|
|
|
rvrslkp = nil
|
|
|
|
frdlkp = nil
|
|
|
|
dom = nil
|
|
|
|
hostlist = nil
|
|
|
|
helpcall = nil
|
2009-01-30 06:18:02 +00:00
|
|
|
srvrc = nil
|
2009-01-08 18:14:03 +00:00
|
|
|
# Parsing of Options
|
|
|
|
@@exec_opts.parse(args) { |opt, idx, val|
|
|
|
|
case opt
|
2009-01-30 06:18:02 +00:00
|
|
|
when "-sr"
|
|
|
|
srvrc = 1
|
2009-01-08 18:14:03 +00:00
|
|
|
when "-rl"
|
|
|
|
rvrslkp = 1
|
|
|
|
when "-fl"
|
|
|
|
frdlkp = 1
|
|
|
|
when "-ps"
|
|
|
|
pngsp = 1
|
|
|
|
when "-st"
|
|
|
|
stdlkp = 1
|
|
|
|
when "-d"
|
|
|
|
dom = val
|
|
|
|
when "-hl"
|
|
|
|
hostlist = val
|
|
|
|
when "-r"
|
|
|
|
range = val
|
2009-01-30 06:18:02 +00:00
|
|
|
|
2009-01-08 18:14:03 +00:00
|
|
|
when "-h"
|
|
|
|
print(
|
|
|
|
"Network Enumerator Meterpreter Script\n" +
|
|
|
|
"Usage:\n" +
|
|
|
|
@@exec_opts.usage
|
|
|
|
)
|
|
|
|
helpcall = 1
|
|
|
|
end
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if range != nil && pngsp == 1
|
|
|
|
message(logs)
|
|
|
|
pingsweep(session,range,dest)
|
|
|
|
elsif range != nil && rvrslkp == 1
|
|
|
|
message(logs)
|
|
|
|
reverselookup(session,range,dest)
|
|
|
|
elsif dom != nil && hostlist!= nil && frdlkp == 1
|
|
|
|
message(logs)
|
|
|
|
frwdlp(session,hostlist,dom,dest)
|
|
|
|
elsif dom != nil && stdlkp == 1
|
2009-01-30 06:18:02 +00:00
|
|
|
message(logs)
|
2009-01-08 18:14:03 +00:00
|
|
|
stdlookup(session,dom,dest)
|
2009-01-30 06:18:02 +00:00
|
|
|
elsif dom != nil && srvrc == 1
|
|
|
|
message(logs)
|
|
|
|
srvreclkp(session,dom,dest)
|
2009-01-08 18:14:03 +00:00
|
|
|
elsif helpcall == nil
|
|
|
|
print(
|
|
|
|
"Network Enumerator Meterpreter Script\n" +
|
|
|
|
"Usage: \n" +
|
|
|
|
@@exec_opts.usage)
|
|
|
|
end
|