6
5

3 Commits 2c3f4c9a1c ... 55a6276c93

Autor SHA1 Mensagem Data
  Patrick Jattke 55a6276c93 - Implemented DoS attack há 7 anos atrás
  Patrick Jattke 53e2150d06 - Improves PortscanAttack: Derives TTL of source IP address based on collected statistics há 7 anos atrás
  Patrick Jattke 9e9fe28404 - Improves the human-readable output in the label file há 7 anos atrás

+ 13 - 11
code/Attack/AttackParameters.py

@@ -6,26 +6,29 @@ class Parameter(Enum):
     Defines the shortname for attack parameters. The shortname may be used for attack parameter specification
     Defines the shortname for attack parameters. The shortname may be used for attack parameter specification
     when calling ID2T via the command line.
     when calling ID2T via the command line.
     """
     """
-    # type: IP address ------------------------------
+    # recommended type: IP address -------------------------------
     IP_SOURCE = 'ip.src'  # source IP address
     IP_SOURCE = 'ip.src'  # source IP address
     IP_DESTINATION = 'ip.dst'  # destination IP address
     IP_DESTINATION = 'ip.dst'  # destination IP address
     IP_DNS = 'ip.dns'  # IP address of DNS server
     IP_DNS = 'ip.dns'  # IP address of DNS server
-    # type: MAC address -----------------------------
+    # recommended type: MAC address ------------------------------
     MAC_SOURCE = 'mac.src'  # MAC address of source
     MAC_SOURCE = 'mac.src'  # MAC address of source
     MAC_DESTINATION = 'mac.dst'  # MAC address of destination
     MAC_DESTINATION = 'mac.dst'  # MAC address of destination
-    # type: Port ------------------------------------
+    # recommended type: Port -------------------------------------
     PORT_OPEN = 'port.open'  # open ports
     PORT_OPEN = 'port.open'  # open ports
     PORT_DESTINATION = 'port.dst'  # destination ports
     PORT_DESTINATION = 'port.dst'  # destination ports
     PORT_SOURCE = 'port.src'  # source ports
     PORT_SOURCE = 'port.src'  # source ports
-    # type: Digits ----------------------------------
+    # recommended type: Integer positive -------------------------
+    PACKETS_LIMIT = 'packets.limit'  # the
+    # recommended type: Float ------------------------------------
     PACKETS_PER_SECOND = 'packets.per-second'  # packets per second
     PACKETS_PER_SECOND = 'packets.per-second'  # packets per second
-    INJECT_AT_TIMESTAMP = 'inject.at-timestamp'  # unix epoch time where attack should be injected
+    INJECT_AT_TIMESTAMP = 'inject.at-timestamp'  # unix epoch time (seconds.millis) where attack should be injected
+    # recommended type: Packet Position ----------------------------------
     INJECT_AFTER_PACKET = 'inject.after-pkt'  # packet after which attack should be injected
     INJECT_AFTER_PACKET = 'inject.after-pkt'  # packet after which attack should be injected
-    # type: boolean  --------------------------------
+    # recommended type: boolean  --------------------------------
     PORT_DEST_SHUFFLE = 'port.dst.shuffle'  # shuffles the destination ports if a list of ports is given
     PORT_DEST_SHUFFLE = 'port.dst.shuffle'  # shuffles the destination ports if a list of ports is given
-    PORT_ORDER_DESC = 'port.dst.order-desc'  # uses a descending port order instead of a ascending order
+    PORT_DEST_ORDER_DESC = 'port.dst.order-desc'  # uses a descending port order instead of a ascending order
     IP_SOURCE_RANDOMIZE = 'ip.src.shuffle'  # randomizes the sources IP address if a list of IP addresses is given
     IP_SOURCE_RANDOMIZE = 'ip.src.shuffle'  # randomizes the sources IP address if a list of IP addresses is given
-    PORT_SOURCE_RANDOM = 'port.src.shuffle'  # randomizes the source port if a list of sources ports is given
+    PORT_SOURCE_RANDOMIZE = 'port.src.shuffle'  # randomizes the source port if a list of sources ports is given
 
 
 
 
 class ParameterTypes(Enum):
 class ParameterTypes(Enum):
