SalityBotnet.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import logging
  2. from random import randint, 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.utils import RawPcapReader
  10. from scapy.layers.inet import IP, Ether, TCP, RandShort
  11. from ID2TLib.Utility import *
  12. class SalityBotnet(BaseAttack.BaseAttack):
  13. template_attack_pcap_path = "resources/sality_botnet.pcap"
  14. def __init__(self):
  15. """
  16. Creates a new instance of the Sality botnet.
  17. """
  18. # Initialize attack
  19. super(SalityBotnet, self).__init__("Sality Botnet", "Injects an Sality botnet'",
  20. "Botnet")
  21. # Define allowed parameters and their type
  22. self.supported_params = {
  23. Param.MAC_SOURCE: ParameterTypes.TYPE_MAC_ADDRESS,
  24. Param.IP_SOURCE: ParameterTypes.TYPE_IP_ADDRESS,
  25. Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
  26. Param.INJECT_AFTER_PACKET: ParameterTypes.TYPE_PACKET_POSITION,
  27. Param.PACKETS_PER_SECOND: ParameterTypes.TYPE_FLOAT
  28. }
  29. def init_params(self):
  30. """
  31. Initialize the parameters of this attack using the user supplied command line parameters.
  32. Use the provided statistics to calculate default parameters and to process user
  33. supplied queries.
  34. :param statistics: Reference to a statistics object.
  35. """
  36. # PARAMETERS: initialize with default utilsvalues
  37. # (values are overwritten if user specifies them)
  38. most_used_ip_address = self.statistics.get_most_used_ip_address()
  39. if isinstance(most_used_ip_address, list):
  40. most_used_ip_address = most_used_ip_address[0]
  41. self.add_param_value(Param.IP_SOURCE, most_used_ip_address)
  42. self.add_param_value(Param.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip_address))
  43. # Attack configuration
  44. self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
  45. self.add_param_value(Param.PACKETS_PER_SECOND,
  46. (self.statistics.get_pps_sent(most_used_ip_address) +
  47. self.statistics.get_pps_received(most_used_ip_address)) / 2)
  48. def generate_attack_pcap(self):
  49. # Timestamp
  50. timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
  51. pps = self.get_param_value(Param.PACKETS_PER_SECOND)
  52. # Calculate complement packet rates of BG traffic per interval
  53. complement_interval_pps = self.statistics.calculate_complement_packet_rates(pps)
  54. # Initialize parameters
  55. packets = []
  56. mac_source = self.get_param_value(Param.MAC_SOURCE)
  57. ip_source = self.get_param_value(Param.IP_SOURCE)
  58. # Pick a DNS server from the background traffic
  59. ip_dns_server = self.statistics.process_db_query("SELECT ipAddress FROM ip_protocols WHERE protocolName='DNS' ORDER BY protocolCount DESC LIMIT 1;")
  60. if not ip_dns_server or ip_source == ip_dns_server:
  61. ip_dns_server = self.statistics.get_random_ip_address()
  62. mac_dns_server = self.statistics.get_mac_address(ip_dns_server)
  63. # Bot original config in the template PCAP
  64. origin_mac_src = "08:00:27:e5:d7:b0"
  65. origin_ip_src = "10.0.2.15"
  66. origin_mac_dns_server = "52:54:00:12:35:02"
  67. origin_ip_dns_server = "10.0.2.2"
  68. ttl_map = {}
  69. ip_map = {origin_ip_src : ip_source, origin_ip_dns_server: ip_dns_server}
  70. mac_map = {origin_mac_src : mac_source, origin_mac_dns_server: mac_dns_server}
  71. path_attack_pcap = None
  72. # Inject Sality botnet
  73. # Read sality_botnet pcap file
  74. exploit_raw_packets = RawPcapReader(self.template_attack_pcap_path)
  75. for pkt_num, pkt in enumerate(exploit_raw_packets):
  76. eth_frame = Ether(pkt[0])
  77. ip_pkt = eth_frame.payload
  78. # Ether
  79. if eth_frame.getfieldval("src") in mac_map:
  80. eth_frame.setfieldval("src", mac_map[eth_frame.getfieldval("src")])
  81. if eth_frame.getfieldval("dst") in mac_map:
  82. eth_frame.setfieldval("dst", mac_map[eth_frame.getfieldval("dst")])
  83. # IP
  84. if ip_pkt.getfieldval("src") in ip_map:
  85. ip_pkt.setfieldval("src", ip_map[ip_pkt.getfieldval("src")])
  86. if ip_pkt.getfieldval("dst") in ip_map:
  87. ip_pkt.setfieldval("dst", ip_map[ip_pkt.getfieldval("dst")])
  88. ## TTL
  89. if ip_pkt.getfieldval("ttl") not in ttl_map:
  90. source_ttl = self.statistics.get_most_used_ttl(ip_pkt.getfieldval("src"))
  91. if not source_ttl:
  92. source_ttl = self.statistics.process_db_query("SELECT ttlValue FROM ip_ttl ORDER BY RANDOM() LIMIT 1;")
  93. ttl_map[ip_pkt.getfieldval("ttl")] = source_ttl
  94. ip_pkt.setfieldval("ttl", ttl_map[ip_pkt.getfieldval("ttl")])
  95. new_pkt = (eth_frame / ip_pkt)
  96. new_pkt.time = timestamp_next_pkt
  97. pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
  98. timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps)
  99. packets.append(new_pkt)
  100. # Store timestamp of first packet (for attack label)
  101. self.attack_start_utime = packets[0].time
  102. self.attack_end_utime = packets[-1].time
  103. if len(packets) > 0:
  104. packets = sorted(packets, key=lambda pkt: pkt.time)
  105. path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
  106. # return packets sorted by packet time_sec_start
  107. # pkt_num+1: because pkt_num starts at 0
  108. return pkt_num + 1, path_attack_pcap