#42 extend utility library

병합
carlos.garcia stefan.schmidt/utility-lib-final 에서 SPIN/master 로 2 commits 를 머지했습니다 6 년 전

+ 3 - 3
code/Attack/BaseAttack.py

@@ -5,16 +5,16 @@ import os
 import random
 import re
 import tempfile
-from abc import abstractmethod, ABCMeta
-from scapy.layers.inet import Ether
 import numpy as np
 
-import ID2TLib.libpcapreader as pr
+from abc import abstractmethod, ABCMeta
+from scapy.layers.inet import Ether
 from scapy.utils import PcapWriter
 
 from Attack import AttackParameters
 from Attack.AttackParameters import Parameter
 from Attack.AttackParameters import ParameterTypes
+import ID2TLib.libpcapreader as pr
 
 
 class BaseAttack(metaclass=ABCMeta):

+ 5 - 53
code/Attack/DDoSAttack.py

@@ -1,17 +1,18 @@
 import logging
-from random import randint, uniform, choice
 
+from random import randint, choice
 from lea import Lea
+from collections import deque
 from scipy.stats import gamma
+from scapy.layers.inet import IP, Ether, TCP, RandShort
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+from ID2TLib.Utility import update_timestamp, get_interval_pps, get_nth_random_element, index_increment
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.layers.inet import IP, Ether, TCP, RandShort
-from collections import deque
 
 
 class DDoSAttack(BaseAttack.BaseAttack):
@@ -72,54 +73,6 @@ class DDoSAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.VICTIM_BUFFER, randint(1000,10000))
 
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            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.
-            """
-            if delay == 0:
-                # 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())
-            else:
-                # Calculate the reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2 * delay: 70, 3 * delay: 20, 5 * delay: 7, 10 * delay: 3})
-                return timestamp + uniform(1 / pps + delay, 1 / pps + randomdelay.random())
-
-        def get_nth_random_element(*element_list):
-            """
-            Returns the n-th element of every list from an arbitrary number of given lists.
-            For example, list1 contains IP addresses, list 2 contains MAC addresses. Use of this function ensures that
-            the n-th IP address uses always the n-th MAC address.
-            :param element_list: An arbitrary number of lists.
-            :return: A tuple of the n-th element of every list.
-            """
-            range_max = min([len(x) for x in element_list])
-            if range_max > 0: range_max -= 1
-            n = randint(0, range_max)
-            return tuple(x[n] for x in element_list)
-
-        def index_increment(number: int, max: int):
-            if number + 1 < max:
-                return number + 1
-            else:
-                return 0
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            # In case the timestamp > capture max timestamp
-            return complement_interval_pps[-1][1]
-
         def get_attacker_config(ipAddress: str):
             """
             Returns the attacker configuration depending on the IP address, this includes the port for the next
@@ -151,7 +104,6 @@ class DDoSAttack(BaseAttack.BaseAttack):
                 attacker_ttl_mapping[ipAddress] = ttl
             # return port and TTL
             return next_port, ttl
-
         BUFFER_SIZE = 1000
 
         # Determine source IP and MAC address
@@ -280,7 +232,7 @@ class DDoSAttack(BaseAttack.BaseAttack):
                     replies_count+=1
                     total_pkt_num += 1
 
-                attacker_pps = max(getIntervalPPS(complement_interval_attacker_pps, timestamp_next_pkt), (pps/num_attackers)/2)
+                attacker_pps = max(get_interval_pps(complement_interval_attacker_pps, timestamp_next_pkt), (pps / num_attackers) / 2)
                 timestamp_next_pkt = update_timestamp(timestamp_next_pkt, attacker_pps)
 
                 # Store timestamp of first packet (for attack label)

+ 11 - 29
code/Attack/EternalBlueExploit.py

@@ -1,16 +1,18 @@
 import logging
-from random import randint, uniform
 
+from random import randint, uniform
 from lea import Lea
+from scapy.utils import RawPcapReader
+from scapy.layers.inet import Ether
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+from ID2TLib.Utility import update_timestamp, get_interval_pps
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.utils import RawPcapReader
-from scapy.layers.inet import IP, Ether, TCP, RandShort
+
 
 class EternalBlueExploit(BaseAttack.BaseAttack):
     template_scan_pcap_path = "resources/Win7_eternalblue_scan.pcap"
