|
@@ -1,4 +1,9 @@
|
|
|
+
|
|
|
+
|
|
|
import logging
|
|
|
+import math
|
|
|
+from operator import itemgetter
|
|
|
+import operator
|
|
|
from random import randint, uniform
|
|
|
|
|
|
from lea import Lea
|
|
@@ -13,6 +18,16 @@ from scapy.utils import RawPcapReader
|
|
|
from scapy.layers.inet import IP, Ether, TCP, RandShort
|
|
|
|
|
|
class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
+
|
|
|
+ maxDefaultPPS = 100
|
|
|
+ minDefaultPPS = 5
|
|
|
+
|
|
|
+ smb_port = 445
|
|
|
+
|
|
|
+ minDefaultPort = 30000
|
|
|
+ maxDefaultPort = 50000
|
|
|
+ last_conn_dst_port = 4444
|
|
|
+
|
|
|
def __init__(self, statistics, pcap_file_path):
|
|
|
"""
|
|
|
Creates a new instance of the EternalBlue Exploit.
|
|
@@ -27,7 +42,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
self.supported_params = {
|
|
|
Param.MAC_SOURCE: ParameterTypes.TYPE_MAC_ADDRESS,
|
|
|
Param.IP_SOURCE: ParameterTypes.TYPE_IP_ADDRESS,
|
|
|
- Param.PORT_SOURCE: ParameterTypes.TYPE_PORT,
|
|
|
+
|
|
|
Param.MAC_DESTINATION: ParameterTypes.TYPE_MAC_ADDRESS,
|
|
|
Param.IP_DESTINATION: ParameterTypes.TYPE_IP_ADDRESS,
|
|
|
Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
|
|
@@ -43,8 +58,8 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
self.add_param_value(Param.IP_SOURCE, most_used_ip_address)
|
|
|
self.add_param_value(Param.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip_address))
|
|
|
self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
|
|
|
- self.add_param_value(Param.PORT_SOURCE, str(RandShort()))
|
|
|
- self.add_param_value(Param.PACKETS_PER_SECOND, randint(1, 64))
|
|
|
+
|
|
|
+ self.add_param_value(Param.PACKETS_PER_SECOND,self.maxDefaultPPS)
|
|
|
|
|
|
|
|
|
|
|
@@ -63,7 +78,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
|
|
|
:return: Timestamp to be used for the next packet.
|
|
|
"""
|
|
|
- return timestamp + uniform(0.1 / pps, maxdelay)
|
|
|
+ return timestamp + uniform(1 / pps, maxdelay)
|
|
|
|
|
|
|
|
|
|
|
@@ -72,32 +87,70 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
pps = self.get_param_value(Param.PACKETS_PER_SECOND)
|
|
|
randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 30, 5 / pps: 15, 10 / pps: 3})
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ result = self.statistics.process_db_query(
|
|
|
+ "SELECT timestamp,pktsCount FROM interval_statistics ORDER BY timestamp")
|
|
|
+ print(result)
|
|
|
+ bg_interval_pps = []
|
|
|
+ intervalsSum = 0
|
|
|
+ if result:
|
|
|
+
|
|
|
+ for i, row in enumerate(result):
|
|
|
+ if i < len(result) - 1:
|
|
|
+ intervalsSum += math.ceil((int(result[i + 1][0]) * 10 ** -6) - (int(row[0]) * 10 ** -6))
|
|
|
+ interval = intervalsSum / (len(result) - 1)
|
|
|
+
|
|
|
+ for row in result:
|
|
|
+ bg_interval_pps.append((int(row[0]) * 10 ** -6, int(row[1] / interval)))
|
|
|
+
|
|
|
+ maxPPS = max(bg_interval_pps, key=itemgetter(1))[1]
|
|
|
+ complement_interval_pps = []
|
|
|
+ for row in bg_interval_pps:
|
|
|
+ complement_interval_pps.append((row[0], int(pps * (maxPPS - row[1]) / maxPPS)))
|
|
|
+ print(complement_interval_pps)
|
|
|
+
|
|
|
+ def getIntervalPPS(timestamp):
|
|
|
+ for row in complement_interval_pps:
|
|
|
+ if timestamp <= row[0]:
|
|
|
+ return row[1]
|
|
|
+ return complement_interval_pps[-1][1]
|
|
|
+
|
|
|
|
|
|
packets = []
|
|
|
mac_source = self.get_param_value(Param.MAC_SOURCE)
|
|
|
ip_source = self.get_param_value(Param.IP_SOURCE)
|
|
|
- port_source = self.get_param_value(Param.PORT_SOURCE)
|
|
|
+
|
|
|
mac_destination = self.get_param_value(Param.MAC_DESTINATION)
|
|
|
ip_destination = self.get_param_value(Param.IP_DESTINATION)
|
|
|
|
|
|
+
|
|
|
+ if ip_source == ip_destination:
|
|
|
+ print("\nERROR: Invalid IP addresses; source IP is the same as destination IP: " + ip_source + ".")
|
|
|
+ import sys
|
|
|
+ sys.exit(0)
|
|
|
+
|
|
|
path_attack_pcap = None
|
|
|
+ replayDelay = self.get_reply_delay(ip_destination)
|
|
|
|
|
|
|
|
|
|
|
|
orig_ip_dst = None
|
|
|
exploit_raw_packets = RawPcapReader("Win7_eternalblue_scan.pcap")
|
|
|
+
|
|
|
+ port_source = randint(self.minDefaultPort,self.maxDefaultPort)
|
|
|
+
|
|
|
for pkt_num, pkt in enumerate(exploit_raw_packets):
|
|
|
eth_frame = Ether(pkt[0])
|
|
|
ip_pkt = eth_frame.payload
|
|
|
tcp_pkt = ip_pkt.payload
|
|
|
|
|
|
- smb_port = 445
|
|
|
if pkt_num == 0:
|
|
|
- if tcp_pkt.getfieldval("dport") == smb_port:
|
|
|
- orig_ip_dst = ip_pkt.getfieldval("dst")
|
|
|
+ if tcp_pkt.getfieldval("dport") == self.smb_port:
|
|
|
+ orig_ip_dst = ip_pkt.getfieldval("dst")
|
|
|
|
|
|
|
|
|
- if ip_pkt.getfieldval("dst") == orig_ip_dst:
|
|
|
+ if ip_pkt.getfieldval("dst") == orig_ip_dst:
|
|
|
|
|
|
eth_frame.setfieldval("src", mac_source)
|
|
|
eth_frame.setfieldval("dst", mac_destination)
|
|
@@ -106,6 +159,14 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
ip_pkt.setfieldval("dst", ip_destination)
|
|
|
|
|
|
tcp_pkt.setfieldval("sport",port_source)
|
|
|
+
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
+ new_pkt.time = timestamp_next_pkt
|
|
|
+
|
|
|
+ maxdelay = randomdelay.random()
|
|
|
+ pps = self.minDefaultPPS if getIntervalPPS(timestamp_next_pkt) is None else max(
|
|
|
+ getIntervalPPS(timestamp_next_pkt), self.minDefaultPPS)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
|
|
|
else:
|
|
|
|
|
@@ -117,58 +178,158 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
|
|
|
- new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
-
|
|
|
- new_pkt.time = timestamp_next_pkt
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
+ timestamp_next_pkt = timestamp_next_pkt + uniform(replayDelay, 2 * replayDelay)
|
|
|
+ new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
packets.append(new_pkt)
|
|
|
|
|
|
- maxdelay = randomdelay.random()
|
|
|
- timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
exploit_raw_packets = RawPcapReader("Win7_eternalblue_exploit.pcap")
|
|
|
- for pkt_num, pkt in enumerate(exploit_raw_packets):
|
|
|
- eth_frame = Ether(pkt[0])
|
|
|
- ip_pkt = eth_frame.payload
|
|
|
- tcp_pkt = ip_pkt.payload
|
|
|
-
|
|
|
- smb_port = 445
|
|
|
- if pkt_num == 0:
|
|
|
- if tcp_pkt.getfieldval("dport") == smb_port:
|
|
|
- orig_ip_dst = ip_pkt.getfieldval("dst")
|
|
|
-
|
|
|
-
|
|
|
- if ip_pkt.getfieldval("dst") == orig_ip_dst:
|
|
|
-
|
|
|
- eth_frame.setfieldval("src", mac_source)
|
|
|
- eth_frame.setfieldval("dst", mac_destination)
|
|
|
-
|
|
|
- ip_pkt.setfieldval("src", ip_source)
|
|
|
- ip_pkt.setfieldval("dst", ip_destination)
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- else:
|
|
|
-
|
|
|
- eth_frame.setfieldval("src", mac_destination)
|
|
|
- eth_frame.setfieldval("dst", mac_source)
|
|
|
-
|
|
|
- ip_pkt.setfieldval("src", ip_destination)
|
|
|
- ip_pkt.setfieldval("dst", ip_source)
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
-
|
|
|
- new_pkt.time = timestamp_next_pkt
|
|
|
-
|
|
|
- packets.append(new_pkt)
|
|
|
|
|
|
- maxdelay = randomdelay.random()
|
|
|
- timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
+
|
|
|
+ def packetsToConvs(exploit_raw_packets):
|
|
|
+ conversations = {}
|
|
|
+ orderList_conversations = []
|
|
|
+ for pkt_num, pkt in enumerate(exploit_raw_packets):
|
|
|
+ eth_frame = Ether(pkt[0])
|
|
|
+
|
|
|
+ ip_pkt = eth_frame.payload
|
|
|
+ ip_dst = ip_pkt.getfieldval("dst")
|
|
|
+ ip_src = ip_pkt.getfieldval("src")
|
|
|
+
|
|
|
+ tcp_pkt = ip_pkt.payload
|
|
|
+ port_dst = tcp_pkt.getfieldval("dport")
|
|
|
+ port_src = tcp_pkt.getfieldval("sport")
|
|
|
+
|
|
|
+ conv_req = (ip_src, port_src, ip_dst, port_dst)
|
|
|
+ conv_rep = (ip_dst, port_dst, ip_src, port_src)
|
|
|
+ if conv_req not in conversations and conv_rep not in conversations:
|
|
|
+ pktList = [pkt]
|
|
|
+ conversations[conv_req] = pktList
|
|
|
+
|
|
|
+ orderList_conversations.append(conv_req)
|
|
|
+ else:
|
|
|
+ if conv_req in conversations:
|
|
|
+ pktList = conversations[conv_req]
|
|
|
+ pktList.append(pkt)
|
|
|
+ conversations[conv_req] = pktList
|
|
|
+ else:
|
|
|
+ pktList = conversations[conv_rep]
|
|
|
+ pktList.append(pkt)
|
|
|
+ conversations[conv_rep] = pktList
|
|
|
+ return (conversations,orderList_conversations)
|
|
|
+
|
|
|
+ port_source = randint(self.minDefaultPort,self.maxDefaultPort)
|
|
|
+
|
|
|
+ temp_tuple = packetsToConvs(exploit_raw_packets)
|
|
|
+ conversations = temp_tuple[0]
|
|
|
+ orderList_conversations = temp_tuple[1]
|
|
|
+
|
|
|
+ for conv_index, conv in enumerate(orderList_conversations):
|
|
|
+ conv_pkts = conversations[conv]
|
|
|
+ if conv_index != len(orderList_conversations)-1:
|
|
|
+ port_source += 2
|
|
|
+ for pkt_num, pkt in enumerate(conv_pkts):
|
|
|
+ eth_frame = Ether(pkt[0])
|
|
|
+ ip_pkt = eth_frame.payload
|
|
|
+ tcp_pkt = ip_pkt.payload
|
|
|
+
|
|
|
+ if pkt_num == 0:
|
|
|
+ if tcp_pkt.getfieldval("dport") == self.smb_port:
|
|
|
+ orig_ip_dst = ip_pkt.getfieldval("dst")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if ip_pkt.getfieldval("dst") == orig_ip_dst:
|
|
|
+
|
|
|
+ eth_frame.setfieldval("src", mac_source)
|
|
|
+ eth_frame.setfieldval("dst", mac_destination)
|
|
|
+
|
|
|
+ ip_pkt.setfieldval("src", ip_source)
|
|
|
+ ip_pkt.setfieldval("dst", ip_destination)
|
|
|
+
|
|
|
+ tcp_pkt.setfieldval("sport", port_source)
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
+
|
|
|
+ new_pkt.time = timestamp_next_pkt
|
|
|
+
|
|
|
+ maxdelay = randomdelay.random()
|
|
|
+ pps = self.minDefaultPPS if getIntervalPPS(timestamp_next_pkt) is None else max(
|
|
|
+ getIntervalPPS(timestamp_next_pkt), self.minDefaultPPS)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ else:
|
|
|
+
|
|
|
+ eth_frame.setfieldval("src", mac_destination)
|
|
|
+ eth_frame.setfieldval("dst", mac_source)
|
|
|
+
|
|
|
+ ip_pkt.setfieldval("src", ip_destination)
|
|
|
+ ip_pkt.setfieldval("dst", ip_source)
|
|
|
+
|
|
|
+ tcp_pkt.setfieldval("dport", port_source)
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
+ timestamp_next_pkt = timestamp_next_pkt + uniform(replayDelay, 2 * replayDelay)
|
|
|
+ new_pkt.time = timestamp_next_pkt
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ packets.append(new_pkt)
|
|
|
+
|
|
|
+ else:
|
|
|
+ port_source = randint(self.minDefaultPort,self.maxDefaultPort)
|
|
|
+ for pkt_num, pkt in enumerate(conv_pkts):
|
|
|
+ eth_frame = Ether(pkt[0])
|
|
|
+ ip_pkt = eth_frame.payload
|
|
|
+ tcp_pkt = ip_pkt.payload
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if tcp_pkt.getfieldval("dport") == self.last_conn_dst_port:
|
|
|
+
|
|
|
+ eth_frame.setfieldval("src", mac_destination)
|
|
|
+ eth_frame.setfieldval("dst", mac_source)
|
|
|
+
|
|
|
+ ip_pkt.setfieldval("src", ip_destination)
|
|
|
+ ip_pkt.setfieldval("dst", ip_source)
|
|
|
+
|
|
|
+ tcp_pkt.setfieldval("sport", port_source)
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
+
|
|
|
+ new_pkt.time = timestamp_next_pkt
|
|
|
+
|
|
|
+ maxdelay = randomdelay.random()
|
|
|
+ pps = self.minDefaultPPS if getIntervalPPS(timestamp_next_pkt) is None else max(
|
|
|
+ getIntervalPPS(timestamp_next_pkt), self.minDefaultPPS)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ else:
|
|
|
+
|
|
|
+ eth_frame.setfieldval("src", mac_source)
|
|
|
+ eth_frame.setfieldval("dst", mac_destination)
|
|
|
+
|
|
|
+ ip_pkt.setfieldval("src", ip_source)
|
|
|
+ ip_pkt.setfieldval("dst", ip_destination)
|
|
|
+
|
|
|
+ tcp_pkt.setfieldval("dport", port_source)
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
+ timestamp_next_pkt = timestamp_next_pkt + uniform(replayDelay, 2 * replayDelay)
|
|
|
+ new_pkt.time = timestamp_next_pkt
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ packets.append(new_pkt)
|
|
|
|
|
|
|
|
|
|