SMBScanAttack.py 23 KB

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