@@ -78,27 +80,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
         self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
 
     def generate_attack_pcap(self):
-        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.
-            """
-            # 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())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
+
 
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
@@ -202,7 +184,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
                 new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                 new_pkt.time = timestamp_next_pkt
 
-                pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                 timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + inter_arrival_times[pkt_num]#float(timeSteps.random())
             # Reply
             else:
@@ -294,7 +276,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
                         new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                         new_pkt.time = timestamp_next_pkt
 
-                        pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                        pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                         timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + inter_arrival_times[pkt_num] #float(timeSteps.random())
 
                     # Reply
@@ -324,7 +306,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
 
                         new_pkt = (eth_frame / ip_pkt / tcp_pkt)
 
-                        pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                        pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                         timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + inter_arrival_times[pkt_num]#float(timeSteps.random())
 
                         new_pkt.time = timestamp_next_pkt
@@ -367,7 +349,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
                         new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                         new_pkt.time = timestamp_next_pkt
 
-                        pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                        pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                         timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + inter_arrival_times[pkt_num]# float(timeSteps.random())
 
                     # Reply
@@ -397,7 +379,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
 
                         new_pkt = (eth_frame / ip_pkt / tcp_pkt)
 
-                        pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                        pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                         timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + inter_arrival_times[pkt_num]# float(timeSteps.random())
 
                         new_pkt.time = timestamp_next_pkt

+ 6 - 26
code/Attack/JoomlaRegPrivExploit.py

@@ -1,16 +1,17 @@
 import logging
-from random import randint, uniform
 
+from random import randint
 from lea import Lea
+from scapy.utils import RawPcapReader
+from scapy.layers.inet import Ether
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+from ID2TLib.Utility import update_timestamp, get_interval_pps
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.utils import RawPcapReader
-from scapy.layers.inet import IP, Ether, TCP, RandShort
 
 
 class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
@@ -79,27 +80,6 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
 
     def generate_attack_pcap(self):
-        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.
-            """
-            # 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())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1]  # in case the timstamp > capture max timestamp
 
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
@@ -206,7 +186,7 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
                 new_pkt = (eth_frame / ip_pkt/ tcp_pkt / str_tcp_seg)
                 new_pkt.time = timestamp_next_pkt
 
-                pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                 timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
 
             # Reply: Victim --> attacker
@@ -232,7 +212,7 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
                     victim_seq += max(strLen, 1)
 
                 new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
