SalityBotnet.py 5.8 KB

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