@@ -39,6 +42,5 @@ class ParameterTypes(Enum):
     TYPE_INTEGER_POSITIVE = 3
     TYPE_INTEGER_POSITIVE = 3
     TYPE_TIMESTAMP = 4
     TYPE_TIMESTAMP = 4
     TYPE_BOOLEAN = 5
     TYPE_BOOLEAN = 5
-    TYPE_ASC_DSC = 6
-    TYPE_FLOAT = 7
-    TYPE_PACKET_POSITION = 8  # used to derive timestamp from parameter INJECT_AFTER_PACKET
+    TYPE_FLOAT = 6
+    TYPE_PACKET_POSITION = 7  # used to derive timestamp from parameter INJECT_AFTER_PACKET

+ 75 - 2
code/Attack/BaseAttack.py

@@ -108,7 +108,9 @@ class BaseAttack(metaclass=ABCMeta):
             """
             """
             return num < 0 or num > 65535
             return num < 0 or num > 65535
 
 
-        ports_input = ports_input.replace(' ', '').split(',')
+        if isinstance(ports_input, str):
+            ports_input = ports_input.replace(' ', '').split(',')
+
         ports_output = []
         ports_output = []
 
 
         for port_entry in ports_input:
         for port_entry in ports_input:
@@ -240,7 +242,11 @@ class BaseAttack(metaclass=ABCMeta):
         elif param_type == ParameterTypes.TYPE_MAC_ADDRESS:
         elif param_type == ParameterTypes.TYPE_MAC_ADDRESS:
             is_valid = self._is_mac_address(value)
             is_valid = self._is_mac_address(value)
         elif param_type == ParameterTypes.TYPE_INTEGER_POSITIVE:
         elif param_type == ParameterTypes.TYPE_INTEGER_POSITIVE:
-            is_valid = value is None or (value.isdigit() and int(value) >= 0)
+            if isinstance(value, int) and int(value) >= 0:
+                is_valid = True
+            elif isinstance(value, str) and value.isdigit() and int(value) >= 0:
+                is_valid = True
+                value = int(value)
         elif param_type == ParameterTypes.TYPE_FLOAT:
         elif param_type == ParameterTypes.TYPE_FLOAT:
             is_valid, value = self._is_float(value)
             is_valid, value = self._is_float(value)
             # this is required to avoid that the timestamp's microseconds of the first attack packet is '000000'
             # this is required to avoid that the timestamp's microseconds of the first attack packet is '000000'
@@ -275,3 +281,70 @@ class BaseAttack(metaclass=ABCMeta):
         :return: The parameter's value.
         :return: The parameter's value.
         """
         """
         return self.params[param]
         return self.params[param]
+
+    def check_parameters(self):
+        """
+        Checks whether all parameter values are defined. If a value is not defined, the application is terminated.
+        However, this should not happen as all attack should define default parameter values.
+        """
+        for param, type in self.supported_params.items():
+            # checks whether all params have assigned values, INJECT_AFTER_PACKET must not be considered because the
+            # timestamp derived from it is set to Parameter.INJECT_AT_TIMESTAMP
+            if param not in self.params.keys() and param is not Parameter.INJECT_AFTER_PACKET:
+                print("\033[91mCRITICAL ERROR: Attack '" + self.attack_name + "' does not define the parameter '" +
+                      str(param) + "'.\n The attack must define default values for all parameters."
+                      + "\n Cannot continue attack generation.\033[0m")
+                import sys
+                sys.exit(0)
+
+    def generate_random_ipv4_address(self, n: int = 1):
+        """
+        Generates n random IPv4 addresses.
+        :param n: The number of IP addresses to be generated
+        :return: A single IP address, or if n>1, a list of IP addresses
+        """
+
+        def is_invalid(ipAddress: ipaddress.IPv4Address):
+            return ipAddress.is_multicast or ipAddress.is_unspecified or ipAddress.is_loopback or \
+                   ipAddress.is_link_local or ipAddress.is_reserved
+
+        def generate_address():
+            return ipaddress.IPv4Address(random.randint(0, 2 ** 32 - 1))
+
+        ip_addresses = []
+        for i in range(0, n):
+            address = generate_address()
+            while (is_invalid(address)):
+                address = generate_address()
+            ip_addresses.append(str(address))
+
+        if n == 1:
+            return ip_addresses[0]
+        else:
+            return ip_addresses
+
+    def generate_random_ipv6_address(self, n: int = 1):
+        """
+        Generates n random IPv6 addresses.
+        :param n: The number of IP addresses to be generated
+        :return: A single IP address, or if n>1, a list of IP addresses
+        """
+
+        def is_invalid(ipAddress: ipaddress.IPv6Address):
+            return ipAddress.is_multicast or ipAddress.is_unspecified or ipAddress.is_loopback or \
+                   ipAddress.is_link_local or ipAddress.is_reserved
+
+        def generate_address():
+            return str(ipaddress.IPv6Address(random.randint(0, 2 ** 128 - 1)))
+
+        ip_addresses = []
+        for i in range(0, n):
+            address = generate_address()
+            while (is_invalid(address)):
+                address = generate_address()
+            ip_addresses.append(str(address))
+
+        if n == 1:
+            return ip_addresses[0]
+        else:
+            return ip_addresses