-                pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                pps = max(get_interval_pps(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
 

+ 8 - 32
code/Attack/PortscanAttack.py

@@ -1,17 +1,18 @@
 import logging
 import csv
 
-from random import shuffle, randint, choice, uniform
-
+from random import shuffle, randint, choice
 from lea import Lea
+from scapy.layers.inet import IP, Ether, TCP
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+from ID2TLib.Utility import update_timestamp, get_interval_pps
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.layers.inet import IP, Ether, TCP
+
 
 class PortscanAttack(BaseAttack.BaseAttack):
 
@@ -108,34 +109,9 @@ class PortscanAttack(BaseAttack.BaseAttack):
         return port_dst_shuffled
 
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            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.
-            """
-            if delay == 0:
-                # Calculate request timestamp
-                # 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())
-            else:
-                # Calculate reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2*delay: 70, 3*delay: 20, 5*delay: 7, 10*delay: 3})
-                return timestamp + uniform(1 / pps + delay,  1 / pps + randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
+
+
+
 
         mac_source = self.get_param_value(Param.MAC_SOURCE)
         mac_destination = self.get_param_value(Param.MAC_DESTINATION)
@@ -279,7 +255,7 @@ class PortscanAttack(BaseAttack.BaseAttack):
 
                 # else: destination port is NOT OPEN -> no reply is sent by target
 
-            pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt),10)
+            pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
             timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps)
 
         # store end time of attack

+ 11 - 41
code/Attack/SMBLorisAttack.py

@@ -1,18 +1,18 @@
 import logging
-import csv
-
-from random import shuffle, randint, choice, uniform
 
+from random import randint, uniform
 from lea import Lea
+from scapy.layers.inet import IP, Ether, TCP
+from scapy.layers.netbios import NBTSession
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+from ID2TLib.Utility import update_timestamp
+from ID2TLib.SMBLib import smb_port
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.layers.inet import IP, Ether, TCP
-from scapy.layers.netbios import NBTSession
 
 # Resources:
 # https://github.com/rapid7/metasploit-framework/blob/master/modules/auxiliary/dos/smb/smb_loris.rb
@@ -20,9 +20,8 @@ from scapy.layers.netbios import NBTSession
 # https://gist.githubusercontent.com/marcan/6a2d14b0e3eaa5de1795a763fb58641e/raw/565befecf4d9a4a27248d027a90b6e3e5994b5b6/smbloris.c
 # http://smbloris.com/
 
+
 class SMBLorisAttack(BaseAttack.BaseAttack):
-    # SMB port
-    smb_port = 445
 
     def __init__(self):
         """
@@ -85,35 +84,6 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.ATTACK_DURATION, 30)
 
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            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.
-            """
-            if delay == 0:
-                # Calculate request timestamp
-                # 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())
-            else:
-                # Calculate reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2*delay: 70, 3*delay: 20, 5*delay: 7, 10*delay: 3})
-                return timestamp + uniform(1 / pps + delay,  1 / pps + randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
-
         def getIpData(ip_address: str):
             """
             :param ip_address: the ip of which (packet-)data shall be returned
@@ -224,7 +194,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 victim_ip = IP(src=ip_destination, dst=ip_source_list[attacker], ttl=destination_ttl_value, flags='DF')
 
                 # connection request from attacker (client)
-                syn_tcp = TCP(sport=sport, dport=self.smb_port, window=source_win_value, flags='S',
+                syn_tcp = TCP(sport=sport, dport=smb_port, window=source_win_value, flags='S',
                               seq=attacker_seq, options=[('MSS', source_mss_value)])
                 attacker_seq += 1
                 syn = (attacker_ether / attacker_ip / syn_tcp)
@@ -233,7 +203,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(syn)
 
                 # response from victim (server)
-                synack_tcp = TCP(sport=self.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='SA',
+                synack_tcp = TCP(sport=smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='SA',
                                  window=destination_win_value, options=[('MSS', destination_mss_value)])
                 victim_seq += 1
                 synack = (victim_ether / victim_ip / synack_tcp)
@@ -242,7 +212,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(synack)
 
                 # acknowledgement from attacker (client)
-                ack_tcp = TCP(sport=sport, dport=self.smb_port, seq=attacker_seq, ack=victim_seq, flags='A',
+                ack_tcp = TCP(sport=sport, dport=smb_port, seq=attacker_seq, ack=victim_seq, flags='A',
                               window=source_win_value, options=[('MSS', source_mss_value)])
                 ack = (attacker_ether / attacker_ip / ack_tcp)
                 ack.time = timestamp_next_pkt
@@ -250,7 +220,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(ack)
 
                 # send NBT session header paket with maximum LENGTH-field
-                req_tcp = TCP(sport=sport, dport=self.smb_port, seq=attacker_seq, ack=victim_seq, flags='AP',
+                req_tcp = TCP(sport=sport, dport=smb_port, seq=attacker_seq, ack=victim_seq, flags='AP',
                               window=source_win_value, options=[('MSS', source_mss_value)])
                 req_payload = NBTSession(TYPE=0x00, LENGTH=0x1FFFF)
 
@@ -261,7 +231,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(req)
 
                 # final ack from victim (server)
-                last_ack_tcp = TCP(sport=self.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='A',
+                last_ack_tcp = TCP(sport=smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='A',
                                    window=destination_win_value, options=[('MSS', destination_mss_value)])
                 last_ack = (victim_ether / victim_ip / last_ack_tcp)
                 last_ack.time = timestamp_next_pkt

+ 10 - 37
code/Attack/SMBScanAttack.py

@@ -1,21 +1,23 @@
 import logging
 
-from random import shuffle, randint, choice, uniform
+from random import shuffle, randint
 from lea import Lea
+from scapy.layers.inet import IP, Ether, TCP
+from scapy.layers.smb import *
+from scapy.layers.netbios import *
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
 from ID2TLib.SMB2 import *
-from ID2TLib.Utility import *
-from ID2TLib.SMBLib import *
-
+from ID2TLib.Utility import update_timestamp, get_interval_pps, get_rnd_os, get_ip_range,\
+    generate_source_port_from_platform, get_filetime_format
+from ID2TLib.SMBLib import smb_port, smb_versions, smb_dialects, get_smb_version, get_smb_platform_data,\
+    invalid_smb_version
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.layers.inet import IP, Ether, TCP
-from scapy.layers.smb import *
-from scapy.layers.netbios import *
+
 
 class SMBScanAttack(BaseAttack.BaseAttack):
 
@@ -94,35 +96,6 @@ class SMBScanAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.IP_DESTINATION_END, "0.0.0.0")
 
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            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.
-            """
-            if delay == 0:
-                # Calculate request timestamp
-                # 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())
-            else:
-                # Calculate reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2*delay: 70, 3*delay: 20, 5*delay: 7, 10*delay: 3})
-                return timestamp + uniform(1 / pps + delay,  1 / pps + randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
-
         def get_ip_data(ip_address: str):
             """
             Gets the MSS, TTL and Windows Size values of a given IP
@@ -424,7 +397,7 @@ class SMBScanAttack(BaseAttack.BaseAttack):
                     reply.time = timestamp_reply
                     packets.append(reply)
 
-            pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+            pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
             timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps)
 
         # store end time of attack

+ 6 - 27
code/Attack/SQLiAttack.py

@@ -1,7 +1,10 @@
 import logging
-from random import randint, uniform
 
+from random import randint
 from lea import Lea
+from scapy.utils import RawPcapReader
+from scapy.layers.inet import Ether
+from ID2TLib.Utility import update_timestamp, get_interval_pps
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
@@ -9,8 +12,6 @@ from Attack.AttackParameters import ParameterTypes
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.utils import RawPcapReader
-from scapy.layers.inet import IP, Ether, TCP, RandShort
 
 
 class SQLiAttack(BaseAttack.BaseAttack):
@@ -79,28 +80,6 @@ class SQLiAttack(BaseAttack.BaseAttack):
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
 
     def generate_attack_pcap(self):
-        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.
-            """
-            # 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())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1]  # in case the timstamp > capture max timestamp
-
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         pps = self.get_param_value(Param.PACKETS_PER_SECOND)
@@ -208,7 +187,7 @@ class SQLiAttack(BaseAttack.BaseAttack):
                     new_pkt = (eth_frame / ip_pkt/ tcp_pkt / str_tcp_seg)
                     new_pkt.time = timestamp_next_pkt
 
-                    pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                    pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                     timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
 
                 # Victim --> attacker
@@ -270,7 +249,7 @@ class SQLiAttack(BaseAttack.BaseAttack):
                     new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
                     new_pkt.time = timestamp_next_pkt
 
-                    pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+                    pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
                     timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
 
                 # Victim --> attacker

+ 5 - 26
code/Attack/SalityBotnet.py

@@ -1,16 +1,16 @@
 import logging
-from random import randint, uniform
 
-from lea import Lea
+from random import randint
+from scapy.utils import RawPcapReader
+from scapy.layers.inet import Ether
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+from ID2TLib.Utility import update_timestamp, get_interval_pps
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
-from scapy.utils import RawPcapReader
-from scapy.layers.inet import IP, Ether, TCP, RandShort
 
 
 class SalityBotnet(BaseAttack.BaseAttack):
@@ -57,27 +57,6 @@ class SalityBotnet(BaseAttack.BaseAttack):
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
 
     def generate_attack_pcap(self):
-        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.
-            """
-            # 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())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1]  # in case the timstamp > capture max timestamp
 
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
@@ -143,7 +122,7 @@ class SalityBotnet(BaseAttack.BaseAttack):
             new_pkt = (eth_frame / ip_pkt)
             new_pkt.time = timestamp_next_pkt
 
-            pps = max(getIntervalPPS(complement_interval_pps, timestamp_next_pkt), 10)
+            pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
             timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps)
 
             packets.append(new_pkt)

+ 1 - 2
code/ID2TLib/SMB2.py

@@ -3,7 +3,6 @@ from scapy.fields import *
 from scapy.layers.netbios import NBTSession
 
 
-
 class SMB2_SYNC_Header(Packet):
     namez = "SMB2Negociate Protocol Response Header"
     fields_desc = [StrFixedLenField("Start","\xfeSMB", 4),
@@ -21,6 +20,7 @@ class SMB2_SYNC_Header(Packet):
                    LELongField("Signature1", 0),
                    LELongField("Signature2", 0)]
 
+
 #No Support of Security Buffer , Padding or Dialect Revision 0x0311
 class SMB2_Negotiate_Protocol_Response(Packet):
     namez = "SMB2Negociate Protocol Response"
@@ -41,6 +41,5 @@ class SMB2_Negotiate_Protocol_Response(Packet):
                    LEIntField("NegotiateContextOffset/Reserved2", 0)]
 
 
-
 bind_layers(NBTSession, SMB2_SYNC_Header,)
 bind_layers(SMB2_SYNC_Header, SMB2_Negotiate_Protocol_Response,)

+ 2 - 3
code/ID2TLib/SMBLib.py

@@ -1,9 +1,8 @@
 from os import urandom
 from binascii import b2a_hex
+from random import random
 
-from ID2TLib.Utility import *
-
-from scapy.layers.netbios import *
+from ID2TLib.Utility import check_platform, get_filetime_format, get_rnd_boot_time
 
 # SMB port
 smb_port = 445

+ 61 - 8
code/ID2TLib/Utility.py

@@ -1,12 +1,66 @@
-from random import randint
-from datetime import datetime, timedelta, tzinfo
-from calendar import timegm
+import ipaddress
 
+from random import randint, uniform
+from datetime import datetime
+from calendar import timegm
 from lea import Lea
 
-from scapy.layers.netbios import *
-
 platforms = {"win7", "win10", "winxp", "win8.1", "macos", "linux", "win8", "winvista", "winnt", "win2000"}
+platform_probability = {"win7": 48.43, "win10": 27.99, "winxp": 6.07, "win8.1": 6.07, "macos": 5.94, "linux": 3.38,
+                        "win8": 1.35, "winvista": 0.46, "winnt": 0.31}
+
+
+def update_timestamp(timestamp, pps, delay=0):
+    """
+    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.
+    """
+    if delay == 0:
+        # Calculate request timestamp
+        # 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())
+    else:
+        # Calculate reply timestamp
+        randomdelay = Lea.fromValFreqsDict({2 * delay: 70, 3 * delay: 20, 5 * delay: 7, 10 * delay: 3})
+        return timestamp + uniform(1 / pps + delay, 1 / pps + randomdelay.random())
+
+
+def get_interval_pps(complement_interval_pps, timestamp):
+    """
+    Gets the packet rate (pps) for a specific time interval.
+
+    :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the
+    corresponding interval).
+    :param timestamp: the timestamp at which the packet rate is required.
+    :return: the corresponding packet rate (pps) .
+    """
+    for row in complement_interval_pps:
+        if timestamp<=row[0]:
+            return row[1]
+    return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
+
+
+def get_nth_random_element(*element_list):
+    """
+    Returns the n-th element of every list from an arbitrary number of given lists.
+    For example, list1 contains IP addresses, list 2 contains MAC addresses. Use of this function ensures that
+    the n-th IP address uses always the n-th MAC address.
+    :param element_list: An arbitrary number of lists.
+    :return: A tuple of the n-th element of every list.
+    """
+    range_max = min([len(x) for x in element_list])
+    if range_max > 0: range_max -= 1
+    n = randint(0, range_max)
+    return tuple(x[n] for x in element_list)
+
+
+def index_increment(number: int, max: int):
+            if number + 1 < max:
+                return number + 1
+            else:
+                return 0
 
 
 def get_rnd_os():
@@ -15,8 +69,7 @@ def get_rnd_os():
 
     :return: random platform as string
     """
-    os_dist = Lea.fromValFreqsDict({"win7": 48.43, "win10": 27.99, "winxp": 6.07, "win8.1": 6.07, "macos": 5.94,
-                                    "linux": 3.38, "win8": 1.35, "winvista": 0.46, "winnt": 0.31})
+    os_dist = Lea.fromValFreqsDict(platform_probability)
     return os_dist.random()
 
 
@@ -113,4 +166,4 @@ def get_rnd_boot_time(timestamp, platform="winxp"):
         uptime_in_days = Lea.fromValFreqsDict({3: 50, 7: 25, 14: 12.5, 31: 6.25, 92: 3.125, 183: 1.5625,
                                                365: 0.78125, 1461: 0.78125})
     timestamp -= randint(0, uptime_in_days.random()*86400)
-    return timestamp
+    return timestamp