PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/pentest/voiper/sulley/network_monitor.py

https://bitbucket.org/manaphassan/raspberry-pwn
Python | 260 lines | 205 code | 39 blank | 16 comment | 14 complexity | 6ba8a89e69a9d1c2b32a28bf80dba953 MD5 | raw file
  1. #!c:\\python\\python.exe
  2. import threading
  3. import getopt
  4. import time
  5. import sys
  6. import os
  7. from sulley import pedrpc
  8. import pcapy
  9. import impacket
  10. import impacket.ImpactDecoder
  11. PORT = 26001
  12. IFS = []
  13. ERR = lambda msg: sys.stderr.write("ERR> " + msg + "\n") or sys.exit(1)
  14. USAGE = "USAGE: network_monitor.py" \
  15. "\n <-d|--device DEVICE #> device to sniff on (see list below)" \
  16. "\n [-f|--filter PCAP FILTER] BPF filter string" \
  17. "\n [-P|--log_path PATH] log directory to store pcaps to" \
  18. "\n [-l|--log_level LEVEL] log level (default 1), increase for more verbosity" \
  19. "\n [--port PORT] TCP port to bind this agent to" \
  20. "\n\nNetwork Device List:\n"
  21. # add the device list to the usage string.
  22. i = 0
  23. for dev in pcapy.findalldevs():
  24. IFS.append(dev)
  25. # if we are on windows, try and resolve the device UUID into an IP address.
  26. if sys.platform.startswith("win"):
  27. import _winreg
  28. try:
  29. # extract the device UUID and open the TCP/IP parameters key for it.
  30. dev = dev[dev.index("{"):dev.index("}")+1]
  31. subkey = r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\%s" % dev
  32. key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey)
  33. # if there is a DHCP address snag that, otherwise fall back to the IP address.
  34. try: ip = _winreg.QueryValueEx(key, "DhcpIPAddress")[0]
  35. except: ip = _winreg.QueryValueEx(key, "IPAddress")[0][0]
  36. dev = dev + "\t" + ip
  37. except:
  38. pass
  39. USAGE += " [%d] %s\n" % (i, dev)
  40. i += 1
  41. ########################################################################################################################
  42. class pcap_thread (threading.Thread):
  43. def __init__ (self, network_monitor, pcap, pcap_save_path):
  44. self.network_monitor = network_monitor
  45. self.pcap = pcap
  46. self.decoder = None
  47. self.dumper = self.pcap.dump_open(pcap_save_path)
  48. self.active = True
  49. self.data_bytes = 0
  50. # register the appropriate decoder.
  51. if pcap.datalink() == pcapy.DLT_EN10MB:
  52. self.decoder = impacket.ImpactDecoder.EthDecoder()
  53. elif pcap.datalink() == pcapy.DLT_LINUX_SLL:
  54. self.decoder = impacket.ImpactDecoder.LinuxSLLDecoder()
  55. else:
  56. raise Exception
  57. threading.Thread.__init__(self)
  58. def packet_handler (self, header, data):
  59. # add the captured data to the PCAP.
  60. self.dumper.dump(header, data)
  61. # increment the captured byte count.
  62. self.data_bytes += len(data)
  63. # log the decoded data at the appropriate log level.
  64. self.network_monitor.log(self.decoder.decode(data), 15)
  65. def run (self):
  66. # process packets while the active flag is raised.
  67. while self.active:
  68. self.pcap.dispatch(0, self.packet_handler)
  69. ########################################################################################################################
  70. class network_monitor_pedrpc_server (pedrpc.server):
  71. def __init__ (self, host, port, device, filter="", log_path="./", log_level=1):
  72. '''
  73. @type host: String
  74. @param host: Hostname or IP address to bind server to
  75. @type port: Integer
  76. @param port: Port to bind server to
  77. @type device: String
  78. @param device: Name of device to capture packets on
  79. @type ignore_pid: Integer
  80. @param ignore_pid: (Optional, def=None) Ignore this PID when searching for the target process
  81. @type log_path: String
  82. @param log_path: (Optional, def="./") Path to save recorded PCAPs to
  83. @type log_level: Integer
  84. @param log_level: (Optional, def=1) Log output level, increase for more verbosity
  85. '''
  86. # initialize the PED-RPC server.
  87. pedrpc.server.__init__(self, host, port)
  88. self.device = device
  89. self.filter = filter
  90. self.log_path = log_path
  91. self.log_level = log_level
  92. self.pcap = None
  93. self.pcap_thread = None
  94. # ensure the log path is valid.
  95. if not os.access(self.log_path, os.X_OK):
  96. self.log("invalid log path: %s" % self.log_path)
  97. raise Exception
  98. self.log("Network Monitor PED-RPC server initialized:")
  99. self.log("\t device: %s" % self.device)
  100. self.log("\t filter: %s" % self.filter)
  101. self.log("\t log path: %s" % self.log_path)
  102. self.log("\t log_level: %d" % self.log_level)
  103. self.log("Awaiting requests...")
  104. def __stop (self):
  105. '''
  106. Kill the PCAP thread.
  107. '''
  108. if self.pcap_thread:
  109. self.log("stopping active packet capture thread.", 10)
  110. self.pcap_thread.active = False
  111. self.pcap_thread = None
  112. def alive (self):
  113. '''
  114. Returns True. Useful for PED-RPC clients who want to see if the PED-RPC connection is still alive.
  115. '''
  116. return True
  117. def post_send (self):
  118. '''
  119. This routine is called after the fuzzer transmits a test case and returns the number of bytes captured by the
  120. PCAP thread.
  121. @rtype: Integer
  122. @return: Number of bytes captured in PCAP thread.
  123. '''
  124. # grab the number of recorded bytes.
  125. data_bytes = self.pcap_thread.data_bytes
  126. # stop the packet capture thread.
  127. self.__stop()
  128. self.log("stopped PCAP thread, snagged %d bytes of data" % data_bytes)
  129. return data_bytes
  130. def pre_send (self, test_number):
  131. '''
  132. This routine is called before the fuzzer transmits a test case and spin off a packet capture thread.
  133. '''
  134. self.log("initializing capture for test case #%d" % test_number)
  135. # open the capture device and set the BPF filter.
  136. self.pcap = pcapy.open_live(self.device, -1, 1, 100)
  137. self.pcap.setfilter(self.filter)
  138. # instantiate the capture thread.
  139. pcap_log_path = "%s/%d.pcap" % (self.log_path, test_number)
  140. self.pcap_thread = pcap_thread(self, self.pcap, pcap_log_path)
  141. self.pcap_thread.start()
  142. def log (self, msg="", level=1):
  143. '''
  144. If the supplied message falls under the current log level, print the specified message to screen.
  145. @type msg: String
  146. @param msg: Message to log
  147. '''
  148. if self.log_level >= level:
  149. print "[%s] %s" % (time.strftime("%I:%M.%S"), msg)
  150. def retrieve (self, test_number):
  151. '''
  152. Return the raw binary contents of the PCAP saved for the specified test case number.
  153. @type test_number: Integer
  154. @param test_number: Test number to retrieve PCAP for.
  155. '''
  156. self.log("retrieving PCAP for test case #%d" % test_number)
  157. pcap_log_path = "%s/%d.pcap" % (self.log_path, test_number)
  158. fh = open(pcap_log_path, "rb")
  159. data = fh.read()
  160. fh.close()
  161. return data
  162. def set_filter (self, filter):
  163. self.log("updating PCAP filter to '%s'" % filter)
  164. self.filter = filter
  165. def set_log_path (self, log_path):
  166. self.log("updating log path to '%s'" % log_path)
  167. self.log_path = log_path
  168. ########################################################################################################################
  169. if __name__ == "__main__":
  170. # parse command line options.
  171. try:
  172. opts, args = getopt.getopt(sys.argv[1:], "d:f:P:l:", ["device=", "filter=", "log_path=", "log_level=", "port="])
  173. except getopt.GetoptError:
  174. ERR(USAGE)
  175. device = None
  176. filter = ""
  177. log_path = "./"
  178. log_level = 1
  179. for opt, arg in opts:
  180. if opt in ("-d", "--device"): device = IFS[int(arg)]
  181. if opt in ("-f", "--filter"): filter = arg
  182. if opt in ("-P", "--log_path"): log_path = arg
  183. if opt in ("-l", "--log_level"): log_level = int(arg)
  184. if opt in ("--port"): PORT = int(arg)
  185. if not device:
  186. ERR(USAGE)
  187. try:
  188. servlet = network_monitor_pedrpc_server("0.0.0.0", PORT, device, filter, log_path, log_level)
  189. servlet.serve_forever()
  190. except:
  191. pass