CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/scripts/meterpreter/netenum.rb
Views: 1904
1
##
2
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
3
# If you'd like to improve this script, please try to port it as a post
4
# module instead. Thank you.
5
##
6
7
8
9
#Meterpreter script for ping sweeps on Windows 2003, Windows Vista
10
#Windows 2008 and Windows XP targets using native windows commands.
11
#Provided by Carlos Perez at carlos_perez[at]darkoperator.com
12
#Version: 0.1.2
13
#Note:
14
################## Variable Declarations ##################
15
@@exec_opts = Rex::Parser::Arguments.new(
16
"-h" => [ false, "Help menu." ],
17
"-r" => [ true, "The target address range or CIDR identifier" ],
18
"-p" => [ false, "To Perform Ping Sweep on IP Range" ],
19
"-l" => [ false, "To Perform DNS Reverse Lookup on IP Range" ],
20
"-f" => [ false, "To Perform DNS Forward Lookup on host list and domain" ],
21
"-H" => [ true, "File with Host List for DNS Forward Lookup" ],
22
"-d" => [ true, "Domain Name for DNS Forward Lookup" ],
23
"-x" => [ false, "To Perform DNS lookup of MX and NS records for a domain" ],
24
"-s" => [ false, "To Perform Service Record DNS lookup for a domain" ]
25
)
26
session = client
27
host,port = session.session_host, session.session_port
28
29
# Create Filename info to be appended to downloaded files
30
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
31
32
# Create a directory for the logs
33
logs = ::File.join(Msf::Config.log_directory,'scripts', 'netenum', host)
34
35
# Create the log directory
36
::FileUtils.mkdir_p(logs)
37
38
#logfile name
39
dest = logs + "/" + host + filenameinfo
40
41
#-------------------------------------------------------------------------------
42
# Function for performing regular lookup of MX and NS records
43
def stdlookup(session, domain, dest)
44
dest = dest + "-general-record-lookup.txt"
45
print_status("Getting MX and NS Records for domain #{domain}")
46
filewrt(dest,"SOA, NS and MX Records for domain #{domain}")
47
types = ["SOA","NS","MX"]
48
mxout = []
49
results = []
50
garbage = []
51
types.each do |t|
52
begin
53
r = session.sys.process.execute("nslookup -type=#{t} #{domain}", nil, {'Hidden' => true, 'Channelized' => true})
54
while(d = r.channel.read)
55
mxout << d
56
end
57
r.channel.close
58
r.close
59
results = mxout.join.split(/\n/)
60
results.each do |rec|
61
if rec.match(/\s*internet\saddress\s\=\s/)
62
garbage << rec.split(/\s*internet\saddress\s\=/)
63
print_status("#{garbage[0].join.sub(" "," ")} #{t} ")
64
filewrt(dest,garbage[0].join.sub(" "," ")+" #{t} ")
65
garbage.clear
66
end
67
garbage.clear
68
end
69
70
rescue ::Exception => e
71
print_status("The following error was encountered: #{e.class} #{e}")
72
end
73
end
74
end
75
76
#-------------------------------------------------------------------------------
77
# Function for writing results of other functions to a file
78
def filewrt(file2wrt, data2wrt)
79
output = ::File.open(file2wrt, "ab")
80
data2wrt.each_line do |d|
81
output.puts(d)
82
end
83
output.close
84
end
85
86
#-------------------------------------------------------------------------------
87
# Function for Executing Reverse lookups
88
def reverselookup(session, iprange, dest)
89
dest = dest + "-DNS-reverse-lookup.txt"
90
print_status("Performing DNS reverse lookup for IP range #{iprange}")
91
filewrt(dest,"DNS reverse lookup for IP range #{iprange}")
92
iplst =[]
93
i, a = 0, []
94
begin
95
ipadd = Rex::Socket::RangeWalker.new(iprange)
96
numip = ipadd.num_ips
97
while (iplst.length < numip)
98
ipa = ipadd.next_ip
99
if (not ipa)
100
break
101
end
102
iplst << ipa
103
end
104
begin
105
iplst.each do |ip|
106
if i < 10
107
a.push(::Thread.new {
108
r = session.sys.process.execute("nslookup #{ip}", nil, {'Hidden' => true, 'Channelized' => true})
109
while(d = r.channel.read)
110
if d =~ /(Name)/
111
d.scan(/Name:\s*\S*\s/) do |n|
112
hostname = n.split(": ")
113
print_status "\t #{ip} is #{hostname[1].chomp("\n")}"
114
filewrt(dest,"#{ip} is #{hostname[1].chomp("\n")}")
115
end
116
break
117
118
end
119
120
end
121
122
r.channel.close
123
r.close
124
125
})
126
i += 1
127
else
128
sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty?
129
i = 0
130
end
131
end
132
a.delete_if {|x| not x.alive?} while not a.empty?
133
end
134
rescue ::Exception => e
135
print_status("The following error was encountered: #{e.class} #{e}")
136
end
137
end
138
139
#-------------------------------------------------------------------------------
140
#Function for Executing Forward Lookups
141
def frwdlp(session, hostlst, domain, dest)
142
dest = dest + "-DNS-forward-lookup.txt"
143
print_status("Performing DNS forward lookup for hosts in #{hostlst} for domain #{domain}")
144
filewrt(dest,"DNS forward lookup for hosts in #{hostlst} for domain #{domain}")
145
result = []
146
threads = []
147
tmpout = []
148
begin
149
if ::File.exist?(hostlst)
150
::File.open(hostlst).each {|line|
151
threads << ::Thread.new(line) { |h|
152
#print_status("checking #{h.chomp}")
153
r = session.sys.process.execute("nslookup #{h.chomp}.#{domain}", nil, {'Hidden' => true, 'Channelized' => true})
154
while(d = r.channel.read)
155
if d =~ /(Name)/
156
d.scan(/Name:\s*\S*\s*Address\w*:\s*.*?.*?.*/) do |n|
157
tmpout << n.split
158
end
159
break
160
end
161
end
162
163
r.channel.close
164
r.close
165
}
166
}
167
threads.each { |aThread| aThread.join }
168
tmpout.uniq.each do |t|
169
print_status("\t#{t.join.sub(/Address\w*:/, "\t")}")
170
filewrt(dest,"#{t.join.sub(/Address\w*:/, "\t")}")
171
end
172
173
else
174
print_status("File #{hostlst} doesn't exists!")
175
exit
176
end
177
rescue ::Exception => e
178
print_status("The following error was encountered: #{e.class} #{e}")
179
end
180
end
181
182
#-------------------------------------------------------------------------------
183
#Function for Executing Ping Sweep
184
def pingsweep(session, iprange, dest)
185
dest = dest + "-pingsweep.txt"
186
print_status("Performing ping sweep for IP range #{iprange}")
187
filewrt(dest,"Ping sweep for IP range #{iprange}")
188
iplst = []
189
begin
190
i, a = 0, []
191
ipadd = Rex::Socket::RangeWalker.new(iprange)
192
numip = ipadd.num_ips
193
while (iplst.length < numip)
194
ipa = ipadd.next_ip
195
if (not ipa)
196
break
197
end
198
iplst << ipa
199
end
200
begin
201
iplst.each do |ip|
202
if i < 10
203
a.push(::Thread.new {
204
r = session.sys.process.execute("ping #{ip} -n 1", nil, {'Hidden' => true, 'Channelized' => true})
205
while(d = r.channel.read)
206
if d =~ /(Reply)/
207
print_status "\t#{ip} host found"
208
filewrt(dest,"#{ip} host found")
209
r.channel.close
210
elsif d =~ /(Antwort)/
211
print_status "\t#{ip} host found"
212
filewrt(dest,"#{ip} host found")
213
r.channel.close
214
end
215
end
216
r.channel.close
217
r.close
218
219
})
220
i += 1
221
else
222
sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty?
223
i = 0
224
end
225
end
226
a.delete_if {|x| not x.alive?} while not a.empty?
227
end
228
rescue ::Exception => e
229
print_status("The following error was encountered: #{e.class} #{e}")
230
end
231
end
232
#-------------------------------------------------------------------------------
233
#Function for enumerating srv records
234
def srvreclkp(session, domain, dest)
235
dest = dest + "-srvenum.txt"
236
srout = []
237
garbage = []
238
srvrcd = [
239
"_gc._tcp.","_kerberos._tcp.", "_kerberos._udp.","_ldap._tcp.","_test._tcp.",
240
"_sips._tcp.","_sip._udp.","_sip._tcp.","_aix._tcp.","_aix._tcp.","_finger._tcp.",
241
"_ftp._tcp.","_http._tcp.","_nntp._tcp.","_telnet._tcp.","_whois._tcp."
242
]
243
print_status("Performing SRV record enumeration for #{domain}")
244
filewrt(dest,"SRV record enumeration for #{domain}")
245
srvrcd.each do |srv|
246
r = session.sys.process.execute("nslookup -query=srv #{srv}#{domain}", nil, {'Hidden' => true, 'Channelized' => true})
247
while(d = r.channel.read)
248
srout << d
249
end
250
r.channel.close
251
r.close
252
results = srout.join.split(/\n/)
253
results.each do |rec|
254
if rec.match(/\s*internet\saddress\s\=\s/)
255
garbage << rec.split(/\s*internet\saddress\s\=/)
256
print_status("\tfor #{srv}#{domain} #{garbage[0].join.sub(" "," ")}")
257
filewrt(dest,"for #{srv}#{domain} #{garbage[0].join.sub(" "," ")}")
258
garbage.clear
259
end
260
garbage.clear
261
srout.clear
262
end
263
end
264
265
end
266
#-------------------------------------------------------------------------------
267
#Function to print message during run
268
def message(dest)
269
print_status "Network Enumerator Meterpreter Script "
270
print_status "Log file being saved in #{dest}"
271
end
272
273
################## MAIN ##################
274
# Variables for Options
275
stdlkp = nil
276
range = nil
277
pngsp = nil
278
rvrslkp = nil
279
frdlkp = nil
280
dom = nil
281
hostlist = nil
282
helpcall = nil
283
srvrc = nil
284
285
# Parsing of Options
286
@@exec_opts.parse(args) { |opt, idx, val|
287
case opt
288
when "-s"
289
srvrc = 1
290
when "-l"
291
rvrslkp = 1
292
when "-f"
293
frdlkp = 1
294
when "-p"
295
pngsp = 1
296
when "-x"
297
stdlkp = 1
298
when "-d"
299
dom = val
300
when "-H"
301
hostlist = val
302
when "-r"
303
range = val
304
when "-h"
305
print(
306
"Network Enumerator Meterpreter Script\n" +
307
"Usage:\n" +
308
@@exec_opts.usage
309
)
310
helpcall = 1
311
end
312
}
313
314
if client.platform == 'windows'
315
if pngsp == 1
316
if range != nil
317
message(logs)
318
pingsweep(session, range, dest)
319
else
320
print_error("Please add a range to scan: -r <value>")
321
end
322
elsif rvrslkp == 1
323
if range != nil
324
message(logs)
325
reverselookup(session, range, dest)
326
else
327
print_error("Please add a range to scan: -r <value>")
328
end
329
elsif frdlkp == 1
330
if dom != nil && hostlist!= nil &&
331
message(logs)
332
frwdlp(session, hostlist, dom, dest)
333
elsif dom == nil
334
print_error("Please add a domain name for DNS forward lookup: -d <value>")
335
elsif hostlist == nil
336
print_error("Please add a file with host list for DNS forward lookup: -hl <value>")
337
else
338
print_error("Something went wrong")
339
end
340
elsif stdlkp == 1
341
if dom != nil
342
message(logs)
343
stdlookup(session, dom, dest)
344
else
345
print_error("Please add a domain name for DNS forward lookup: -d <value>")
346
end
347
elsif srvrc == 1
348
if dom != nil
349
message(logs)
350
srvreclkp(session, dom, dest)
351
else
352
print_error("Please add a domain name for DNS forward lookup: -d <value>")
353
end
354
else
355
print("Network Enumerator Meterpreter Script\n" +
356
"Usage:\n" +
357
"\tnetenum -r <value> (-p | -l)\n" +
358
"\tnetenum -d <value> (-x | -s)\n" +
359
"\tnetenum -d <value> -H <value> -fl\n" +
360
@@exec_opts.usage)
361
end
362
else
363
print_error("This version of Meterpreter is not supported with this script!")
364
raise Rex::Script::Completed
365
end
366
367