SMBScanAttack.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. import logging
  2. import random as rnd
  3. import scapy.layers.inet as inet
  4. from scapy.layers.smb import *
  5. import Attack.AttackParameters as atkParam
  6. import Attack.BaseAttack as BaseAttack
  7. import ID2TLib.SMB2 as SMB2
  8. import ID2TLib.SMBLib as SMBLib
  9. import ID2TLib.Utility as Util
  10. logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
  11. # noinspection PyPep8
  12. class SMBScanAttack(BaseAttack.BaseAttack):
  13. def __init__(self):
  14. """
  15. Creates a new instance of the SMBScanAttack.
  16. This Attack injects TCP Syn Requests to the port 445 of several ips and related response into the output
  17. pcap file.
  18. If port 445 is open, it will simulate and inject the SMB Protocol Negotiation too.
  19. """
  20. # Initialize attack
  21. super(SMBScanAttack, self).__init__("SmbScan Attack", "Injects an SMB scan",
  22. "Scanning/Probing")
  23. self.host_os = Util.get_rnd_os()
  24. # Define allowed parameters and their type
  25. self.supported_params.update({
  26. atkParam.Parameter.IP_SOURCE: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
  27. atkParam.Parameter.IP_DESTINATION: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
  28. atkParam.Parameter.TARGET_COUNT: atkParam.ParameterTypes.TYPE_INTEGER_POSITIVE,
  29. atkParam.Parameter.HOSTING_PERCENTAGE: atkParam.ParameterTypes.TYPE_PERCENTAGE,
  30. atkParam.Parameter.PORT_SOURCE: atkParam.ParameterTypes.TYPE_PORT,
  31. atkParam.Parameter.MAC_SOURCE: atkParam.ParameterTypes.TYPE_MAC_ADDRESS,
  32. atkParam.Parameter.INJECT_AT_TIMESTAMP: atkParam.ParameterTypes.TYPE_FLOAT,
  33. atkParam.Parameter.INJECT_AFTER_PACKET: atkParam.ParameterTypes.TYPE_PACKET_POSITION,
  34. atkParam.Parameter.IP_SOURCE_RANDOMIZE: atkParam.ParameterTypes.TYPE_BOOLEAN,
  35. atkParam.Parameter.PACKETS_PER_SECOND: atkParam.ParameterTypes.TYPE_FLOAT,
  36. atkParam.Parameter.INJECT_PPS: atkParam.ParameterTypes.TYPE_FLOAT,
  37. atkParam.Parameter.PORT_SOURCE_RANDOMIZE: atkParam.ParameterTypes.TYPE_BOOLEAN,
  38. atkParam.Parameter.HOSTING_IP: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
  39. atkParam.Parameter.HOSTING_VERSION: atkParam.ParameterTypes.TYPE_STRING,
  40. atkParam.Parameter.SOURCE_PLATFORM: atkParam.ParameterTypes.TYPE_STRING,
  41. atkParam.Parameter.PROTOCOL_VERSION: atkParam.ParameterTypes.TYPE_STRING
  42. })
  43. def init_params(self):
  44. """
  45. Initialize the parameters of this attack using the user supplied command line parameters.
  46. Use the provided statistics to calculate default parameters and to process user
  47. supplied queries.
  48. """
  49. # PARAMETERS: initialize with default values
  50. # (values are overwritten if user specifies them)
  51. most_used_ip_address = self.statistics.get_most_used_ip_address()
  52. self.add_param_value(atkParam.Parameter.IP_SOURCE, most_used_ip_address)
  53. self.add_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE, 'False')
  54. self.add_param_value(atkParam.Parameter.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip_address))
  55. self.add_param_value(atkParam.Parameter.TARGET_COUNT, 200)
  56. self.add_param_value(atkParam.Parameter.IP_DESTINATION, "1.1.1.1")
  57. self.add_param_value(atkParam.Parameter.PORT_SOURCE, rnd.randint(1024, 65535))
  58. self.add_param_value(atkParam.Parameter.PORT_SOURCE_RANDOMIZE, 'True')
  59. self.add_param_value(atkParam.Parameter.PACKETS_PER_SECOND,
  60. (self.statistics.get_pps_sent(most_used_ip_address) +
  61. self.statistics.get_pps_received(most_used_ip_address)) / 2)
  62. self.add_param_value(atkParam.Parameter.INJECT_AFTER_PACKET, rnd.randint(0, self.statistics.get_packet_count()))
  63. start = Util.get_timestamp_from_datetime_str(self.statistics.get_pcap_timestamp_start())
  64. end = Util.get_timestamp_from_datetime_str(self.statistics.get_pcap_timestamp_end())
  65. self.add_param_value(atkParam.Parameter.INJECT_AT_TIMESTAMP, (start + end) / 2)
  66. self.add_param_value(atkParam.Parameter.INJECT_PPS, 0)
  67. self.add_param_value(atkParam.Parameter.HOSTING_PERCENTAGE, 0.5)
  68. self.add_param_value(atkParam.Parameter.HOSTING_IP, "1.1.1.1")
  69. self.add_param_value(atkParam.Parameter.HOSTING_VERSION, SMBLib.get_smb_version(platform=self.host_os))
  70. self.add_param_value(atkParam.Parameter.SOURCE_PLATFORM, Util.get_rnd_os())
  71. self.add_param_value(atkParam.Parameter.PROTOCOL_VERSION, "1")
  72. def generate_attack_packets(self):
  73. """
  74. Creates the attack packets.
  75. """
  76. pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)
  77. # Calculate complement packet rates of the background traffic for each interval
  78. complement_interval_pps = self.statistics.calculate_complement_packet_rates(pps)
  79. # Timestamp
  80. timestamp_next_pkt = self.get_param_value(atkParam.Parameter.INJECT_AT_TIMESTAMP)
  81. # store start time of attack
  82. self.attack_start_utime = timestamp_next_pkt
  83. timestamp_prv_reply, timestamp_confirm = 0, 0
  84. # Initialize parameters
  85. ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)
  86. dest_ip_count = self.get_param_value(atkParam.Parameter.TARGET_COUNT)
  87. ip_addr_count = self.statistics.get_ip_address_count()
  88. if ip_addr_count < dest_ip_count + 1:
  89. dest_ip_count = ip_addr_count
  90. # Check for user defined target IP addresses
  91. ip_destinations = self.get_param_value(atkParam.Parameter.IP_DESTINATION)
  92. if isinstance(ip_destinations, list):
  93. dest_ip_count = dest_ip_count - len(ip_destinations)
  94. elif ip_destinations is not "1.1.1.1":
  95. dest_ip_count = dest_ip_count - 1
  96. ip_destinations = [ip_destinations]
  97. else:
  98. ip_destinations = []
  99. # Take random targets from pcap
  100. rnd_ips = self.statistics.get_random_ip_address(dest_ip_count)
  101. if not isinstance(rnd_ips, list):
  102. rnd_ips = [rnd_ips]
  103. ip_destinations = ip_destinations + rnd_ips
  104. # Make sure the source IP is not part of targets
  105. if ip_source in ip_destinations and isinstance(ip_destinations, list):
  106. ip_destinations.remove(ip_source)
  107. self.add_param_value(atkParam.Parameter.IP_DESTINATION, ip_destinations)
  108. ip_destinations = self.get_param_value(atkParam.Parameter.IP_DESTINATION)
  109. # Calculate the amount of IP addresses which are hosting SMB
  110. host_percentage = self.get_param_value(atkParam.Parameter.HOSTING_PERCENTAGE)
  111. rnd_ip_count = len(ip_destinations) * host_percentage
  112. # Check for user defined IP addresses which are hosting SMB
  113. hosting_ip = self.get_param_value(atkParam.Parameter.HOSTING_IP)
  114. if isinstance(hosting_ip, list):
  115. rnd_ip_count = rnd_ip_count - len(hosting_ip)
  116. elif hosting_ip is not "1.1.1.1":
  117. rnd_ip_count = rnd_ip_count - 1
  118. hosting_ip = [hosting_ip]
  119. else:
  120. hosting_ip = []
  121. hosting_ip = hosting_ip + ip_destinations[:int(rnd_ip_count)]
  122. self.add_param_value(atkParam.Parameter.HOSTING_IP, hosting_ip)
  123. # Shuffle targets
  124. rnd.shuffle(ip_destinations)
  125. # FIXME: Handle mac addresses correctly
  126. mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
  127. mac_dest = self.get_param_value(atkParam.Parameter.MAC_DESTINATION)
  128. # Check smb version
  129. smb_version = self.get_param_value(atkParam.Parameter.PROTOCOL_VERSION)
  130. if smb_version not in SMBLib.smb_versions:
  131. SMBLib.invalid_smb_version(smb_version)
  132. hosting_version = self.get_param_value(atkParam.Parameter.HOSTING_VERSION)
  133. if hosting_version not in SMBLib.smb_versions:
  134. SMBLib.invalid_smb_version(hosting_version)
  135. # Check source platform
  136. src_platform = self.get_param_value(atkParam.Parameter.SOURCE_PLATFORM).lower()
  137. self.packets = []
  138. # randomize source ports according to platform, if specified
  139. if self.get_param_value(atkParam.Parameter.PORT_SOURCE_RANDOMIZE):
  140. sport = Util.generate_source_port_from_platform(src_platform)
  141. else:
  142. sport = self.get_param_value(atkParam.Parameter.PORT_SOURCE)
  143. # No destination IP was specified, but a destination MAC was specified, generate IP that fits MAC
  144. if isinstance(ip_destinations, list) and isinstance(mac_dest, str):
  145. ip_destinations = self.statistics.get_ip_address_from_mac(mac_dest)
  146. if len(ip_destinations) == 0:
  147. ip_destinations = self.generate_random_ipv4_address("Unknown", 1)
  148. # Check ip.src == ip.dst
  149. self.ip_src_dst_equal_check(ip_source, ip_destinations)
  150. ip_dests = []
  151. if isinstance(ip_destinations, list):
  152. ip_dests = ip_destinations
  153. else:
  154. ip_dests.append(ip_destinations)
  155. if isinstance(ip_dests, list):
  156. rnd.shuffle(ip_dests)
  157. # Randomize source IP, if specified
  158. if self.get_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE):
  159. ip_source = self.generate_random_ipv4_address("Unknown", 1)
  160. while ip_source in ip_dests:
  161. ip_source = self.generate_random_ipv4_address("Unknown", 1)
  162. mac_source = self.statistics.get_mac_address(str(ip_source))
  163. if len(mac_source) == 0:
  164. mac_source = self.generate_random_mac_address()
  165. # Get MSS, TTL and Window size value for source IP
  166. source_mss_value, source_ttl_value, source_win_value = self.get_ip_data(ip_source)
  167. mac_dests = self.statistics.get_mac_addresses(ip_dests)
  168. first_timestamp_smb = self.statistics.get_pcap_timestamp_start()[:19]
  169. # get inject pss
  170. inject_pps = self.get_param_value(atkParam.Parameter.INJECT_PPS)
  171. for ip in ip_dests:
  172. if ip != ip_source:
  173. # Get destination Mac Address
  174. mac_destination = ""
  175. if ip in mac_dests.keys():
  176. mac_destination = mac_dests[ip]
  177. if len(mac_destination) == 0:
  178. if isinstance(mac_dest, str):
  179. ip_from_mac = self.statistics.get_ip_address_from_mac(mac_dest)
  180. if len(ip_from_mac) != 0:
  181. ip = ip_from_mac
  182. self.ip_src_dst_equal_check(ip_source, ip)
  183. mac_destination = mac_dest
  184. else:
  185. mac_destination = self.generate_random_mac_address()
  186. # Get MSS, TTL and Window size value for destination IP
  187. destination_mss_value, destination_ttl_value, destination_win_value = self.get_ip_data(ip)
  188. min_delay, max_delay = self.get_reply_delay(ip)
  189. # New connection, new random TCP sequence numbers
  190. attacker_seq = rnd.randint(1000, 50000)
  191. victim_seq = rnd.randint(1000, 50000)
  192. # Randomize source port for each connection if specified
  193. if self.get_param_value(atkParam.Parameter.PORT_SOURCE_RANDOMIZE):
  194. sport = Util.generate_source_port_from_platform(src_platform, sport)
  195. # 1) Build request package
  196. request_ether = inet.Ether(src=mac_source, dst=mac_destination)
  197. request_ip = inet.IP(src=ip_source, dst=ip, ttl=source_ttl_value, flags='DF')
  198. request_tcp = inet.TCP(sport=sport, dport=SMBLib.smb_port, window=source_win_value, flags='S',
  199. seq=attacker_seq, options=[('MSS', source_mss_value)])
  200. attacker_seq += 1
  201. request = (request_ether / request_ip / request_tcp)
  202. request.time = timestamp_next_pkt
  203. # Append request
  204. self.packets.append(request)
  205. # Update timestamp for next package
  206. timestamp_reply = Util.update_timestamp(timestamp_next_pkt, pps, min_delay, inj_pps=inject_pps,
  207. inj_timestamp=self.attack_start_utime)
  208. while timestamp_reply <= timestamp_prv_reply:
  209. timestamp_reply = Util.update_timestamp(timestamp_prv_reply, pps, min_delay, inj_pps=inject_pps,
  210. inj_timestamp=self.attack_start_utime)
  211. timestamp_prv_reply = timestamp_reply
  212. if ip in hosting_ip:
  213. # 2) Build TCP packages for ip that hosts SMB
  214. # destination sends SYN, ACK
  215. reply_ether = inet.Ether(src=mac_destination, dst=mac_source)
  216. reply_ip = inet.IP(src=ip, dst=ip_source, ttl=destination_ttl_value, flags='DF')
  217. reply_tcp = inet.TCP(sport=SMBLib.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq,
  218. flags='SA',
  219. window=destination_win_value, options=[('MSS', destination_mss_value)])
  220. victim_seq += 1
  221. reply = (reply_ether / reply_ip / reply_tcp)
  222. reply.time = timestamp_reply
  223. self.packets.append(reply)
  224. # requester confirms, ACK
  225. confirm_ether = request_ether
  226. confirm_ip = request_ip
  227. confirm_tcp = inet.TCP(sport=sport, dport=SMBLib.smb_port, seq=attacker_seq, ack=victim_seq,
  228. window=source_win_value, flags='A')
  229. confirm = (confirm_ether / confirm_ip / confirm_tcp)
  230. timestamp_confirm = Util.update_timestamp(timestamp_reply, pps, min_delay)
  231. confirm.time = timestamp_confirm
  232. self.packets.append(confirm)
  233. # 3) Build SMB Negotiation packets
  234. smb_mid = rnd.randint(1, 65535)
  235. smb_pid = rnd.randint(1, 65535)
  236. smb_req_tail_arr = []
  237. smb_req_tail_size = 0
  238. # select dialects based on smb version
  239. if smb_version is "1":
  240. smb_req_dialects = SMBLib.smb_dialects[0:6]
  241. else:
  242. smb_req_dialects = SMBLib.smb_dialects
  243. if len(smb_req_dialects) == 0:
  244. smb_req_tail_arr.append(SMBNegociate_Protocol_Request_Tail())
  245. smb_req_tail_size = len(SMBNegociate_Protocol_Request_Tail())
  246. else:
  247. for dia in smb_req_dialects:
  248. smb_req_tail_arr.append(SMBNegociate_Protocol_Request_Tail(BufferData=dia))
  249. smb_req_tail_size += len(SMBNegociate_Protocol_Request_Tail(BufferData=dia))
  250. # Creation of SMB Negotiate Protocol Request packet
  251. smb_req_head = SMBNegociate_Protocol_Request_Header(Flags2=0x2801, PID=smb_pid, MID=smb_mid,
  252. ByteCount=smb_req_tail_size)
  253. smb_req_length = len(smb_req_head) + smb_req_tail_size
  254. smb_req_net_bio = NBTSession(TYPE=0x00, LENGTH=smb_req_length)
  255. smb_req_tcp = inet.TCP(sport=sport, dport=SMBLib.smb_port, flags='PA', seq=attacker_seq,
  256. ack=victim_seq)
  257. smb_req_ip = inet.IP(src=ip_source, dst=ip, ttl=source_ttl_value)
  258. smb_req_ether = inet.Ether(src=mac_source, dst=mac_destination)
  259. attacker_seq += len(smb_req_net_bio) + len(smb_req_head) + smb_req_tail_size
  260. smb_req_combined = (smb_req_ether / smb_req_ip / smb_req_tcp / smb_req_net_bio / smb_req_head)
  261. for i in range(0, len(smb_req_tail_arr)):
  262. smb_req_combined = smb_req_combined / smb_req_tail_arr[i]
  263. timestamp_smb_req = Util.update_timestamp(timestamp_confirm, pps, min_delay)
  264. smb_req_combined.time = timestamp_smb_req
  265. self.packets.append(smb_req_combined)
  266. # destination confirms SMB request package
  267. reply_tcp = inet.TCP(sport=SMBLib.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq,
  268. window=destination_win_value, flags='A')
  269. confirm_smb_req = (reply_ether / reply_ip / reply_tcp)
  270. timestamp_reply = Util.update_timestamp(timestamp_smb_req, pps, min_delay)
  271. confirm_smb_req.time = timestamp_reply
  272. self.packets.append(confirm_smb_req)
  273. # smb response package
  274. first_timestamp = time.mktime(time.strptime(first_timestamp_smb, "%Y-%m-%d %H:%M:%S"))
  275. server_guid, security_blob, capabilities, data_size, server_start_time =\
  276. SMBLib.get_smb_platform_data(self.host_os, first_timestamp)
  277. timestamp_smb_rsp = Util.update_timestamp(timestamp_reply, pps, min_delay)
  278. diff = timestamp_smb_rsp - timestamp_smb_req
  279. begin = Util.get_filetime_format(timestamp_smb_req + diff * 0.1)
  280. end = Util.get_filetime_format(timestamp_smb_rsp - diff * 0.1)
  281. system_time = rnd.randint(begin, end)
  282. # Creation of SMB Negotiate Protocol Response packets
  283. if smb_version is not "1" and hosting_version is not "1":
  284. smb_rsp_packet = SMB2.SMB2_SYNC_Header(Flags=1)
  285. smb_rsp_negotiate_body =\
  286. SMB2.SMB2_Negotiate_Protocol_Response(DialectRevision=0x02ff, SecurityBufferOffset=124,
  287. SecurityBufferLength=len(security_blob),
  288. SecurityBlob=security_blob, Capabilities=capabilities,
  289. MaxTransactSize=data_size, MaxReadSize=data_size,
  290. MaxWriteSize=data_size, SystemTime=system_time,
  291. ServerStartTime=server_start_time,
  292. ServerGuid=server_guid)
  293. smb_rsp_length = len(smb_rsp_packet) + len(smb_rsp_negotiate_body)
  294. else:
  295. smb_rsp_packet =\
  296. SMBNegociate_Protocol_Response_Advanced_Security(Start="\xffSMB", PID=smb_pid, MID=smb_mid,
  297. DialectIndex=5, SecurityBlob=security_blob)
  298. smb_rsp_length = len(smb_rsp_packet)
  299. smb_rsp_net_bio = NBTSession(TYPE=0x00, LENGTH=smb_rsp_length)
  300. smb_rsp_tcp = inet.TCP(sport=SMBLib.smb_port, dport=sport, flags='PA', seq=victim_seq,
  301. ack=attacker_seq)
  302. smb_rsp_ip = inet.IP(src=ip, dst=ip_source, ttl=destination_ttl_value)
  303. smb_rsp_ether = inet.Ether(src=mac_destination, dst=mac_source)
  304. victim_seq += len(smb_rsp_net_bio) + len(smb_rsp_packet)
  305. if smb_version is not "1" and hosting_version is not "1":
  306. victim_seq += len(smb_rsp_negotiate_body)
  307. smb_rsp_combined = (smb_rsp_ether / smb_rsp_ip / smb_rsp_tcp / smb_rsp_net_bio / smb_rsp_packet)
  308. if smb_version is not "1" and hosting_version is not "1":
  309. smb_rsp_combined = (smb_rsp_combined / smb_rsp_negotiate_body)
  310. smb_rsp_combined.time = timestamp_smb_rsp
  311. self.packets.append(smb_rsp_combined)
  312. # source confirms SMB response package
  313. confirm_tcp = inet.TCP(sport=sport, dport=SMBLib.smb_port, seq=attacker_seq, ack=victim_seq,
  314. window=source_win_value, flags='A')
  315. confirm_smb_res = (confirm_ether / confirm_ip / confirm_tcp)
  316. timestamp_confirm = Util.update_timestamp(timestamp_smb_rsp, pps, min_delay)
  317. confirm_smb_res.time = timestamp_confirm
  318. self.packets.append(confirm_smb_res)
  319. # attacker sends FIN ACK
  320. confirm_tcp = inet.TCP(sport=sport, dport=SMBLib.smb_port, seq=attacker_seq, ack=victim_seq,
  321. window=source_win_value, flags='FA')
  322. source_fin_ack = (confirm_ether / confirm_ip / confirm_tcp)
  323. timestamp_src_fin_ack = Util.update_timestamp(timestamp_confirm, pps, min_delay)
  324. source_fin_ack.time = timestamp_src_fin_ack
  325. attacker_seq += 1
  326. self.packets.append(source_fin_ack)
  327. # victim sends FIN ACK
  328. reply_tcp = inet.TCP(sport=SMBLib.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq,
  329. window=destination_win_value, flags='FA')
  330. destination_fin_ack = (reply_ether / reply_ip / reply_tcp)
  331. timestamp_dest_fin_ack = Util.update_timestamp(timestamp_src_fin_ack, pps, min_delay)
  332. victim_seq += 1
  333. destination_fin_ack.time = timestamp_dest_fin_ack
  334. self.packets.append(destination_fin_ack)
  335. # source sends final ACK
  336. confirm_tcp = inet.TCP(sport=sport, dport=SMBLib.smb_port, seq=attacker_seq, ack=victim_seq,
  337. window=source_win_value, flags='A')
  338. final_ack = (confirm_ether / confirm_ip / confirm_tcp)
  339. timestamp_final_ack = Util.update_timestamp(timestamp_dest_fin_ack, pps, min_delay)
  340. final_ack.time = timestamp_final_ack
  341. self.packets.append(final_ack)
  342. else:
  343. # Build RST package
  344. reply_ether = inet.Ether(src=mac_destination, dst=mac_source)
  345. reply_ip = inet.IP(src=ip, dst=ip_source, ttl=destination_ttl_value, flags='DF')
  346. reply_tcp = inet.TCP(sport=SMBLib.smb_port, dport=sport, seq=0, ack=attacker_seq, flags='RA',
  347. window=destination_win_value, options=[('MSS', destination_mss_value)])
  348. reply = (reply_ether / reply_ip / reply_tcp)
  349. reply.time = timestamp_reply
  350. self.packets.append(reply)
  351. pps = max(Util.get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
  352. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
  353. def generate_attack_pcap(self):
  354. """
  355. Creates a pcap containing the attack packets.
  356. :return: The location of the generated pcap file.
  357. """
  358. # store end time of attack
  359. self.attack_end_utime = self.packets[-1].time
  360. # write attack self.packets to pcap
  361. pcap_path = self.write_attack_pcap(sorted(self.packets, key=lambda pkt: pkt.time))
  362. # return packets sorted by packet time_sec_start
  363. return len(self.packets), pcap_path