DosAttack.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import logging
  2. from random import randint, choice, uniform
  3. from lea import Lea
  4. from Attack import BaseAttack
  5. from Attack.AttackParameters import Parameter as Param
  6. from Attack.AttackParameters import ParameterTypes
  7. logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
  8. # noinspection PyPep8
  9. from scapy.layers.inet import IP, Ether, TCP, RandShort
  10. from collections import deque
  11. class DosAttack(BaseAttack.BaseAttack):
  12. def __init__(self, statistics, pcap_file_path):
  13. """
  14. Creates a new instance of the PortscanAttack.
  15. :param statistics: A reference to the statistics class.
  16. """
  17. # Initialize attack
  18. super(DosAttack, self).__init__(statistics, "DoS Attack", "Injects a DoS attack'",
  19. "Resource Exhaustion")
  20. # Define allowed parameters and their type
  21. self.supported_params = {
  22. Param.IP_SOURCE: ParameterTypes.TYPE_IP_ADDRESS,
  23. Param.MAC_SOURCE: ParameterTypes.TYPE_MAC_ADDRESS,
  24. Param.PORT_SOURCE: ParameterTypes.TYPE_PORT,
  25. Param.PORT_SOURCE_RANDOMIZE: ParameterTypes.TYPE_BOOLEAN,
  26. Param.IP_DESTINATION: ParameterTypes.TYPE_IP_ADDRESS,
  27. Param.MAC_DESTINATION: ParameterTypes.TYPE_MAC_ADDRESS,
  28. Param.PORT_DESTINATION: ParameterTypes.TYPE_PORT,
  29. Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
  30. Param.INJECT_AFTER_PACKET: ParameterTypes.TYPE_PACKET_POSITION,
  31. Param.PACKETS_PER_SECOND: ParameterTypes.TYPE_FLOAT,
  32. Param.PACKETS_LIMIT: ParameterTypes.TYPE_INTEGER_POSITIVE
  33. }
  34. # PARAMETERS: initialize with default values
  35. # (values are overwritten if user specifies them)
  36. most_used_ip_address = self.statistics.get_most_used_ip_address()
  37. if isinstance(most_used_ip_address, list): most_used_ip_address = most_used_ip_address[0]
  38. self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
  39. # sender configuration
  40. self.add_param_value(Param.IP_SOURCE, most_used_ip_address)
  41. self.add_param_value(Param.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip_address))
  42. self.add_param_value(Param.PORT_SOURCE, str(RandShort()))
  43. self.add_param_value(Param.PORT_SOURCE_RANDOMIZE, False)
  44. self.add_param_value(Param.PACKETS_PER_SECOND,
  45. (self.statistics.get_pps_sent(most_used_ip_address) +
  46. self.statistics.get_pps_received(most_used_ip_address)) / 2)
  47. # receiver configuration
  48. random_ip_address = self.statistics.get_random_ip_address()
  49. self.add_param_value(Param.IP_DESTINATION, random_ip_address)
  50. self.add_param_value(Param.MAC_DESTINATION, self.statistics.get_mac_address(random_ip_address))
  51. self.add_param_value(Param.PORT_DESTINATION, '80')
  52. self.add_param_value(Param.PACKETS_LIMIT, randint(10, 1000))
  53. def get_packets(self):
  54. def update_timestamp(timestamp, pps, maxdelay):
  55. """
  56. Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
  57. :return: Timestamp to be used for the next packet.
  58. """
  59. return timestamp + uniform(0.1 / pps, maxdelay)
  60. def get_nth_random_element(*element_list):
  61. """
  62. :param element_list:
  63. :return:
  64. """
  65. range_max = min([len(x) for x in element_list])
  66. if range_max > 0: range_max -= 1
  67. n = randint(0, range_max)
  68. return tuple(x[n] for x in element_list)
  69. BUFFER_SIZE_PACKETS = self.get_param_value(Param.PACKETS_LIMIT)
  70. # Timestamp
  71. timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
  72. # store start time of attack
  73. self.attack_start_utime = timestamp_next_pkt
  74. pps = self.get_param_value(Param.PACKETS_PER_SECOND)
  75. randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 30, 5 / pps: 15, 10 / pps: 3})
  76. # Initialize parameters
  77. packets = deque(maxlen=BUFFER_SIZE_PACKETS)
  78. # packets = []
  79. mac_source = self.get_param_value(Param.MAC_SOURCE)
  80. ip_source = self.get_param_value(Param.IP_SOURCE)
  81. port_source = self.get_param_value(Param.PORT_SOURCE)
  82. mac_destination = self.get_param_value(Param.MAC_DESTINATION)
  83. ip_destination = self.get_param_value(Param.IP_DESTINATION)
  84. port_destination = self.get_param_value(Param.PORT_DESTINATION)
  85. # Set TTL based on TTL distribution of IP address
  86. ttl_dist = self.statistics.get_ttl_distribution(ip_source)
  87. if len(ttl_dist) > 0:
  88. ttl_prob_dict = Lea.fromValFreqsDict(ttl_dist)
  89. ttl_value = ttl_prob_dict.random()
  90. else:
  91. ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
  92. # MSS (Maximum Segment Size) for Ethernet. Allowed values [536,1500]
  93. mss = self.statistics.get_mss(ip_destination)
  94. for pkt_num in range(self.get_param_value(Param.PACKETS_LIMIT)):
  95. # Determine source port
  96. if self.get_param_value(Param.PORT_SOURCE_RANDOMIZE):
  97. cur_port_source = RandShort()
  98. elif isinstance(port_source, list):
  99. cur_port_source = choice(port_source)
  100. else:
  101. cur_port_source = port_source
  102. maxdelay = randomdelay.random()
  103. request_ether = Ether(dst=mac_destination, src=mac_source)
  104. request_ip = IP(src=ip_source, dst=ip_destination, ttl=ttl_value)
  105. request_tcp = TCP(sport=cur_port_source, dport=port_destination, flags='S', ack=0)
  106. request = (request_ether / request_ip / request_tcp)
  107. request.time = timestamp_next_pkt
  108. packets.append(request)
  109. timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
  110. self.attack_end_utime = request.time
  111. # return packets sorted by packet time_sec_start
  112. return sorted(packets, key=lambda pkt: pkt.time)