+ 134 - 0
code/Attack/DosAttack.py

@@ -0,0 +1,134 @@
+import logging
+from random import randint, choice, uniform
+from lea import Lea
+from Attack import BaseAttack
+from Attack.AttackParameters import Parameter as Param
+from Attack.AttackParameters import ParameterTypes
+
+logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
+# noinspection PyPep8
+from scapy.layers.inet import IP, Ether, TCP, RandShort
+from collections import deque
+
+
+class DosAttack(BaseAttack.BaseAttack):
+    def __init__(self, statistics, pcap_file_path):
+        """
+        Creates a new instance of the PortscanAttack.
+
+        :param statistics: A reference to the statistics class.
+        """
+        # Initialize attack
+        super(DosAttack, self).__init__(statistics, "DoS Attack", "Injects a DoS attack'",
+                                        "Resource Exhaustion")
+
+        # Define allowed parameters and their type
+        self.supported_params = {
+            Param.IP_SOURCE: ParameterTypes.TYPE_IP_ADDRESS,
+            Param.MAC_SOURCE: ParameterTypes.TYPE_MAC_ADDRESS,
+            Param.PORT_SOURCE: ParameterTypes.TYPE_PORT,
+            Param.PORT_SOURCE_RANDOMIZE: ParameterTypes.TYPE_BOOLEAN,
+            Param.IP_DESTINATION: ParameterTypes.TYPE_IP_ADDRESS,
+            Param.MAC_DESTINATION: ParameterTypes.TYPE_MAC_ADDRESS,
+            Param.PORT_DESTINATION: ParameterTypes.TYPE_PORT,
+            Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
+            Param.INJECT_AFTER_PACKET: ParameterTypes.TYPE_PACKET_POSITION,
+            Param.PACKETS_PER_SECOND: ParameterTypes.TYPE_FLOAT,
+            Param.PACKETS_LIMIT: ParameterTypes.TYPE_INTEGER_POSITIVE
+        }
+
+        # PARAMETERS: initialize with default values
+        # (values are overwritten if user specifies them)
+        most_used_ip_address = self.statistics.get_most_used_ip_address()
+        if isinstance(most_used_ip_address, list): most_used_ip_address = most_used_ip_address[0]
+        self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
+        # sender configuration
+        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.PORT_SOURCE, str(RandShort()))
+        self.add_param_value(Param.PORT_SOURCE_RANDOMIZE, False)
+        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)
+        # receiver configuration
+        random_ip_address = self.statistics.get_random_ip_address()
+        self.add_param_value(Param.IP_DESTINATION, random_ip_address)
+        self.add_param_value(Param.MAC_DESTINATION, self.statistics.get_mac_address(random_ip_address))
+        self.add_param_value(Param.PORT_DESTINATION, '80')
+        self.add_param_value(Param.PACKETS_LIMIT, randint(10, 1000))
+
+    def get_packets(self):
+        def update_timestamp(timestamp, pps, maxdelay):
+            """
+            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(0.1 / pps, maxdelay)
+
+        def get_nth_random_element(*element_list):
+            """
+
+            :param element_list:
+            :return:
+            """
+            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)
+
+        BUFFER_SIZE_PACKETS = self.get_param_value(Param.PACKETS_LIMIT)
+
+        # Timestamp
+        timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
+        # store start time of attack
+        self.attack_start_utime = timestamp_next_pkt
+        pps = self.get_param_value(Param.PACKETS_PER_SECOND)
+        randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 30, 5 / pps: 15, 10 / pps: 3})
+
+        # Initialize parameters
+        packets = deque(maxlen=BUFFER_SIZE_PACKETS)
+        # 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)
+        port_destination = self.get_param_value(Param.PORT_DESTINATION)
+
+        # Set TTL based on TTL distribution of IP address
+        ttl_dist = self.statistics.get_ttl_distribution(ip_source)
+        if len(ttl_dist) > 0:
+            ttl_prob_dict = Lea.fromValFreqsDict(ttl_dist)
+            ttl_value = ttl_prob_dict.random()
+        else:
+            ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
+
+        # MSS (Maximum Segment Size) for Ethernet. Allowed values [536,1500]
+        mss = self.statistics.get_mss(ip_destination)
+
+        for pkt_num in range(self.get_param_value(Param.PACKETS_LIMIT)):
+            # Determine source port
+            if self.get_param_value(Param.PORT_SOURCE_RANDOMIZE):
+                cur_port_source = RandShort()
+            elif isinstance(port_source, list):
+                cur_port_source = choice(port_source)
+            else:
+                cur_port_source = port_source
+
+            maxdelay = randomdelay.random()
+
+            request_ether = Ether(dst=mac_destination, src=mac_source)
+            request_ip = IP(src=ip_source, dst=ip_destination, ttl=ttl_value)
+            request_tcp = TCP(sport=cur_port_source, dport=port_destination, flags='S', ack=0)
+
+            request = (request_ether / request_ip / request_tcp)
+            request.time = timestamp_next_pkt
+            packets.append(request)
+
+            timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
+
+        self.attack_end_utime = request.time
+
+        # return packets sorted by packet time_sec_start
+        return sorted(packets, key=lambda pkt: pkt.time)

+ 24 - 28
code/Attack/PortscanAttack.py

@@ -35,10 +35,11 @@ class PortscanAttack(BaseAttack.BaseAttack):
             Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
             Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
             Param.INJECT_AFTER_PACKET: ParameterTypes.TYPE_PACKET_POSITION,
             Param.INJECT_AFTER_PACKET: ParameterTypes.TYPE_PACKET_POSITION,
             Param.PORT_DEST_SHUFFLE: ParameterTypes.TYPE_BOOLEAN,
             Param.PORT_DEST_SHUFFLE: ParameterTypes.TYPE_BOOLEAN,
-            Param.PORT_ORDER_DESC: ParameterTypes.TYPE_BOOLEAN,
+            Param.PORT_DEST_ORDER_DESC: ParameterTypes.TYPE_BOOLEAN,
             Param.IP_SOURCE_RANDOMIZE: ParameterTypes.TYPE_BOOLEAN,
             Param.IP_SOURCE_RANDOMIZE: ParameterTypes.TYPE_BOOLEAN,
             Param.PACKETS_PER_SECOND: ParameterTypes.TYPE_FLOAT,
             Param.PACKETS_PER_SECOND: ParameterTypes.TYPE_FLOAT,
-            Param.PORT_SOURCE_RANDOM: ParameterTypes.TYPE_BOOLEAN}
+            Param.PORT_SOURCE_RANDOMIZE: ParameterTypes.TYPE_BOOLEAN
+        }
 
 
         # PARAMETERS: initialize with default values
         # PARAMETERS: initialize with default values
         # (values are overwritten if user specifies them)
         # (values are overwritten if user specifies them)
@@ -57,10 +58,10 @@ class PortscanAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.PORT_DESTINATION, '0-1023,1720,1900,8080')
         self.add_param_value(Param.PORT_DESTINATION, '0-1023,1720,1900,8080')
         self.add_param_value(Param.PORT_OPEN, '8080,9232,9233')
         self.add_param_value(Param.PORT_OPEN, '8080,9232,9233')
         self.add_param_value(Param.PORT_DEST_SHUFFLE, 'False')
         self.add_param_value(Param.PORT_DEST_SHUFFLE, 'False')
-        self.add_param_value(Param.PORT_ORDER_DESC, 'False')
+        self.add_param_value(Param.PORT_DEST_ORDER_DESC, 'False')
 
 
         self.add_param_value(Param.PORT_SOURCE, '8542')
         self.add_param_value(Param.PORT_SOURCE, '8542')
-        self.add_param_value(Param.PORT_SOURCE_RANDOM, 'False')
+        self.add_param_value(Param.PORT_SOURCE_RANDOMIZE, 'False')
 
 
         self.add_param_value(Param.PACKETS_PER_SECOND,
         self.add_param_value(Param.PACKETS_PER_SECOND,
                              (self.statistics.get_pps_sent(most_used_ip_address) +
                              (self.statistics.get_pps_sent(most_used_ip_address) +
@@ -78,27 +79,19 @@ class PortscanAttack(BaseAttack.BaseAttack):
 
 
         # Determine ports
         # Determine ports
         dest_ports = self.get_param_value(Param.PORT_DESTINATION)
         dest_ports = self.get_param_value(Param.PORT_DESTINATION)
-        if self.get_param_value(Param.PORT_ORDER_DESC):
+        if self.get_param_value(Param.PORT_DEST_ORDER_DESC):
             dest_ports.reverse()
             dest_ports.reverse()
         elif self.get_param_value(Param.PORT_DEST_SHUFFLE):
         elif self.get_param_value(Param.PORT_DEST_SHUFFLE):
             shuffle(dest_ports)
             shuffle(dest_ports)
-        if self.get_param_value(Param.PORT_SOURCE_RANDOM):
+        if self.get_param_value(Param.PORT_SOURCE_RANDOMIZE):
             sport = randint(0, 65535)
             sport = randint(0, 65535)
         else:
         else:
             sport = self.get_param_value(Param.PORT_SOURCE)
             sport = self.get_param_value(Param.PORT_SOURCE)
 
 
-        # Get TTL distribution
-        # keys = list(self.statistics.get_ttl_distribution().vals()
-        # values = list(self.statistics.get_ttl_distribution().pmf())
-        # TTL_samples = numpy.random.choice(keys, size=len(dest_ports), replace=True, dport=values)
-        ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
-
         # Timestamp
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
-        self.attack_start_utime = timestamp_next_pkt  # store start time of attack
-        pps = self.get_param_value(Param.PACKETS_PER_SECOND)
-        randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 30, 5 / pps: 15, 10 / pps: 3})
-        maxdelay = randomdelay.random()
+        # store start time of attack
+        self.attack_start_utime = timestamp_next_pkt
 
 
         # Initialize parameters
         # Initialize parameters
         packets = []
         packets = []
@@ -106,10 +99,21 @@ class PortscanAttack(BaseAttack.BaseAttack):
         ip_destination = self.get_param_value(Param.IP_DESTINATION)
         ip_destination = self.get_param_value(Param.IP_DESTINATION)
         mac_source = self.get_param_value(Param.MAC_SOURCE)
         mac_source = self.get_param_value(Param.MAC_SOURCE)
         mac_destination = self.get_param_value(Param.MAC_DESTINATION)
         mac_destination = self.get_param_value(Param.MAC_DESTINATION)
+        pps = self.get_param_value(Param.PACKETS_PER_SECOND)
+        randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 30, 5 / pps: 15, 10 / pps: 3})
+        maxdelay = randomdelay.random()
 
 
         # MSS (Maximum Segment Size) for Ethernet. Allowed values [536,1500]
         # MSS (Maximum Segment Size) for Ethernet. Allowed values [536,1500]
         mss = self.statistics.get_mss(ip_destination)
         mss = self.statistics.get_mss(ip_destination)
 
 
+        # Set TTL based on TTL distribution of IP address
+        ttl_dist = self.statistics.get_ttl_distribution(ip_source)
+        if len(ttl_dist) > 0:
+            ttl_prob_dict = Lea.fromValFreqsDict(ttl_dist)
+            ttl_value = ttl_prob_dict.random()
+        else:
+            ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
+
         for dport in dest_ports:
         for dport in dest_ports:
             # Parameters changing each iteration
             # Parameters changing each iteration
             if self.get_param_value(Param.IP_SOURCE_RANDOMIZE) and isinstance(ip_source, list):
             if self.get_param_value(Param.IP_SOURCE_RANDOMIZE) and isinstance(ip_source, list):
@@ -118,7 +122,7 @@ class PortscanAttack(BaseAttack.BaseAttack):
             # 1) Build request package
             # 1) Build request package
             request_ether = Ether(src=mac_source, dst=mac_destination)
             request_ether = Ether(src=mac_source, dst=mac_destination)
             request_ip = IP(src=ip_source, dst=ip_destination, ttl=ttl_value)
             request_ip = IP(src=ip_source, dst=ip_destination, ttl=ttl_value)
-            request_tcp = TCP(sport=sport, dport=dport)
+            request_tcp = TCP(sport=sport, dport=dport, flags='S')
             request = (request_ether / request_ip / request_tcp)
             request = (request_ether / request_ip / request_tcp)
             # first packet uses timestamp provided by attack parameter Param.INJECT_AT_TIMESTAMP
             # first packet uses timestamp provided by attack parameter Param.INJECT_AT_TIMESTAMP
             if len(packets) > 0:
             if len(packets) > 0:
@@ -127,17 +131,15 @@ class PortscanAttack(BaseAttack.BaseAttack):
             packets.append(request)
             packets.append(request)
 
 
             # 2) Build reply package
             # 2) Build reply package
-            reply_ether = Ether(src=mac_destination, dst=mac_source)
-            reply_ip = IP(src=ip_destination, dst=ip_source, flags='DF')
-
             if dport in self.get_param_value(Param.PORT_OPEN):  # destination port is OPEN
             if dport in self.get_param_value(Param.PORT_OPEN):  # destination port is OPEN
+                reply_ether = Ether(src=mac_destination, dst=mac_source)
+                reply_ip = IP(src=ip_destination, dst=ip_source, flags='DF')
                 # target answers
                 # target answers
                 if mss is None:
                 if mss is None:
                     reply_tcp = TCP(sport=dport, dport=sport, seq=0, ack=1, flags='SA', window=29200)
                     reply_tcp = TCP(sport=dport, dport=sport, seq=0, ack=1, flags='SA', window=29200)
                 else:
                 else:
                     reply_tcp = TCP(sport=dport, dport=sport, seq=0, ack=1, flags='SA', window=29200,
                     reply_tcp = TCP(sport=dport, dport=sport, seq=0, ack=1, flags='SA', window=29200,
                                     options=[('MSS', mss)])
                                     options=[('MSS', mss)])
-                # reply_tcp.time = time_sec_start + random.uniform(0.00005, 0.00013)
                 reply = (reply_ether / reply_ip / reply_tcp)
                 reply = (reply_ether / reply_ip / reply_tcp)
                 timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
                 timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
                 reply.time = timestamp_next_pkt
                 reply.time = timestamp_next_pkt
@@ -152,13 +154,7 @@ class PortscanAttack(BaseAttack.BaseAttack):
                 reply.time = timestamp_next_pkt
                 reply.time = timestamp_next_pkt
                 packets.append(reply)
                 packets.append(reply)
 
 
-                # else:  # destination port is NOT OPEN -> no reply is sent by target
-                #     reply_tcp = TCP(sport=dport, dport=sport, flags='RA', seq=1, ack=1, window=0)
-                #     # reply_tcp.time = time_sec_start + random.uniform(0.00005, 0.00013)
-                #     reply = (reply_ether / reply_ip / reply_tcp)
-                #     timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
-                #     reply.time = timestamp_next_pkt
-                #     packets.append(reply)
+                # else: destination port is NOT OPEN -> no reply is sent by target
 
 
         # store end time of attack
         # store end time of attack
         self.attack_end_utime = reply.time
         self.attack_end_utime = reply.time

+ 0 - 0
code/GUI/__init__.py


+ 8 - 2
code/ID2TLib/AttackController.py

@@ -1,9 +1,8 @@
 import importlib
 import importlib
 import os
 import os
 import tempfile
 import tempfile
-
+import sys
 from scapy.utils import PcapWriter
 from scapy.utils import PcapWriter
-
 from Attack.AttackParameters import Parameter
 from Attack.AttackParameters import Parameter
 from ID2TLib import LabelManager
 from ID2TLib import LabelManager
 from ID2TLib import Statistics
 from ID2TLib import Statistics
@@ -32,7 +31,14 @@ class AttackController:
         Writes the attack's packets into a PCAP file with a temporary filename.
         Writes the attack's packets into a PCAP file with a temporary filename.
         :return: The path of the written PCAP file.
         :return: The path of the written PCAP file.
         """
         """
+        # Check if all req. parameters are set
+        self.current_attack.check_parameters()
+
+        # Create attack packets
+        print("Generating attack packets...", end=" ")
+        sys.stdout.flush()  # force python to print text immediately
         packets = self.current_attack.get_packets()
         packets = self.current_attack.get_packets()
+        print("done.")
 
 
         # Write packets into pcap file
         # Write packets into pcap file
         temp_pcap = tempfile.NamedTemporaryFile(delete=False)
         temp_pcap = tempfile.NamedTemporaryFile(delete=False)

+ 5 - 0
code/ID2TLib/Controller.py

@@ -1,5 +1,7 @@
 import os
 import os
 
 
+import sys
+
 from ID2TLib.AttackController import AttackController
 from ID2TLib.AttackController import AttackController
 from ID2TLib.LabelManager import LabelManager
 from ID2TLib.LabelManager import LabelManager
 from ID2TLib.PcapFile import PcapFile
 from ID2TLib.PcapFile import PcapFile
@@ -49,8 +51,11 @@ class Controller:
             self.written_pcaps.append(self.pcap_dest_path)
             self.written_pcaps.append(self.pcap_dest_path)
 
 
         # delete intermediate PCAP files
         # delete intermediate PCAP files
+        print('Deleting intermediate attack pcaps...', end="")
+        sys.stdout.flush()  # force python to print text immediately
         for i in range(len(self.written_pcaps) - 1):
         for i in range(len(self.written_pcaps) - 1):
             os.remove(self.written_pcaps[i])
             os.remove(self.written_pcaps[i])
+        print("done.")
 
 
         # print status message
         # print status message
         print('\nOutput file created: ', self.pcap_dest_path)
         print('\nOutput file created: ', self.pcap_dest_path)

+ 1 - 1
code/ID2TLib/LabelManager.py

@@ -76,7 +76,7 @@ class LabelManager:
 
 
             # add timestamp in human-readable format
             # add timestamp in human-readable format
             timestamp_hr = doc.createElement(self.TAG_TIMESTAMP_HR)
             timestamp_hr = doc.createElement(self.TAG_TIMESTAMP_HR)
-            timestamp_hr_text = datetime.fromtimestamp(int(timestamp_entry)).strftime('%Y-%m-%d %H:%M:%S')
+            timestamp_hr_text = datetime.fromtimestamp(timestamp_entry).strftime('%Y-%m-%d %H:%M:%S.%f')
             timestamp_hr.appendChild(doc.createTextNode(timestamp_hr_text))
             timestamp_hr.appendChild(doc.createTextNode(timestamp_hr_text))
             timestamp_root.appendChild(timestamp_hr)
             timestamp_root.appendChild(timestamp_hr)
 
 

+ 1 - 1
code/ID2TLib/PcapFile.py

@@ -21,7 +21,7 @@ class PcapFile(object):
         :param attack_pcap_path: The path to the PCAP file to merge with the PCAP at pcap_file_path
         :param attack_pcap_path: The path to the PCAP file to merge with the PCAP at pcap_file_path
         :return: The file path of the resulting PCAP file
         :return: The file path of the resulting PCAP file
         """
         """
-        print("Merging base PCAP with attack PCAP...", end=" ")
+        print("Merging base pcap with attack pcap...", end=" ")
         sys.stdout.flush()  # force python to print text immediately
         sys.stdout.flush()  # force python to print text immediately
 
 
         pcap = pr.pcap_processor(self.pcap_file_path)
         pcap = pr.pcap_processor(self.pcap_file_path)

+ 5 - 0
code/ID2TLib/Statistics.py

@@ -213,6 +213,11 @@ class Statistics:
         """
         """
         return self.process_db_query("most_used(ipAddress)")
         return self.process_db_query("most_used(ipAddress)")
 
 
+    def get_ttl_distribution(self, ipAddress: str):
+        result = self.process_db_query('SELECT ttlValue, ttlCount from ip_ttl WHERE ipAddress="' + ipAddress + '"')
+        result_dict = {key: value for (key, value) in result}
+        return result_dict
+
     def get_random_ip_address(self, count: int = 1):
     def get_random_ip_address(self, count: int = 1):
         """
         """
         :param count: The number of IP addreses to return
         :param count: The number of IP addreses to return