Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

netenum.rb 11KB

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