|
@@ -1,5 +1,3 @@
|
|
|
-# Created by Aidmar
|
|
|
-
|
|
|
import logging
|
|
|
from random import randint, uniform
|
|
|
|
|
@@ -15,9 +13,7 @@ from scapy.utils import RawPcapReader
|
|
|
from scapy.layers.inet import IP, Ether, TCP, RandShort
|
|
|
|
|
|
class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
- # Metasploit default packet rate
|
|
|
- maxDefaultPPS = 100
|
|
|
- minDefaultPPS = 5
|
|
|
+ template_attack_pcap_path = "resources/Win7_eternalblue_scan.pcap"
|
|
|
# SMB port
|
|
|
smb_port = 445
|
|
|
# Empirical values from Metasploit experiments
|
|
@@ -54,7 +50,9 @@ 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.PACKETS_PER_SECOND,self.maxDefaultPPS)
|
|
|
+ self.add_param_value(Param.PACKETS_PER_SECOND,
|
|
|
+ (self.statistics.get_pps_sent(most_used_ip_address) +
|
|
|
+ self.statistics.get_pps_received(most_used_ip_address)) / 2)
|
|
|
|
|
|
# victim configuration
|
|
|
random_ip_address = self.statistics.get_random_ip_address()
|
|
@@ -66,15 +64,17 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
self.add_param_value(Param.MAC_DESTINATION, destination_mac)
|
|
|
|
|
|
def generate_attack_pcap(self):
|
|
|
- def update_timestamp(timestamp, pps, maxdelay):
|
|
|
+ def update_timestamp(timestamp, pps):
|
|
|
"""
|
|
|
Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
|
|
|
|
|
|
:return: Timestamp to be used for the next packet.
|
|
|
"""
|
|
|
- return timestamp + uniform(1 / pps, maxdelay)
|
|
|
+ # Calculate the request timestamp
|
|
|
+ # A distribution to imitate the bursty behavior of traffic
|
|
|
+ randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
|
|
|
+ return timestamp + uniform(1 / pps, randomdelay.random())
|
|
|
|
|
|
- # Aidmar
|
|
|
def getIntervalPPS(complement_interval_pps, timestamp):
|
|
|
"""
|
|
|
Gets the packet rate (pps) in specific time interval.
|
|
@@ -88,28 +88,24 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
|
|
|
# Timestamp
|
|
|
timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
|
|
|
- # TO-DO: find better pkt rate
|
|
|
pps = self.get_param_value(Param.PACKETS_PER_SECOND)
|
|
|
- randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 30, 5 / pps: 15, 10 / pps: 3})
|
|
|
|
|
|
- # Aidmar - calculate complement packet rates of BG traffic per interval
|
|
|
+ # calculate complement packet rates of BG traffic per interval
|
|
|
complement_interval_pps = self.statistics.calculate_complement_packet_rates(pps)
|
|
|
|
|
|
# Initialize parameters
|
|
|
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)
|
|
|
|
|
|
- # Aidmar - check ip.src == ip.dst
|
|
|
+ # check ip.src == ip.dst
|
|
|
self.ip_src_dst_equal_check(ip_source, ip_destination)
|
|
|
|
|
|
path_attack_pcap = None
|
|
|
minDelay, maxDelay = self.get_reply_delay(ip_destination)
|
|
|
|
|
|
-
|
|
|
# Set TTL based on TTL distribution of IP address
|
|
|
source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
|
|
|
if len(source_ttl_dist) > 0:
|
|
@@ -128,7 +124,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# Scan (MS17) for EternalBlue
|
|
|
# Read Win7_eternalblue_scan_vulnerable pcap file
|
|
|
orig_ip_dst = None
|
|
|
- exploit_raw_packets = RawPcapReader("resources/Win7_eternalblue_scan.pcap")
|
|
|
+ exploit_raw_packets = RawPcapReader(self.template_attack_pcap_path)
|
|
|
|
|
|
port_source = randint(self.minDefaultPort,self.maxDefaultPort) # experiments show this range of ports
|
|
|
|
|
@@ -156,9 +152,8 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
- maxdelay = randomdelay.random()
|
|
|
- pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
- timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps)
|
|
|
# Reply
|
|
|
else:
|
|
|
# Ether
|
|
@@ -186,19 +181,18 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# conversations = {(ip.src, ip.dst, port.src, port.dst): packets}
|
|
|
conversations, orderList_conversations = self.packetsToConvs(exploit_raw_packets)
|
|
|
|
|
|
- # the last two connections have special treatment, they start after the other connections finish
|
|
|
- # TO-DO
|
|
|
-
|
|
|
conv_start_timesamp = timestamp_next_pkt
|
|
|
for conv_index, conv in enumerate(orderList_conversations):
|
|
|
conv_start_timesamp = conv_start_timesamp + uniform(0.001,0.01) # the distance between the starts of the converstaions
|
|
|
timestamp_next_pkt = conv_start_timesamp
|
|
|
|
|
|
conv_pkts = conversations[conv]
|
|
|
+ inter_arrival_time_dist = self.get_inter_arrival_time_dist(conv_pkts)
|
|
|
+ timeSteps = Lea.fromValFreqsDict(inter_arrival_time_dist)
|
|
|
+
|
|
|
if conv_index == len(orderList_conversations) - 2: # Not the last conversation
|
|
|
timestamp_next_pkt = packets[-1].time + uniform(0.001,0.01)
|
|
|
|
|
|
-
|
|
|
if conv_index != len(orderList_conversations)-1: # Not the last conversation
|
|
|
port_source += 2
|
|
|
for pkt_num, pkt in enumerate(conv_pkts):
|
|
@@ -226,9 +220,8 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
- maxdelay = randomdelay.random()
|
|
|
- pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
- timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
|
|
|
|
|
|
# Reply
|
|
|
else:
|
|
@@ -242,7 +235,10 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
- timestamp_next_pkt = timestamp_next_pkt + uniform(minDelay, maxDelay)
|
|
|
+
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
|
|
|
+
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
packets.append(new_pkt)
|
|
@@ -271,9 +267,8 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
- maxdelay = randomdelay.random()
|
|
|
- pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
- timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
|
|
|
|
|
|
# Reply
|
|
|
else:
|
|
@@ -287,7 +282,10 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
- timestamp_next_pkt = timestamp_next_pkt + uniform(minDelay, maxDelay)
|
|
|
+
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
|
|
|
+ timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
|
|
|
+
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
packets.append(new_pkt)
|