SMBScanAttack.py 24 KB

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