|
@@ -39,7 +39,6 @@ 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,
|
|
@@ -55,11 +54,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.PORT_SOURCE, str(RandShort()))
|
|
|
self.add_param_value(Param.PACKETS_PER_SECOND,self.maxDefaultPPS)
|
|
|
|
|
|
# victim configuration
|
|
|
- # TO-DO: confirm that ip.dst uses Win OS
|
|
|
random_ip_address = self.statistics.get_random_ip_address()
|
|
|
self.add_param_value(Param.IP_DESTINATION, random_ip_address)
|
|
|
|
|
@@ -115,10 +112,26 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
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:
|
|
|
+ source_ttl_prob_dict = Lea.fromValFreqsDict(source_ttl_dist)
|
|
|
+ source_ttl_value = source_ttl_prob_dict.random()
|
|
|
+ else:
|
|
|
+ source_ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
|
|
|
+
|
|
|
+ destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
|
|
|
+ if len(destination_ttl_dist) > 0:
|
|
|
+ destination_ttl_prob_dict = Lea.fromValFreqsDict(destination_ttl_dist)
|
|
|
+ destination_ttl_value = destination_ttl_prob_dict.random()
|
|
|
+ else:
|
|
|
+ destination_ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
|
|
|
+
|
|
|
# Scan (MS17) for EternalBlue
|
|
|
# Read Win7_eternalblue_scan_vulnerable pcap file
|
|
|
orig_ip_dst = None
|
|
|
- exploit_raw_packets = RawPcapReader("Win7_eternalblue_scan.pcap")
|
|
|
+ exploit_raw_packets = RawPcapReader("resources/Win7_eternalblue_scan.pcap")
|
|
|
|
|
|
port_source = randint(self.minDefaultPort,self.maxDefaultPort) # experiments show this range of ports
|
|
|
|
|
@@ -139,6 +152,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# IP
|
|
|
ip_pkt.setfieldval("src", ip_source)
|
|
|
ip_pkt.setfieldval("dst", ip_destination)
|
|
|
+ ip_pkt.setfieldval("ttl", source_ttl_value)
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("sport",port_source)
|
|
|
|
|
@@ -146,8 +160,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
maxdelay = randomdelay.random()
|
|
|
- pps = self.minDefaultPPS if getIntervalPPS(complement_interval_pps,timestamp_next_pkt) is None else max(
|
|
|
- getIntervalPPS(complement_interval_pps,timestamp_next_pkt), self.minDefaultPPS)
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
# Reply
|
|
|
else:
|
|
@@ -157,6 +170,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# IP
|
|
|
ip_pkt.setfieldval("src", ip_destination)
|
|
|
ip_pkt.setfieldval("dst", ip_source)
|
|
|
+ ip_pkt.setfieldval("ttl", destination_ttl_value)
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
|
|
@@ -169,49 +183,25 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
|
|
|
# Inject EternalBlue exploit packets
|
|
|
# Read Win7_eternalblue_exploit pcap file
|
|
|
- exploit_raw_packets = RawPcapReader("Win7_eternalblue_exploit.pcap")
|
|
|
-
|
|
|
- # Group the packets in conversations
|
|
|
- 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
|
|
|
- # Order list of conv
|
|
|
- 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)
|
|
|
+ exploit_raw_packets = RawPcapReader("resources/Win7_eternalblue_exploit.pcap")
|
|
|
|
|
|
port_source = randint(self.minDefaultPort,self.maxDefaultPort) # experiments show this range of ports
|
|
|
# conversations = {(ip.src, ip.dst, port.src, port.dst): packets}
|
|
|
- temp_tuple = packetsToConvs(exploit_raw_packets)
|
|
|
- conversations = temp_tuple[0]
|
|
|
- orderList_conversations = temp_tuple[1]
|
|
|
+ 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]
|
|
|
+ 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):
|
|
@@ -223,9 +213,8 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
if tcp_pkt.getfieldval("dport") == self.smb_port:
|
|
|
orig_ip_dst = ip_pkt.getfieldval("dst")
|
|
|
|
|
|
-
|
|
|
# defining req/rep should be adapted to fit the last converstaion where
|
|
|
- # victim start a connection with the attacker
|
|
|
+ # victim starts a connection with the attacker
|
|
|
# Request
|
|
|
if ip_pkt.getfieldval("dst") == orig_ip_dst: # victim IP
|
|
|
# Ether
|
|
@@ -234,18 +223,15 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# IP
|
|
|
ip_pkt.setfieldval("src", ip_source)
|
|
|
ip_pkt.setfieldval("dst", ip_destination)
|
|
|
+ ip_pkt.setfieldval("ttl", source_ttl_value)
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("sport", port_source)
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
- # TO-DO: reply should have different timestamp delay
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
maxdelay = randomdelay.random()
|
|
|
- pps = self.minDefaultPPS if getIntervalPPS(complement_interval_pps, timestamp_next_pkt) is None else max(
|
|
|
- getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
- # Not perfect timestamp
|
|
|
- #req_time = req_time + randomDelay || rep_time + randomDelay
|
|
|
|
|
|
# Reply
|
|
|
else:
|
|
@@ -255,17 +241,17 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# IP
|
|
|
ip_pkt.setfieldval("src", ip_destination)
|
|
|
ip_pkt.setfieldval("dst", ip_source)
|
|
|
+ ip_pkt.setfieldval("ttl", destination_ttl_value)
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
timestamp_next_pkt = timestamp_next_pkt + uniform(minDelay, maxDelay)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
- # Not perfect timestamp
|
|
|
- # rep_time = req_time + replayDelay
|
|
|
|
|
|
packets.append(new_pkt)
|
|
|
|
|
|
else: # Last conversation where the victim start a connection with the attacker
|
|
|
+ timestamp_next_pkt = packets[-1].time + uniform(0.001, 0.01)
|
|
|
port_source = randint(self.minDefaultPort,self.maxDefaultPort)
|
|
|
for pkt_num, pkt in enumerate(conv_pkts):
|
|
|
eth_frame = Ether(pkt[0])
|
|
@@ -282,18 +268,15 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# IP
|
|
|
ip_pkt.setfieldval("src", ip_destination)
|
|
|
ip_pkt.setfieldval("dst", ip_source)
|
|
|
+ ip_pkt.setfieldval("ttl", destination_ttl_value)
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("sport", port_source)
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
- # TO-DO: reply should have different timestamp delay
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
maxdelay = randomdelay.random()
|
|
|
- pps = self.minDefaultPPS if getIntervalPPS(complement_interval_pps, timestamp_next_pkt) is None else max(
|
|
|
- getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
+ pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
- # Not perfect timestamp
|
|
|
- # req_time = req_time + randomDelay || rep_time + randomDelay
|
|
|
|
|
|
# Reply
|
|
|
else:
|
|
@@ -303,13 +286,12 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
|
|
|
# IP
|
|
|
ip_pkt.setfieldval("src", ip_source)
|
|
|
ip_pkt.setfieldval("dst", ip_destination)
|
|
|
+ ip_pkt.setfieldval("ttl", source_ttl_value)
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
new_pkt = (eth_frame / ip_pkt / tcp_pkt)
|
|
|
timestamp_next_pkt = timestamp_next_pkt + uniform(minDelay, maxDelay)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
- # Not perfect timestamp
|
|
|
- # rep_time = req_time + replayDelay
|
|
|
|
|
|
packets.append(new_pkt)
|
|
|
|