47 Commits dea6ca2340 ... abb0c8af3f

Author SHA1 Message Date
  Roey Regev abb0c8af3f small enhancements 6 years ago
  Roey Regev ddb51b8a11 additional TODOs for missing documentation 6 years ago
  Roey Regev 2d75b83a49 added TODOs to function where documentation is missing and corrected some misspelling 6 years ago
  Roey Regev ed87d4723e Added documentation for the methods generate_attack_pcap and generate_attack_packets of all attacks 6 years ago
  Carlos Garcia 0626dff544 Merge branch 'temporal_efficiency_fix' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Jens Keim 84255cbc90 add MS17 efficiency test 6 years ago
  Jens Keim 92f398a6bd replace named queries in Portscan 6 years ago
  Jens Keim 6c4220c07d replace named queries in SQLiAttack 6 years ago
  Jens Keim aa3ca6a1cb replace named queries in SMBLoris 6 years ago
  Jens Keim dc13f7f992 replace named queries in M17 Scan 6 years ago
  Jens Keim f40847cd3f replace named queries in FTP Exploit 6 years ago
  Jens Keim 503e7a1100 replace named queries in EternalBlue 6 years ago
  Jens Keim 4a1bd34777 replace named queries in DDoS 6 years ago
  Jens Keim e89957dd8c replace named queries in Joomla 6 years ago
  Jens Keim d952413ed2 add named query mothods to statistics 6 years ago
  Stefan Schmidt 6c42bdd1db Accelerated get_ip_address_from_mac and get_mac_address by replacing named queries with SQL 6 years ago
  Jens Keim cb051ce5c1 update temp efficiency tests to inject 1.000 pkts 6 years ago
  Carlos Garcia ee04907762 Merge branch 'label_improvements' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Stefan Schmidt 89fb8934ae Added file information for input and output pcap to label file 6 years ago
  Stefan Schmidt a4f95d6907 Implemented saving and loading of seeds in label files 6 years ago
  Stefan Schmidt 06802ea711 Added get_seed function to AttackController 6 years ago
  Stefan Schmidt a00555a540 Store a "user_specified"-attribute in the label file for each parameter 6 years ago
  Stefan Schmidt 4e01d73d4e Store and load parameters in label files, simplified tag names 6 years ago
  Stefan Schmidt e237e6b6dc Refactored add_param_value to not always require a statistics database 6 years ago
  Stefan Schmidt 922299db21 Fixed boolean returned as integer by adding an additional cast 6 years ago
  Stefan Schmidt 5b15235a28 Changed root-tag of label file to lowercase 6 years ago
  Carlos Garcia 22e1d7219f Merge branch 'ddos_test_fix' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Stefan Schmidt 16ce9eba2e Fixed DDoS unittest hashes 6 years ago
  Carlos Garcia 51235cc2c4 Merge branch 'seed_int' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Stefan Schmidt d806904e53 Fixed type of rng_seed in the Controller class 6 years ago
  Carlos Garcia ed15b76fee Merge branch 'rng_seed_refactor' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Jens Keim 24887d1349 adjust rng seed 6 years ago
  Carlos Garcia 5d87f9b4c3 Merge branch 'efficiency_script_fix' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Carlos Garcia 1ca555363d Merge branch 'stats_summary' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Carlos Garcia 1d8e4f47a4 Merge branch 'stats_progresss_indication' of stefan.schmidt/ID2T-toolkit into master 6 years ago
  Stefan Schmidt 42e3688c5c Indicate progress every second when generating statistics database 6 years ago
  Jens Keim d52c6637dd fix potential compatibility issues 6 years ago
  Roey Regev dea6ca2340 small enhancements 6 years ago
  Roey Regev c1960f88d1 additional TODOs for missing documentation 6 years ago
  Roey Regev b87a83f83a added TODOs to function where documentation is missing and corrected some misspelling 6 years ago
  Roey Regev 4f61eba9cb Added documentation for the methods generate_attack_pcap and generate_attack_packets of all attacks 6 years ago
  Jonathan Speth 148dc54e40 added non-verbose cli argument, adjusted tests 6 years ago
  Jonathan Speth 2cf964e5fa added pdu stats to -s flag, slight beautifications 6 years ago
  Jonathan Speth d07672d77c split summary into post_injection and new_db, moved them to Statistics.py, added support for multiple attacks 6 years ago
  Jonathan Speth 355ebdd2fc moved summary back to after injection, added some stats, rephrased descriptions 6 years ago
  Jonathan Speth 55601c5ef1 moved summary to the before the injection, rephrased pdu to unknown pdu 6 years ago
  Jonathan Speth 601da89f5c added stats summary after injecting an attack 6 years ago

+ 4 - 4
build.sh

@@ -62,9 +62,9 @@ testpath="discover -s Test/"
 if [ -e "Test/test_\$1.py" ]; then
 if [ -e "Test/test_\$1.py" ]; then
     testpath="Test/test_\$1.py"
     testpath="Test/test_\$1.py"
 fi
 fi
-PYTHONWARNINGS="ignore" coverage run --source=. -m unittest \$testpath >/dev/null
-coverage html
-coverage report -m
+PYTHONWARNINGS="ignore" coverage3 run --source=. -m unittest \$testpath >/dev/null
+coverage3 html
+coverage3 report -m
 EOF
 EOF
 
 
 # Create the test script
 # Create the test script
@@ -79,7 +79,7 @@ SCRIPT_PATH=\${ID2T_DIR%/*}
 cd \$SCRIPT_PATH/code
 cd \$SCRIPT_PATH/code
 # Execute tests
 # Execute tests
 set -e
 set -e
-python -m unittest Test/efficiency_testing.py
+python3 -m unittest Test/efficiency_testing.py
 EOF
 EOF
 
 
 chmod +x ./code/CLI.py
 chmod +x ./code/CLI.py

+ 30 - 16
code/Attack/BaseAttack.py

@@ -9,6 +9,7 @@ import socket
 import sys
 import sys
 import tempfile
 import tempfile
 import time
 import time
+import collections
 
 
 # TODO: double check this import
 # TODO: double check this import
 # does it complain because libpcapreader is not a .py?
 # does it complain because libpcapreader is not a .py?
@@ -27,6 +28,8 @@ class BaseAttack(metaclass=abc.ABCMeta):
     Abstract base class for all attack classes. Provides basic functionalities, like parameter validation.
     Abstract base class for all attack classes. Provides basic functionalities, like parameter validation.
     """
     """
 
 
+    ValuePair = collections.namedtuple('ValuePair', ['value', 'user_specified'])
+
     def __init__(self, name, description, attack_type):
     def __init__(self, name, description, attack_type):
         """
         """
         To be called within the individual attack class to initialize the required parameters.
         To be called within the individual attack class to initialize the required parameters.
@@ -250,7 +253,7 @@ class BaseAttack(metaclass=abc.ABCMeta):
         try:
         try:
             import distutils.core
             import distutils.core
             import distutils.util
             import distutils.util
-            value = distutils.util.strtobool(value.lower())
+            value = bool(distutils.util.strtobool(value.lower()))
             is_bool = True
             is_bool = True
         except ValueError:
         except ValueError:
             is_bool = False
             is_bool = False
@@ -311,19 +314,16 @@ class BaseAttack(metaclass=abc.ABCMeta):
         """
         """
         return self.finish_time - self.start_time
         return self.finish_time - self.start_time
 
 
-    def add_param_value(self, param, value):
+    def add_param_value(self, param, value, user_specified: bool = True):
         """
         """
         Adds the pair param : value to the dictionary of attack parameters. Prints and error message and skips the
         Adds the pair param : value to the dictionary of attack parameters. Prints and error message and skips the
         parameter if the validation fails.
         parameter if the validation fails.
 
 
         :param param: Name of the parameter that we wish to modify.
         :param param: Name of the parameter that we wish to modify.
         :param value: The value we wish to assign to the specified parameter.
         :param value: The value we wish to assign to the specified parameter.
+        :param user_specified: Whether the value was specified by the user (or left default)
         :return: None.
         :return: None.
         """
         """
-        # This function call is valid only if there is a statistics object available.
-        if self.statistics is None:
-            print('Error: Attack parameter added without setting a statistics object first.')
-            exit(1)
 
 
         # by default no param is valid
         # by default no param is valid
         is_valid = False
         is_valid = False
@@ -344,14 +344,6 @@ class BaseAttack(metaclass=abc.ABCMeta):
         if param_type is None:
         if param_type is None:
             print('Parameter ' + str(param_name) + ' not available for chosen attack. Skipping parameter.')
             print('Parameter ' + str(param_name) + ' not available for chosen attack. Skipping parameter.')
 
 
-        # If value is query -> get value from database
-        elif self.statistics.is_query(value):
-            value = self.statistics.process_db_query(value, False)
-            if value is not None and value is not "":
-                is_valid = True
-            else:
-                print('Error in given parameter value: ' + str(value) + '. Data could not be retrieved.')
-
         # Validate parameter depending on parameter's type
         # Validate parameter depending on parameter's type
         elif param_type == atkParam.ParameterTypes.TYPE_IP_ADDRESS:
         elif param_type == atkParam.ParameterTypes.TYPE_IP_ADDRESS:
             is_valid, value = self._is_ip_address(value)
             is_valid, value = self._is_ip_address(value)
@@ -381,6 +373,11 @@ class BaseAttack(metaclass=abc.ABCMeta):
         elif param_type == atkParam.ParameterTypes.TYPE_BOOLEAN:
         elif param_type == atkParam.ParameterTypes.TYPE_BOOLEAN:
             is_valid, value = self._is_boolean(value)
             is_valid, value = self._is_boolean(value)
         elif param_type == atkParam.ParameterTypes.TYPE_PACKET_POSITION:
         elif param_type == atkParam.ParameterTypes.TYPE_PACKET_POSITION:
+            # This function call is valid only if there is a statistics object available.
+            if self.statistics is None:
+                print('Error: Statistics-dependent attack parameter added without setting a statistics object first.')
+                exit(1)
+
             ts = pr.pcap_processor(self.statistics.pcap_filepath, "False").get_timestamp_mu_sec(int(value))
             ts = pr.pcap_processor(self.statistics.pcap_filepath, "False").get_timestamp_mu_sec(int(value))
             if 0 <= int(value) <= self.statistics.get_packet_count() and ts >= 0:
             if 0 <= int(value) <= self.statistics.get_packet_count() and ts >= 0:
                 is_valid = True
                 is_valid = True
@@ -391,7 +388,7 @@ class BaseAttack(metaclass=abc.ABCMeta):
 
 
         # add value iff validation was successful
         # add value iff validation was successful
         if is_valid:
         if is_valid:
-            self.params[param_name] = value
+            self.params[param_name] = self.ValuePair(value, user_specified)
         else:
         else:
             print("ERROR: Parameter " + str(param) + " or parameter value " + str(value) +
             print("ERROR: Parameter " + str(param) + " or parameter value " + str(value) +
                   " not valid. Skipping parameter.")
                   " not valid. Skipping parameter.")
@@ -403,7 +400,24 @@ class BaseAttack(metaclass=abc.ABCMeta):
         :param param: The parameter whose value is wanted.
         :param param: The parameter whose value is wanted.
         :return: The parameter's value.
         :return: The parameter's value.
         """
         """
-        return self.params.get(param)
+        parameter = self.params.get(param)
+        if parameter is not None:
+            return parameter.value
+        else:
+            return None
+
+    def get_param_user_specified(self, param: atkParam.Parameter) -> bool:
+        """
+        Returns whether the parameter value was specified by the user for a given parameter.
+
+        :param param: The parameter whose user-specified flag is wanted.
+        :return: The parameter's user-specified flag.
+        """
+        parameter = self.params.get(param)
+        if parameter is not None:
+            return parameter.user_specified
+        else:
+            return False
 
 
     def check_parameters(self):
     def check_parameters(self):
         """
         """

+ 4 - 4
code/Attack/DDoSAttack.py

@@ -55,7 +55,7 @@ class DDoSAttack(BaseAttack.BaseAttack):
         # attacker configuration
         # attacker configuration
         num_attackers = rnd.randint(1, 16)
         num_attackers = rnd.randint(1, 16)
         # The most used IP class in background traffic
         # The most used IP class in background traffic
-        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ipClass)"))
+        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
 
 
         self.add_param_value(atkParam.Parameter.IP_SOURCE,
         self.add_param_value(atkParam.Parameter.IP_SOURCE,
                              self.generate_random_ipv4_address(most_used_ip_class, num_attackers))
                              self.generate_random_ipv4_address(most_used_ip_class, num_attackers))
@@ -85,7 +85,7 @@ class DDoSAttack(BaseAttack.BaseAttack):
         if (num_attackers is not None) and (num_attackers is not 0):
         if (num_attackers is not None) and (num_attackers is not 0):
             # user supplied atkParam.Parameter.NUMBER_ATTACKERS
             # user supplied atkParam.Parameter.NUMBER_ATTACKERS
             # The most used IP class in background traffic
             # The most used IP class in background traffic
-            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ipClass)"))
+            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
             # Create random attackers based on user input atkParam.Parameter.NUMBER_ATTACKERS
             # Create random attackers based on user input atkParam.Parameter.NUMBER_ATTACKERS
             ip_source_list = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
             ip_source_list = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
             mac_source_list = self.generate_random_mac_address(num_attackers)
             mac_source_list = self.generate_random_mac_address(num_attackers)
@@ -167,14 +167,14 @@ class DDoSAttack(BaseAttack.BaseAttack):
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
             destination_win_value = destination_win_prob_dict.random()
             destination_win_value = destination_win_prob_dict.random()
         else:
         else:
-            destination_win_value = self.statistics.process_db_query("most_used(winSize)")
+            destination_win_value = self.statistics.get_most_used_win_size()
 
 
         destination_win_value = Util.handle_most_used_outputs(destination_win_value)
         destination_win_value = Util.handle_most_used_outputs(destination_win_value)
 
 
         # MSS that was used by IP destination in background traffic
         # MSS that was used by IP destination in background traffic
         mss_dst = self.statistics.get_most_used_mss(ip_destination)
         mss_dst = self.statistics.get_most_used_mss(ip_destination)
         if mss_dst is None:
         if mss_dst is None:
-            mss_dst = self.statistics.process_db_query("most_used(mssValue)")
+            mss_dst = self.statistics.get_most_used_mss_value()
 
 
         mss_dst = Util.handle_most_used_outputs(mss_dst)
         mss_dst = Util.handle_most_used_outputs(mss_dst)
 
 

+ 3 - 3
code/Attack/EternalBlueExploit.py

@@ -108,7 +108,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_value = source_ttl_prob_dict.random()
             source_ttl_value = source_ttl_prob_dict.random()
         else:
         else:
-            source_ttl_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ttlValue)"))
+            source_ttl_value = Util.handle_most_used_outputs(self.statistics.get_most_used_ttl_value())
 
 
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         if len(destination_ttl_dist) > 0:
         if len(destination_ttl_dist) > 0:
@@ -116,7 +116,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
             destination_ttl_value = destination_ttl_prob_dict.random()
             destination_ttl_value = destination_ttl_prob_dict.random()
         else:
         else:
             destination_ttl_value = Util.handle_most_used_outputs(
             destination_ttl_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(ttlValue)"))
+                self.statistics.get_most_used_ttl_value())
 
 
         # Set Window Size based on Window Size distribution of IP address
         # Set Window Size based on Window Size distribution of IP address
         source_win_dist = self.statistics.get_win_distribution(ip_source)
         source_win_dist = self.statistics.get_win_distribution(ip_source)
@@ -134,7 +134,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
 
 
         # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
         # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
-        mss_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(mssValue)"))
+        mss_value = Util.handle_most_used_outputs(self.statistics.get_most_used_mss_value())
         if not mss_value:
         if not mss_value:
             mss_value = 1465
             mss_value = 1465
 
 

+ 2 - 2
code/Attack/FTPWinaXeExploit.py

@@ -50,7 +50,7 @@ class FTPWinaXeExploit(BaseAttack.BaseAttack):
         most_used_ip_address = self.statistics.get_most_used_ip_address()
         most_used_ip_address = self.statistics.get_most_used_ip_address()
 
 
         # The most used IP class in background traffic
         # The most used IP class in background traffic
-        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ipClass)"))
+        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
         attacker_ip = self.generate_random_ipv4_address(most_used_ip_class)
         attacker_ip = self.generate_random_ipv4_address(most_used_ip_class)
         self.add_param_value(atkParam.Parameter.IP_DESTINATION, attacker_ip)
         self.add_param_value(atkParam.Parameter.IP_DESTINATION, attacker_ip)
         self.add_param_value(atkParam.Parameter.MAC_DESTINATION, self.generate_random_mac_address())
         self.add_param_value(atkParam.Parameter.MAC_DESTINATION, self.generate_random_mac_address())
@@ -100,7 +100,7 @@ class FTPWinaXeExploit(BaseAttack.BaseAttack):
         # Create random victim if specified
         # Create random victim if specified
         if self.get_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE):
         if self.get_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE):
             # The most used IP class in background traffic
             # The most used IP class in background traffic
-            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ipClass)"))
+            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
             ip_victim = self.generate_random_ipv4_address(most_used_ip_class, 1)
             ip_victim = self.generate_random_ipv4_address(most_used_ip_class, 1)
             mac_victim = self.generate_random_mac_address()
             mac_victim = self.generate_random_mac_address()
 
 

+ 2 - 2
code/Attack/JoomlaRegPrivExploit.py

@@ -110,7 +110,7 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_value = source_ttl_prob_dict.random()
             source_ttl_value = source_ttl_prob_dict.random()
         else:
         else:
-            source_ttl_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ttlValue)"))
+            source_ttl_value = Util.handle_most_used_outputs(self.statistics.get_most_used_ttl_value())
 
 
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         if len(destination_ttl_dist) > 0:
         if len(destination_ttl_dist) > 0:
@@ -118,7 +118,7 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
             destination_ttl_value = destination_ttl_prob_dict.random()
             destination_ttl_value = destination_ttl_prob_dict.random()
         else:
         else:
             destination_ttl_value = Util.handle_most_used_outputs(
             destination_ttl_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(ttlValue)"))
+                self.statistics.get_most_used_ttl_value())
 
 
         # Inject Joomla_registration_privesc
         # Inject Joomla_registration_privesc
         # Read joomla_registration_privesc pcap file
         # Read joomla_registration_privesc pcap file

+ 3 - 3
code/Attack/MS17ScanAttack.py

@@ -106,7 +106,7 @@ class MS17ScanAttack(BaseAttack.BaseAttack):
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_value = source_ttl_prob_dict.random()
             source_ttl_value = source_ttl_prob_dict.random()
         else:
         else:
-            source_ttl_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ttlValue)"))
+            source_ttl_value = Util.handle_most_used_outputs(self.statistics.get_most_used_ttl_value())
 
 
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         if len(destination_ttl_dist) > 0:
         if len(destination_ttl_dist) > 0:
@@ -114,7 +114,7 @@ class MS17ScanAttack(BaseAttack.BaseAttack):
             destination_ttl_value = destination_ttl_prob_dict.random()
             destination_ttl_value = destination_ttl_prob_dict.random()
         else:
         else:
             destination_ttl_value = Util.handle_most_used_outputs(
             destination_ttl_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(ttlValue)"))
+                self.statistics.get_most_used_ttl_value())
 
 
         # Set Window Size based on Window Size distribution of IP address
         # Set Window Size based on Window Size distribution of IP address
         source_win_dist = self.statistics.get_win_distribution(ip_source)
         source_win_dist = self.statistics.get_win_distribution(ip_source)
@@ -132,7 +132,7 @@ class MS17ScanAttack(BaseAttack.BaseAttack):
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
 
 
         # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
         # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
-        mss_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(mssValue)"))
+        mss_value = Util.handle_most_used_outputs(self.statistics.get_most_used_mss_value())
         if not mss_value:
         if not mss_value:
             mss_value = 1465
             mss_value = 1465
 
 

+ 6 - 9
code/Attack/PortscanAttack.py

@@ -142,14 +142,13 @@ class PortscanAttack(BaseAttack.BaseAttack):
             source_mss_prob_dict = lea.Lea.fromValFreqsDict(source_mss_dist)
             source_mss_prob_dict = lea.Lea.fromValFreqsDict(source_mss_dist)
             source_mss_value = source_mss_prob_dict.random()
             source_mss_value = source_mss_prob_dict.random()
         else:
         else:
-            source_mss_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(mssValue)"))
+            source_mss_value = Util.handle_most_used_outputs(self.statistics.get_most_used_mss_value())
         destination_mss_dist = self.statistics.get_mss_distribution(ip_destination)
         destination_mss_dist = self.statistics.get_mss_distribution(ip_destination)
         if len(destination_mss_dist) > 0:
         if len(destination_mss_dist) > 0:
             destination_mss_prob_dict = lea.Lea.fromValFreqsDict(destination_mss_dist)
             destination_mss_prob_dict = lea.Lea.fromValFreqsDict(destination_mss_dist)
             destination_mss_value = destination_mss_prob_dict.random()
             destination_mss_value = destination_mss_prob_dict.random()
         else:
         else:
-            destination_mss_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(mssValue)"))
+            destination_mss_value = Util.handle_most_used_outputs(self.statistics.get_most_used_mss_value())
 
 
         # Set TTL based on TTL distribution of IP address
         # Set TTL based on TTL distribution of IP address
         source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
         source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
@@ -157,14 +156,13 @@ class PortscanAttack(BaseAttack.BaseAttack):
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_value = source_ttl_prob_dict.random()
             source_ttl_value = source_ttl_prob_dict.random()
         else:
         else:
-            source_ttl_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ttlValue)"))
+            source_ttl_value = Util.handle_most_used_outputs(self.statistics.get_most_used_ttl_value())
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         if len(destination_ttl_dist) > 0:
         if len(destination_ttl_dist) > 0:
             destination_ttl_prob_dict = lea.Lea.fromValFreqsDict(destination_ttl_dist)
             destination_ttl_prob_dict = lea.Lea.fromValFreqsDict(destination_ttl_dist)
             destination_ttl_value = destination_ttl_prob_dict.random()
             destination_ttl_value = destination_ttl_prob_dict.random()
         else:
         else:
-            destination_ttl_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(ttlValue)"))
+            destination_ttl_value = Util.handle_most_used_outputs(self.statistics.get_most_used_ttl_value())
 
 
         # Set Window Size based on Window Size distribution of IP address
         # Set Window Size based on Window Size distribution of IP address
         source_win_dist = self.statistics.get_win_distribution(ip_source)
         source_win_dist = self.statistics.get_win_distribution(ip_source)
@@ -172,14 +170,13 @@ class PortscanAttack(BaseAttack.BaseAttack):
             source_win_prob_dict = lea.Lea.fromValFreqsDict(source_win_dist)
             source_win_prob_dict = lea.Lea.fromValFreqsDict(source_win_dist)
             source_win_value = source_win_prob_dict.random()
             source_win_value = source_win_prob_dict.random()
         else:
         else:
-            source_win_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(winSize)"))
+            source_win_value = Util.handle_most_used_outputs(self.statistics.get_most_used_win_size())
         destination_win_dist = self.statistics.get_win_distribution(ip_destination)
         destination_win_dist = self.statistics.get_win_distribution(ip_destination)
         if len(destination_win_dist) > 0:
         if len(destination_win_dist) > 0:
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
             destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
             destination_win_value = destination_win_prob_dict.random()
             destination_win_value = destination_win_prob_dict.random()
         else:
         else:
-            destination_win_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(winSize)"))
+            destination_win_value = Util.handle_most_used_outputs(self.statistics.get_most_used_win_size())
 
 
         min_delay, max_delay = self.get_reply_delay(ip_destination)
         min_delay, max_delay = self.get_reply_delay(ip_destination)
 
 

+ 2 - 2
code/Attack/SMBLorisAttack.py

@@ -48,7 +48,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
         most_used_ip_address = self.statistics.get_most_used_ip_address()
         most_used_ip_address = self.statistics.get_most_used_ip_address()
 
 
         # The most used IP class in background traffic
         # The most used IP class in background traffic
-        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ipClass)"))
+        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
         num_attackers = rnd.randint(1, 16)
         num_attackers = rnd.randint(1, 16)
         source_ip = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
         source_ip = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
 
 
@@ -92,7 +92,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
         # user supplied atkParam.Parameter.NUMBER_ATTACKERS
         # user supplied atkParam.Parameter.NUMBER_ATTACKERS
         if (num_attackers is not None) and (num_attackers is not 0):
         if (num_attackers is not None) and (num_attackers is not 0):
             # The most used IP class in background traffic
             # The most used IP class in background traffic
-            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ipClass)"))
+            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
             # Create random attackers based on user input atkParam.Parameter.NUMBER_ATTACKERS
             # Create random attackers based on user input atkParam.Parameter.NUMBER_ATTACKERS
             ip_source = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
             ip_source = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
             mac_source = self.generate_random_mac_address(num_attackers)
             mac_source = self.generate_random_mac_address(num_attackers)

+ 2 - 2
code/Attack/SQLiAttack.py

@@ -114,7 +114,7 @@ class SQLiAttack(BaseAttack.BaseAttack):
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
             source_ttl_value = source_ttl_prob_dict.random()
             source_ttl_value = source_ttl_prob_dict.random()
         else:
         else:
-            source_ttl_value = Util.handle_most_used_outputs(self.statistics.process_db_query("most_used(ttlValue)"))
+            source_ttl_value = Util.handle_most_used_outputs(self.statistics.get_most_used_ttl_value())
 
 
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
         if len(destination_ttl_dist) > 0:
         if len(destination_ttl_dist) > 0:
@@ -122,7 +122,7 @@ class SQLiAttack(BaseAttack.BaseAttack):
             destination_ttl_value = destination_ttl_prob_dict.random()
             destination_ttl_value = destination_ttl_prob_dict.random()
         else:
         else:
             destination_ttl_value = Util.handle_most_used_outputs(
             destination_ttl_value = Util.handle_most_used_outputs(
-                self.statistics.process_db_query("most_used(ttlValue)"))
+                self.statistics.get_most_used_ttl_value())
 
 
         # Inject SQLi Attack
         # Inject SQLi Attack
         # Read SQLi Attack pcap file
         # Read SQLi Attack pcap file

+ 7 - 6
code/CLI.py

@@ -66,9 +66,10 @@ class CLI(object):
                             help='perform extra tests on the input pcap file, including calculating IP entropy'
                             help='perform extra tests on the input pcap file, including calculating IP entropy'
                                  'in interval-wise, TCP checksum, and checking payload availability.',
                                  'in interval-wise, TCP checksum, and checking payload availability.',
                             action='store_true')
                             action='store_true')
-        parser.add_argument('-S', '--randomSeed', action='append', help='sets random seed for testing or benchmarking',
+        parser.add_argument('-S', '--rngSeed', action='append', help='sets rng seed for testing or benchmarking',
                             nargs='+', default=[])
                             nargs='+', default=[])
         parser.add_argument('-T', '--time', help='measures packet generation time', action='store_true', default=False)
         parser.add_argument('-T', '--time', help='measures packet generation time', action='store_true', default=False)
+        parser.add_argument('-V', '--non-verbose', help='reduces terminal clutter', action='store_true', default=False)
 
 
         # Attack arguments
         # Attack arguments
         parser.add_argument('-a', '--attack', metavar="ATTACK", action='append',
         parser.add_argument('-a', '--attack', metavar="ATTACK", action='append',
@@ -139,7 +140,7 @@ class CLI(object):
         Evaluates given queries.
         Evaluates given queries.
         """
         """
         # Create Core Controller
         # Create Core Controller
-        controller = Controller(self.args.input, self.args.extraTests)
+        controller = Controller(self.args.input, self.args.extraTests, self.args.non_verbose)
 
 
         # Load PCAP statistics
         # Load PCAP statistics
         controller.load_pcap_statistics(self.args.export, self.args.recalculate, self.args.statistics)
         controller.load_pcap_statistics(self.args.export, self.args.recalculate, self.args.statistics)
@@ -151,14 +152,14 @@ class CLI(object):
                 do_entropy = True
                 do_entropy = True
             controller.create_statistics_plot(self.args.plot, do_entropy)
             controller.create_statistics_plot(self.args.plot, do_entropy)
 
 
-        # Check random seed
-        if not isinstance(self.args.randomSeed, list):
-            self.args.randomSeed = [self.args.randomSeed]
+        # Check rng seed
+        if not isinstance(self.args.rngSeed, list):
+            self.args.rngSeed = [self.args.rngSeed]
 
 
         # Process attack(s) with given attack params
         # Process attack(s) with given attack params
         if self.args.attack is not None:
         if self.args.attack is not None:
             # If attack is present, load attack with params
             # If attack is present, load attack with params
-            controller.process_attacks(self.args.attack, self.args.randomSeed, self.args.time)
+            controller.process_attacks(self.args.attack, self.args.rngSeed, self.args.time)
 
 
         # Parameter -q without arguments was given -> go into query loop
         # Parameter -q without arguments was given -> go into query loop
         if self.args.query == [None]:
         if self.args.query == [None]:

+ 19 - 5
code/Core/AttackController.py

@@ -2,6 +2,7 @@ import importlib
 import sys
 import sys
 import difflib
 import difflib
 import pkgutil
 import pkgutil
+import typing
 
 
 import Attack.AttackParameters as atkParam
 import Attack.AttackParameters as atkParam
 import Core.LabelManager as LabelManager
 import Core.LabelManager as LabelManager
@@ -29,14 +30,21 @@ class AttackController:
         self.seed = None
         self.seed = None
         self.total_packets = 0
         self.total_packets = 0
 
 
-    def set_seed(self, seed: int):
+    def set_seed(self, seed: int) -> None:
         """
         """
-        Sets global seed.
+        Sets rng seed.
 
 
-        :param seed: random seed
+        :param seed: rng seed
         """
         """
         self.seed = seed
         self.seed = seed
 
 
+    def get_seed(self) -> typing.Union[int, None]:
+        """
+        Gets rng seed.
+        :return: The current rng seed
+        """
+        return self.seed
+
     @staticmethod
     @staticmethod
     def choose_attack(input_name):
     def choose_attack(input_name):
         """"
         """"
@@ -108,7 +116,13 @@ class AttackController:
         self.current_attack.set_statistics(self.statistics)
         self.current_attack.set_statistics(self.statistics)
         if seed is not None:
         if seed is not None:
             self.current_attack.set_seed(seed=seed)
             self.current_attack.set_seed(seed=seed)
+
         self.current_attack.init_params()
         self.current_attack.init_params()
+
+        # Unset the user-specified-flag for all parameters set in init_params
+        for k, v in self.current_attack.params.items():
+            self.current_attack.params[k] = self.current_attack.ValuePair(v.value, False)
+
         # Record the attack
         # Record the attack
         self.added_attacks.append(self.current_attack)
         self.added_attacks.append(self.current_attack)
 
 
@@ -169,8 +183,8 @@ class AttackController:
         print(".)")
         print(".)")
 
 
         # Store label into LabelManager
         # Store label into LabelManager
-        label = Label.Label(attack, self.get_attack_start_utime(),
-                            self.get_attack_end_utime(), attack_note)
+        label = Label.Label(attack, self.get_attack_start_utime(), self.get_attack_end_utime(),
+                            self.seed, self.current_attack.params, attack_note)
         self.label_mgr.add_labels(label)
         self.label_mgr.add_labels(label)
 
 
         return temp_attack_pcap_path, duration
         return temp_attack_pcap_path, duration

+ 18 - 3
code/Core/Controller.py

@@ -11,7 +11,7 @@ import ID2TLib.Utility as Util
 
 
 
 
 class Controller:
 class Controller:
-    def __init__(self, pcap_file_path: str, do_extra_tests: bool):
+    def __init__(self, pcap_file_path: str, do_extra_tests: bool, non_verbose: bool):
         """
         """
         Creates a new Controller, acting as a central coordinator for the whole application.
         Creates a new Controller, acting as a central coordinator for the whole application.
 
 
@@ -22,8 +22,10 @@ class Controller:
         self.pcap_dest_path = ''
         self.pcap_dest_path = ''
         self.written_pcaps = []
         self.written_pcaps = []
         self.do_extra_tests = do_extra_tests
         self.do_extra_tests = do_extra_tests
+        self.non_verbose = non_verbose
         self.seed = None
         self.seed = None
         self.durations = []
         self.durations = []
+        self.added_packets = 0
 
 
         # Initialize class instances
         # Initialize class instances
         print("Input file: %s" % self.pcap_src_path)
         print("Input file: %s" % self.pcap_src_path)
@@ -42,9 +44,11 @@ class Controller:
         :param flag_write_file: Writes the statistics to a file.
         :param flag_write_file: Writes the statistics to a file.
         :param flag_recalculate_stats: Forces the recalculation of statistics.
         :param flag_recalculate_stats: Forces the recalculation of statistics.
         :param flag_print_statistics: Prints the statistics on the terminal.
         :param flag_print_statistics: Prints the statistics on the terminal.
+        :param flag_non_verbose: Reduces terminal clutter.
         :return: None
         :return: None
         """
         """
-        self.statistics.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
+        self.statistics.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics,
+                                             self.non_verbose)
 
 
     def process_attacks(self, attacks_config: list, seeds=None, time=False):
     def process_attacks(self, attacks_config: list, seeds=None, time=False):
         """
         """
@@ -58,13 +62,20 @@ class Controller:
         :param seeds: A list of random seeds for the given attacks.
         :param seeds: A list of random seeds for the given attacks.
         :param time: Measure time for packet generation.
         :param time: Measure time for packet generation.
         """
         """
+
         # load attacks sequentially
         # load attacks sequentially
         i = 0
         i = 0
         for attack in attacks_config:
         for attack in attacks_config:
             if seeds is not None and len(seeds) > i:
             if seeds is not None and len(seeds) > i:
-                self.attack_controller.set_seed(seed=seeds[i][0])
+                rng_seed = seeds[i][0]
+            else:
+                rng_seed = int.from_bytes(os.urandom(16), sys.byteorder)
+            self.attack_controller.set_seed(seed=rng_seed)
             temp_attack_pcap, duration = self.attack_controller.process_attack(attack[0], attack[1:], time)
             temp_attack_pcap, duration = self.attack_controller.process_attack(attack[0], attack[1:], time)
             self.durations.append(duration)
             self.durations.append(duration)
+            self.added_packets += self.attack_controller.total_packets
+            if not self.non_verbose:
+                self.statistics.stats_summary_post_attack(self.added_packets)
             self.written_pcaps.append(temp_attack_pcap)
             self.written_pcaps.append(temp_attack_pcap)
             i += 1
             i += 1
 
 
@@ -110,6 +121,10 @@ class Controller:
         # print status message
         # print status message
         print('\nOutput files created: \n', self.pcap_dest_path, '\n', self.label_manager.label_file_path)
         print('\nOutput files created: \n', self.pcap_dest_path, '\n', self.label_manager.label_file_path)
 
 
+        # print summary statistics
+        if not self.non_verbose:
+            self.statistics.stats_summary_post_attack(self.added_packets)
+
     def process_db_queries(self, query, print_results=False):
     def process_db_queries(self, query, print_results=False):
         """
         """
         Processes a statistics database query. This can be a standard SQL query or a named query.
         Processes a statistics database query. This can be a standard SQL query or a named query.

+ 85 - 5
code/Core/LabelManager.py

@@ -1,23 +1,32 @@
+import importlib
 import datetime as dt
 import datetime as dt
 import os.path
 import os.path
 import xml.dom.minidom as minidom
 import xml.dom.minidom as minidom
 
 
 import ID2TLib.Label as Label
 import ID2TLib.Label as Label
+import ID2TLib.TestLibrary as Lib
 
 
 
 
 class LabelManager:
 class LabelManager:
-    TAG_ROOT = 'LABELS'
+    TAG_ROOT = 'labels'
+    TAG_INPUT = 'input'
+    TAG_OUTPUT = 'output'
+    TAG_FILE_NAME = 'filename'
+    TAG_FILE_HASH = 'sha256'
     TAG_ATTACK = 'attack'
     TAG_ATTACK = 'attack'
-    TAG_ATTACK_NAME = 'attack_name'
-    TAG_ATTACK_NOTE = 'attack_note'
+    TAG_ATTACK_NAME = 'name'
+    TAG_ATTACK_NOTE = 'note'
+    TAG_ATTACK_SEED = 'seed'
     TAG_TIMESTAMP_START = 'timestamp_start'
     TAG_TIMESTAMP_START = 'timestamp_start'
     TAG_TIMESTAMP_END = 'timestamp_end'
     TAG_TIMESTAMP_END = 'timestamp_end'
     TAG_TIMESTAMP = 'timestamp'
     TAG_TIMESTAMP = 'timestamp'
     TAG_TIMESTAMP_HR = 'timestamp_hr'
     TAG_TIMESTAMP_HR = 'timestamp_hr'
+    TAG_PARAMETERS = 'parameters'
     ATTR_VERSION = 'version_parser'
     ATTR_VERSION = 'version_parser'
+    ATTR_PARAM_USERSPECIFIED = 'user_specified'
 
 
     # update this attribute if XML scheme was modified
     # update this attribute if XML scheme was modified
-    ATTR_VERSION_VALUE = '0.2'
+    ATTR_VERSION_VALUE = '0.3'
 
 
     def __init__(self, filepath_pcap=None):
     def __init__(self, filepath_pcap=None):
         """
         """
@@ -26,6 +35,7 @@ class LabelManager:
         :param filepath_pcap: The path to the PCAP file associated to the labels.
         :param filepath_pcap: The path to the PCAP file associated to the labels.
         """
         """
         self.labels = list()
         self.labels = list()
+        self.filepath_input_pcap = filepath_pcap
 
 
         if filepath_pcap is not None:
         if filepath_pcap is not None:
             self.label_file_path = os.path.splitext(filepath_pcap)[0] + '_labels.xml'
             self.label_file_path = os.path.splitext(filepath_pcap)[0] + '_labels.xml'
@@ -58,6 +68,25 @@ class LabelManager:
         :param filepath: The path where the label file should be written to.
         :param filepath: The path where the label file should be written to.
         """
         """
 
 
+        def get_subtree_fileinfo(xml_tag_root, filename) -> minidom.Element:
+            """
+            Creates the subtree for pcap file information (filename and hash).
+
+            :return: The root node of the XML subtree
+            """
+
+            input_root = doc.createElement(xml_tag_root)
+
+            file = doc.createElement(self.TAG_FILE_NAME)
+            file.appendChild(doc.createTextNode(os.path.split(filename)[-1]))
+            input_root.appendChild(file)
+
+            hash_node = doc.createElement(self.TAG_FILE_HASH)
+            hash_node.appendChild(doc.createTextNode(Lib.get_sha256(filename)))
+            input_root.appendChild(hash_node)
+
+            return input_root
+
         def get_subtree_timestamp(xml_tag_root, timestamp_entry):
         def get_subtree_timestamp(xml_tag_root, timestamp_entry):
             """
             """
             Creates the subtree for a given timestamp, consisting of the unix time format (seconds) and a human-readable
             Creates the subtree for a given timestamp, consisting of the unix time format (seconds) and a human-readable
@@ -82,6 +111,23 @@ class LabelManager:
 
 
             return timestamp_root
             return timestamp_root
 
 
+        def get_subtree_parameters(parameters):
+            """
+            Creates a subtree containing all parameters used to construct the attack
+
+            :param parameters: The list of parameters used to run the attack
+            :return: The root node of the XML subtree
+            """
+            parameters_root = doc.createElement(self.TAG_PARAMETERS)
+
+            for param_key, param_value in parameters.items():
+                param = doc.createElement(param_key.value)
+                param.appendChild(doc.createTextNode(str(param_value.value)))
+                param.setAttribute(self.ATTR_PARAM_USERSPECIFIED, str(param_value.user_specified))
+                parameters_root.appendChild(param)
+
+            return parameters_root
+
         if filepath is not None:
         if filepath is not None:
             self.label_file_path = os.path.splitext(filepath)[0] + '_labels.xml'
             self.label_file_path = os.path.splitext(filepath)[0] + '_labels.xml'
 
 
@@ -89,6 +135,9 @@ class LabelManager:
         doc = minidom.Document()
         doc = minidom.Document()
         node = doc.createElement(self.TAG_ROOT)
         node = doc.createElement(self.TAG_ROOT)
         node.setAttribute(self.ATTR_VERSION, self.ATTR_VERSION_VALUE)
         node.setAttribute(self.ATTR_VERSION, self.ATTR_VERSION_VALUE)
+        node.appendChild(get_subtree_fileinfo(self.TAG_INPUT, self.filepath_input_pcap))
+        node.appendChild(get_subtree_fileinfo(self.TAG_OUTPUT, filepath))
+
         for label in self.labels:
         for label in self.labels:
             xml_tree = doc.createElement(self.TAG_ATTACK)
             xml_tree = doc.createElement(self.TAG_ATTACK)
 
 
@@ -99,6 +148,9 @@ class LabelManager:
             attack_note = doc.createElement(self.TAG_ATTACK_NOTE)
             attack_note = doc.createElement(self.TAG_ATTACK_NOTE)
             attack_note.appendChild(doc.createTextNode(str(label.attack_note)))
             attack_note.appendChild(doc.createTextNode(str(label.attack_note)))
             xml_tree.appendChild(attack_note)
             xml_tree.appendChild(attack_note)
+            attack_seed = doc.createElement(self.TAG_ATTACK_SEED)
+            attack_seed.appendChild(doc.createTextNode(str(label.seed)))
+            xml_tree.appendChild(attack_seed)
 
 
             # add timestamp_start to XML tree
             # add timestamp_start to XML tree
             xml_tree.appendChild(get_subtree_timestamp(self.TAG_TIMESTAMP_START, label.timestamp_start))
             xml_tree.appendChild(get_subtree_timestamp(self.TAG_TIMESTAMP_START, label.timestamp_start))
@@ -106,6 +158,9 @@ class LabelManager:
             # add timestamp_end to XML tree
             # add timestamp_end to XML tree
             xml_tree.appendChild(get_subtree_timestamp(self.TAG_TIMESTAMP_END, label.timestamp_end))
             xml_tree.appendChild(get_subtree_timestamp(self.TAG_TIMESTAMP_END, label.timestamp_end))
 
 
+            # add parameters to XML tree
+            xml_tree.appendChild(get_subtree_parameters(label.parameters))
+
             node.appendChild(xml_tree)
             node.appendChild(xml_tree)
 
 
         doc.appendChild(node)
         doc.appendChild(node)
@@ -155,6 +210,11 @@ class LabelManager:
                     "The file " + self.label_file_path + " was created by another version of ID2TLib.LabelManager. "
                     "The file " + self.label_file_path + " was created by another version of ID2TLib.LabelManager. "
                                                          "Ignoring label file.")
                                                          "Ignoring label file.")
 
 
+        self.input_filename = get_value_from_node(dom, self.TAG_INPUT, 1, 0)
+        self.input_hash = get_value_from_node(dom, self.TAG_INPUT, 3, 0)
+        self.output_filename = get_value_from_node(dom, self.TAG_OUTPUT, 1, 0)
+        self.output_hash = get_value_from_node(dom, self.TAG_OUTPUT, 3, 0)
+
         # Parse attacks from XML file
         # Parse attacks from XML file
         attacks = dom.getElementsByTagName(self.TAG_ATTACK)
         attacks = dom.getElementsByTagName(self.TAG_ATTACK)
         count_labels = 0
         count_labels = 0
@@ -163,7 +223,27 @@ class LabelManager:
             attack_note = get_value_from_node(a, self.TAG_ATTACK_NOTE, 0)
             attack_note = get_value_from_node(a, self.TAG_ATTACK_NOTE, 0)
             timestamp_start = get_value_from_node(a, self.TAG_TIMESTAMP_START, 1, 0)
             timestamp_start = get_value_from_node(a, self.TAG_TIMESTAMP_START, 1, 0)
             timestamp_end = get_value_from_node(a, self.TAG_TIMESTAMP_END, 1, 0)
             timestamp_end = get_value_from_node(a, self.TAG_TIMESTAMP_END, 1, 0)
-            label = Label.Label(attack_name, float(timestamp_start), float(timestamp_end), attack_note)
+            attack_seed = get_value_from_node(a, self.TAG_ATTACK_SEED, 0)
+
+            # Instantiate this attack to create a parameter list with the correct types
+            attack_module = importlib.import_module("Attack." + attack_name)
+            attack_class = getattr(attack_module, attack_name)
+            attack = attack_class()
+
+            # Loop through all parameters listed in the XML file
+            param = a.getElementsByTagName(self.TAG_PARAMETERS)[0]
+            for param in param.childNodes:
+                # Skip empty text nodes returned by minidom
+                if not isinstance(param, minidom.Text):
+                    import distutils.util
+                    param_name = param.tagName
+                    param_value = param.childNodes[0].nodeValue
+                    param_userspecified = bool(distutils.util.strtobool(param.getAttribute(self.ATTR_PARAM_USERSPECIFIED)))
+                    attack.add_param_value(param_name, param_value, param_userspecified)
+
+            # Create the label from the data read
+            label = Label.Label(attack_name, float(timestamp_start), float(timestamp_end), attack_seed, attack.params,
+                                attack_note)
             self.labels.append(label)
             self.labels.append(label)
             count_labels += 1
             count_labels += 1
 
 

+ 107 - 9
code/Core/Statistics.py

@@ -39,7 +39,8 @@ class Statistics:
         # Class instances
         # Class instances
         self.stats_db = statsDB.StatsDatabase(self.path_db)
         self.stats_db = statsDB.StatsDatabase(self.path_db)
 
 
-    def load_pcap_statistics(self, flag_write_file: bool, flag_recalculate_stats: bool, flag_print_statistics: bool):
+    def load_pcap_statistics(self, flag_write_file: bool, flag_recalculate_stats: bool, flag_print_statistics: bool,
+                             flag_non_verbose: bool):
         """
         """
         Loads the PCAP statistics for the file specified by pcap_filepath. If the database is not existing yet, the
         Loads the PCAP statistics for the file specified by pcap_filepath. If the database is not existing yet, the
         statistics are calculated by the PCAP file processor and saved into the newly created database. Otherwise the
         statistics are calculated by the PCAP file processor and saved into the newly created database. Otherwise the
@@ -49,6 +50,7 @@ class Statistics:
         or not (False)
         or not (False)
         :param flag_recalculate_stats: Indicates whether eventually existing statistics should be recalculated
         :param flag_recalculate_stats: Indicates whether eventually existing statistics should be recalculated
         :param flag_print_statistics: Indicates whether the gathered basic statistics should be printed to the terminal
         :param flag_print_statistics: Indicates whether the gathered basic statistics should be printed to the terminal
+        :param flag_non_verbose: Indicates whether certain prints should be made or not, to reduce terminal clutter
         """
         """
         # Load pcap and get loading time
         # Load pcap and get loading time
         time_start = time.clock()
         time_start = time.clock()
@@ -63,6 +65,10 @@ class Statistics:
             self.pcap_proc.collect_statistics()
             self.pcap_proc.collect_statistics()
             self.pcap_proc.write_to_database(self.path_db)
             self.pcap_proc.write_to_database(self.path_db)
             outstring_datasource = "by PCAP file processor."
             outstring_datasource = "by PCAP file processor."
+
+            # only print summary of new db if -s flag not set
+            if not flag_print_statistics and not flag_non_verbose:
+                self.stats_summary_new_db()
         else:
         else:
             outstring_datasource = "from statistics database."
             outstring_datasource = "from statistics database."
 
 
@@ -86,11 +92,22 @@ class Statistics:
 
 
         :return: a list of tuples, each consisting of (description, value, unit), where unit is optional.
         :return: a list of tuples, each consisting of (description, value, unit), where unit is optional.
         """
         """
-        return [("Pcap file", self.pcap_filepath),
-                ("Packets", self.get_packet_count(), "packets"),
-                ("Capture length", self.get_capture_duration(), "seconds"),
-                ("Capture start", self.get_pcap_timestamp_start()),
-                ("Capture end", self.get_pcap_timestamp_end())]
+
+        pdu_count = self.process_db_query("SELECT SUM(pktCount) FROM unrecognized_pdus")
+        pdu_share = pdu_count / self.get_packet_count() * 100
+        last_pdu_timestamp = self.process_db_query(
+            "SELECT MAX(timestampLastOccurrence) FROM unrecognized_pdus")
+
+        return [("Pcap file path", self.pcap_filepath),
+                ("Total packet count", self.get_packet_count(), "packets"),
+                ("Recognized packets", self.get_packet_count() - pdu_count, "packets"),
+                ("Unrecognized packets", pdu_count, "PDUs"),
+                ("% Recognized packets", 100 - pdu_share, "%"),
+                ("% Unrecognized packets", pdu_share, "%"),
+                ("Last unknown PDU", last_pdu_timestamp),
+                ("Capture duration", self.get_capture_duration(), "seconds"),
+                ("Capture start", "\t" + str(self.get_pcap_timestamp_start())),
+                ("Capture end", "\t" + str(self.get_pcap_timestamp_end()))]
 
 
     def get_general_file_statistics(self):
     def get_general_file_statistics(self):
         """
         """
@@ -560,7 +577,7 @@ class Statistics:
         :return: A randomly chosen IP address from the dataset or iff param count is greater than one, a list of
         :return: A randomly chosen IP address from the dataset or iff param count is greater than one, a list of
         randomly chosen IP addresses
         randomly chosen IP addresses
         """
         """
-        ip_address_list = self.process_db_query("all(ipAddress)")
+        ip_address_list = self.process_db_query("SELECT ipAddress from ip_statistics ORDER BY ipAddress ASC")
         if count == 1:
         if count == 1:
             return random.choice(ip_address_list)
             return random.choice(ip_address_list)
         else:
         else:
@@ -576,13 +593,45 @@ class Statistics:
         :param mac_address: the MAC address of which the IP shall be returned, if existing in DB
         :param mac_address: the MAC address of which the IP shall be returned, if existing in DB
         :return: the IP address used in the dataset by a given MAC address
         :return: the IP address used in the dataset by a given MAC address
         """
         """
-        return self.process_db_query('ipAddress(macAddress=' + mac_address + ")")
+        return self.process_db_query("SELECT DISTINCT ipAddress FROM ip_mac WHERE macAddress = '" + mac_address + "'")
 
 
     def get_mac_address(self, ip_address: str):
     def get_mac_address(self, ip_address: str):
         """
         """
         :return: The MAC address used in the dataset for the given IP address.
         :return: The MAC address used in the dataset for the given IP address.
         """
         """
-        return self.process_db_query('macAddress(ipAddress=' + ip_address + ")")
+        return self.process_db_query("SELECT DISTINCT macAddress from ip_mac WHERE ipAddress = '" + ip_address + "'")
+
+    def get_most_used_ttl_value(self):
+        """
+        :return: The most used TTL value.
+        """
+        return self.process_db_query("SELECT ttlValue FROM (SELECT ttlValue, SUM(ttlCount) as occ FROM ip_ttl GROUP BY "
+                                     "ttlValue) WHERE occ=(SELECT SUM(ttlCount) as occ FROM ip_ttl GROUP BY ttlValue "
+                                     "ORDER BY occ DESC LIMIT 1) ORDER BY ttlValue ASC")
+
+    def get_most_used_ip_class(self):
+        """
+        :return: The most used IP class.
+        """
+        return self.process_db_query("SELECT ipClass FROM (SELECT ipClass, COUNT(*) as occ from ip_statistics GROUP BY "
+                                     "ipClass ORDER BY occ DESC) WHERE occ=(SELECT COUNT(*) as occ from ip_statistics "
+                                     "GROUP BY ipClass ORDER BY occ DESC LIMIT 1) ORDER BY ipClass ASC")
+
+    def get_most_used_win_size(self):
+        """
+        :return: The most used window size.
+        """
+        return self.process_db_query("SELECT winSize FROM (SELECT winSize, SUM(winCount) as occ FROM tcp_win GROUP BY "
+                                     "winSize) WHERE occ=(SELECT SUM(winCount) as occ FROM tcp_win GROUP BY winSize "
+                                     "ORDER BY occ DESC LIMIT 1) ORDER BY winSize ASC")
+
+    def get_most_used_mss_value(self):
+        """
+        :return: The most used mss value.
+        """
+        return self.process_db_query("SELECT mssValue FROM (SELECT mssValue, SUM(mssCount) as occ FROM tcp_mss GROUP BY"
+                                     " mssValue) WHERE occ=(SELECT SUM(mssCount) as occ FROM tcp_mss GROUP BY mssValue "
+                                     "ORDER BY occ DESC LIMIT 1) ORDER BY mssValue ASC")
 
 
     def get_most_used_mss(self, ip_address: str):
     def get_most_used_mss(self, ip_address: str):
         """
         """
@@ -1152,3 +1201,52 @@ class Statistics:
         # ip_dst_out_path = plot_ip_dst('.' + format)
         # ip_dst_out_path = plot_ip_dst('.' + format)
 
 
         print("Saved plots in the input PCAP directory.")
         print("Saved plots in the input PCAP directory.")
+
+    def stats_summary_post_attack(self, added_packets):
+        """
+        Prints a summary of relevant statistics after an attack is injected
+
+        :param added_packets: sum of packets added by attacks, gets updated if more than one attack
+        :return: None
+        """
+
+        total_packet_count = self.get_packet_count() + added_packets
+        added_packets_share = added_packets / total_packet_count * 100
+        timespan = self.get_capture_duration()
+
+        summary = [("Total packet count", total_packet_count, "packets"),
+                   ("Added packet count", added_packets, "packets"),
+                   ("Share of added packets", added_packets_share, "%"),
+                   ("Capture duration", timespan, "seconds")]
+
+        print("\nPOST INJECTION STATISTICS SUMMARY  --------------------------")
+        self.write_list(summary, print, "")
+        print("------------------------------------------------------------")
+
+    def stats_summary_new_db(self):
+        """
+        Prints a summary of relevant statistics when a new db is created
+
+        :return: None
+        """
+
+        self.file_info = self.stats_db.get_file_info()
+        print("\nNew database has been generated, printing statistics summary... ")
+        total_packet_count = self.get_packet_count()
+        pdu_count = self.process_db_query("SELECT SUM(pktCount) FROM unrecognized_pdus")
+        pdu_share = pdu_count / total_packet_count * 100
+        last_pdu_timestamp = self.process_db_query(
+            "SELECT MAX(timestampLastOccurrence) FROM unrecognized_pdus")
+        timespan = self.get_capture_duration()
+
+        summary = [("Total packet count", total_packet_count, "packets"),
+                   ("Recognized packets", total_packet_count - pdu_count, "packets"),
+                   ("Unrecognized packets", pdu_count, "PDUs"),
+                   ("% Recognized packets", 100 - pdu_share, "%"),
+                   ("% Unrecognized packets", pdu_share, "%"),
+                   ("Last unknown PDU", last_pdu_timestamp),
+                   ("Capture duration", timespan, "seconds")]
+
+        print("\nPCAP FILE STATISTICS SUMMARY  ------------------------------")
+        self.write_list(summary, print, "")
+        print("------------------------------------------------------------")

+ 4 - 1
code/ID2TLib/Label.py

@@ -3,19 +3,22 @@ import functools
 
 
 @functools.total_ordering
 @functools.total_ordering
 class Label:
 class Label:
-    def __init__(self, attack_name, timestamp_start, timestamp_end, attack_note=""):
+    def __init__(self, attack_name, timestamp_start, timestamp_end, seed, parameters, attack_note=""):
         """
         """
         Creates a new attack label
         Creates a new attack label
 
 
         :param attack_name: The name of the associated attack
         :param attack_name: The name of the associated attack
         :param timestamp_start: The timestamp as unix time of the first attack packet
         :param timestamp_start: The timestamp as unix time of the first attack packet
         :param timestamp_end: The timestamp as unix time of the last attack packet
         :param timestamp_end: The timestamp as unix time of the last attack packet
+        :param parameters: The list of parameters used to run the attack
         :param attack_note: A note associated to the attack (optional)
         :param attack_note: A note associated to the attack (optional)
         """
         """
         self.attack_name = attack_name
         self.attack_name = attack_name
         self.timestamp_start = timestamp_start
         self.timestamp_start = timestamp_start
         self.timestamp_end = timestamp_end
         self.timestamp_end = timestamp_end
+        self.seed = seed
         self.attack_note = attack_note
         self.attack_note = attack_note
+        self.parameters = parameters
 
 
     def __eq__(self, other):
     def __eq__(self, other):
         return self.timestamp == other.timestamp
         return self.timestamp == other.timestamp

+ 3 - 3
code/Test/ID2TAttackTest.py

@@ -31,7 +31,7 @@ class ID2TAttackTest(unittest.TestCase):
         :param time: Measure time for packet generation.
         :param time: Measure time for packet generation.
         """
         """
 
 
-        controller = Ctrl.Controller(pcap_file_path=pcap, do_extra_tests=False)
+        controller = Ctrl.Controller(pcap_file_path=pcap, do_extra_tests=False, non_verbose=True)
         controller.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
         controller.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
 
 
         controller.process_attacks(attack_args, [[seed]], time)
         controller.process_attacks(attack_args, [[seed]], time)
@@ -69,7 +69,7 @@ class ID2TAttackTest(unittest.TestCase):
         :param test_sub_dir: create sub-directory for each test-function/case if True
         :param test_sub_dir: create sub-directory for each test-function/case if True
         """
         """
 
 
-        controller = Ctrl.Controller(pcap_file_path=pcap, do_extra_tests=False)
+        controller = Ctrl.Controller(pcap_file_path=pcap, do_extra_tests=False, non_verbose=True)
         controller.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
         controller.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
 
 
         if seed is None:
         if seed is None:
@@ -110,7 +110,7 @@ class ID2TAttackTest(unittest.TestCase):
         :param test_sub_dir: create sub-directory for each test-function/case if True
         :param test_sub_dir: create sub-directory for each test-function/case if True
         """
         """
 
 
-        controller = Ctrl.Controller(pcap_file_path=pcap, do_extra_tests=False)
+        controller = Ctrl.Controller(pcap_file_path=pcap, do_extra_tests=False, non_verbose=True)
         controller.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
         controller.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
         controller.process_attacks(attack_args, [[seed]])
         controller.process_attacks(attack_args, [[seed]])
 
 

+ 29 - 44
code/Test/efficiency_testing.py

@@ -5,65 +5,50 @@ import Test.ID2TAttackTest as Test
 
 
 
 
 class EfficiencyTests(Test.ID2TAttackTest):
 class EfficiencyTests(Test.ID2TAttackTest):
-    def test_SMBLoris_10_000(self):
-        self.temporal_efficiency_test([['SMBLorisAttack', 'attackers.count=30', 'packets.per-second=8.0']],
-                                      time_limit=15, factor=10000)
+    def test_SMBLoris(self):
+        self.temporal_efficiency_test([['SMBLorisAttack', 'attackers.count=4', 'packets.per-second=8.0']],
+                                      time_limit=1.5, factor=1000)
 
 
-    def test_SMBLoris_100_000(self):
-        self.temporal_efficiency_test([['SMBLorisAttack', 'attackers.count=30', 'packets.per-second=98']],
-                                      time_limit=150, factor=100000)
-
-    def test_SMBScan_10_000(self):
+    def test_SMBScan(self):
         self.temporal_efficiency_test([['SMBScanAttack', 'ip.src=192.168.178.1',
         self.temporal_efficiency_test([['SMBScanAttack', 'ip.src=192.168.178.1',
-                                        'ip.dst=192.168.178.10-192.168.197.145']], time_limit=15, factor=10000)
-
-    def test_SMBScan_100_000(self):
-        self.temporal_efficiency_test([['SMBScanAttack', 'ip.src=192.168.178.1', 'ip.dst=192.168.0.1-192.168.195.76']],
-                                      time_limit=150, factor=100000)
+                                        'ip.dst=192.168.178.10-192.168.179.253']], time_limit=1.5, factor=1000)
 
 
-    def test_SMBScan_hosting_10_000(self):
+    def test_SMBScan_hosting(self):
         self.temporal_efficiency_test([['SMBScanAttack', 'ip.src=192.168.178.1',
         self.temporal_efficiency_test([['SMBScanAttack', 'ip.src=192.168.178.1',
-                                        'ip.dst=192.168.178.10-192.168.181.241',
-                                        'hosting.ip=192.168.178.10-192.168.181.241']], time_limit=15, factor=10000)
-
-    def test_SMBScan_hosting_100_000(self):
-        self.temporal_efficiency_test([['SMBScanAttack', 'ip.src=192.168.178.1', 'ip.dst=192.168.178.10-192.168.217.25',
-                                        'hosting.ip=192.168.178.10-192.168.217.25']], time_limit=150, factor=100000)
+                                        'ip.dst=192.168.178.10-192.168.178.109',
+                                        'hosting.ip=192.168.178.10-192.168.178.109']], time_limit=1.5, factor=1000)
 
 
     @mock.patch('ID2TLib.Utility.get_rnd_bytes', side_effect=Lib.get_bytes)
     @mock.patch('ID2TLib.Utility.get_rnd_bytes', side_effect=Lib.get_bytes)
     @mock.patch('ID2TLib.Utility.get_rnd_x86_nop', side_effect=Lib.get_x86_nop)
     @mock.patch('ID2TLib.Utility.get_rnd_x86_nop', side_effect=Lib.get_x86_nop)
     def test_FTPExploit(self, mock_get_rnd_x86_nop, mock_get_rnd_bytes):
     def test_FTPExploit(self, mock_get_rnd_x86_nop, mock_get_rnd_bytes):
         self.temporal_efficiency_test([['FTPWinaXeExploit', 'ip.src=192.168.178.1', 'ip.dst=192.168.178.10']],
         self.temporal_efficiency_test([['FTPWinaXeExploit', 'ip.src=192.168.178.1', 'ip.dst=192.168.178.10']],
-                                      time_limit=15, factor=10000)
+                                      time_limit=1.5, factor=1000)
 
 
-    def test_PortscanAttack_open_10_000(self):
-        self.temporal_efficiency_test([['PortscanAttack', 'ip.src=192.168.178.1', 'port.open=80']], time_limit=15,
-                                      factor=10000)
+    def test_PortscanAttack_open(self):
+        self.temporal_efficiency_test([['PortscanAttack', 'ip.src=192.168.178.1', 'port.open=80']], time_limit=1.5,
+                                      factor=1000)
 
 
-    def test_PortscanAttack_close_10_000(self):
-        self.temporal_efficiency_test([['PortscanAttack', 'ip.src=192.168.178.1', 'port.open=20']], time_limit=15,
-                                      factor=10000)
+    def test_PortscanAttack_close(self):
+        self.temporal_efficiency_test([['PortscanAttack', 'ip.src=192.168.178.1', 'port.open=20']], time_limit=1.5,
+                                      factor=1000)
 
 
-    def test_SQLi_10_000(self):
-        # FIXME: sometimes it takes 15.34028493521018 instead of the normal 7.150923313737726 seconds
-        self.temporal_efficiency_test([['SQLiAttack', 'ip.dst=192.168.0.1']], time_limit=15, factor=10000)
+    def test_SQLi(self):
+        self.temporal_efficiency_test([['SQLiAttack', 'ip.dst=192.168.0.1']], time_limit=1.5, factor=1000)
 
 
-    def test_Joomla_10_000(self):
-        self.temporal_efficiency_test([['JoomlaRegPrivExploit', 'ip.src=192.168.178.1']], time_limit=15, factor=10000)
+    def test_Joomla(self):
+        self.temporal_efficiency_test([['JoomlaRegPrivExploit', 'ip.src=192.168.178.1']], time_limit=1.5, factor=1000)
 
 
-    def test_SalityBotnet_10_000(self):
-        self.temporal_efficiency_test([['SalityBotnet']], time_limit=15, factor=10000)
+    def test_SalityBotnet(self):
+        self.temporal_efficiency_test([['SalityBotnet']], time_limit=1.5, factor=1000)
 
 
     @mock.patch('Attack.BaseAttack.BaseAttack.write_attack_pcap', side_effect=Lib.write_attack_pcap)
     @mock.patch('Attack.BaseAttack.BaseAttack.write_attack_pcap', side_effect=Lib.write_attack_pcap)
-    def test_DDoS_10_000(self, mock_write_attack_pcap):
-        # TODO: update attack args, when DDoS gets refactored
-        self.temporal_efficiency_test([['DDoSAttack', 'attackers.count=100', 'packets.per-second=95',
-                                        'attack.duration=150']], time_limit=15, factor=10000)
+    def test_DDoS(self, mock_write_attack_pcap):
+        self.temporal_efficiency_test([['DDoSAttack', 'attackers.count=10', 'packets.per-second=95',
+                                        'attack.duration=10']], time_limit=1.5, factor=1000)
 
 
-    @mock.patch('Attack.BaseAttack.BaseAttack.write_attack_pcap', side_effect=Lib.write_attack_pcap)
-    def test_DDoS_100_000(self, mock_write_attack_pcap):
-        # TODO: update attack args, when DDoS gets refactored
-        self.temporal_efficiency_test([['DDoSAttack', 'attackers.count=1000', 'packets.per-second=950',
-                                        'attack.duration=300']], time_limit=150, factor=100000)
+    def test_MS17(self):
+        self.temporal_efficiency_test([['MS17Scan', 'ip.src=192.168.178.1']], time_limit=1.5, factor=1000)
 
 
-        # TODO: add temporal efficiency test(s) for EternalBlue and MS17
+    # FIXME: improve EternalBlue efficiency
+    #def test_EternalBlue(self):
+    #    self.temporal_efficiency_test([['EternalBlue']], time_limit=1.5, factor=1000)

+ 7 - 7
code/Test/test_DDoSAttack.py

@@ -3,13 +3,13 @@ import unittest.mock as mock
 import ID2TLib.TestLibrary as Lib
 import ID2TLib.TestLibrary as Lib
 import Test.ID2TAttackTest as Test
 import Test.ID2TAttackTest as Test
 
 
-sha_basic_ddos = 'd30a14ba0568cb9c3be0db6a6d8e5d68b703d995015fc2215bfa150a8aff8b2a'
-sha_num_attackers_ddos = '0de1ac89bb02e0163a31a0215d59ef2e2d819ffb904f8a99be1ecb52a568a392'
-sha_dest_mac_length_zero_ddos = '55720bc3aa43a6abad2db1bd1f9c7ff71cb50f11ca5f17995b24184678c18226'
-sha_mss_none_ddos = 'd30a14ba0568cb9c3be0db6a6d8e5d68b703d995015fc2215bfa150a8aff8b2a'
-sha_one_attacker_ddos = '8bb7798e85cff15b91c5ee2c0bb65f01ff3097a417bdd2e58a540f89d542bea9'
-sha_ip_range_ddos = 'bef5deb3cc7ee7537a90a85323cf885cf5a0431e15ae7001c0c762afc643e7a6'
-sha_port_range_ddos = '082f9bee607931751087fc4004bc95bf225f23b2a54ce1f771969019a5443ee7'
+sha_basic_ddos = 'a9b75322e2a331f617250d14935b0235aa818dd08803584d9cc3560b8305b459'
+sha_num_attackers_ddos = '86f13efe33d3e07c282d0111da09dead12bda1c2047d85e3a2c2f8d02b49e151'
+sha_dest_mac_length_zero_ddos = 'df4c55d25c3e13e38294f036e8ce17d7aaea309ecb9ade4eb551ed61589c0648'
+sha_mss_none_ddos = 'a9b75322e2a331f617250d14935b0235aa818dd08803584d9cc3560b8305b459'
+sha_one_attacker_ddos = 'd706c8594f54ab31f02700366fb9bfa872f9cc0e6393a9ed80bf255432e9cce8'
+sha_ip_range_ddos = '867b560a415562ffb6e973e57cdddf856826e6931dd1dbd732c6799fdc078f25'
+sha_port_range_ddos = 'f9adfe2d86fca0c66904a9b358e4bf31e122095eb2877f4ebcaec8e60b482ade'
 
 
 
 
 class UnitTestDDoS(Test.ID2TAttackTest):
 class UnitTestDDoS(Test.ID2TAttackTest):

+ 10 - 4
code/Test/test_Queries.py

@@ -6,12 +6,18 @@ import ID2TLib.TestLibrary as Test
 
 
 # TODO: improve coverage
 # TODO: improve coverage
 
 
-controller = Ctrl.Controller(pcap_file_path=Test.test_pcap, do_extra_tests=False)
+controller = Ctrl.Controller(pcap_file_path=Test.test_pcap, do_extra_tests=False, non_verbose=True)
 controller.load_pcap_statistics(flag_write_file=False, flag_recalculate_stats=True, flag_print_statistics=False)
 controller.load_pcap_statistics(flag_write_file=False, flag_recalculate_stats=True, flag_print_statistics=False)
 
 
-file_information = [('Pcap file', Test.test_pcap),
-                    ('Packets', 1998, 'packets'), ('Capture length', '25.4294414520264', 'seconds'),
-                    ('Capture start', '1970-01-01 01:01:45.647675'), ('Capture end', '1970-01-01 01:08:10.102034')]
+file_information = [('Pcap file path', Test.test_pcap),
+                    ('Total packet count', 1998, 'packets'),
+                    ("Recognized packets", 1988, "packets"),
+                    ("Unrecognized packets", 10, "PDUs"), ("% Recognized packets", 99.49949949949949, "%"),
+                    ("% Unrecognized packets", 0.5005005005005005, "%"),
+                    ("Last unknown PDU", '1970-01-01 01:07:39.604899'),
+                    ('Capture duration', '25.4294414520264', 'seconds'),
+                    ('Capture start', '\t1970-01-01 01:01:45.647675'),
+                    ('Capture end', '\t1970-01-01 01:08:10.102034')]
 
 
 file_statistics = [('Avg. packet rate', 78.57034301757812, 'packets/sec'), ('Avg. packet size', 0.0, 'kbytes'),
 file_statistics = [('Avg. packet rate', 78.57034301757812, 'packets/sec'), ('Avg. packet size', 0.0, 'kbytes'),
                    ('Avg. packets sent', 90.0, 'packets'), ('Avg. bandwidth in', 9.5290, 'kbit/s'),
                    ('Avg. packets sent', 90.0, 'packets'), ('Avg. bandwidth in', 9.5290, 'kbit/s'),

+ 17 - 2
code_boost/src/cxx/pcap_processor.cpp

@@ -128,6 +128,7 @@ void pcap_processor::collect_statistics() {
         // Save timestamp of first packet
         // Save timestamp of first packet
         stats.setTimestampFirstPacket(i->timestamp());
         stats.setTimestampFirstPacket(i->timestamp());
 
 
+        int totalPackets = 0;
         int timeIntervalCounter = 1;
         int timeIntervalCounter = 1;
         int timeIntervalsNum = 100;
         int timeIntervalsNum = 100;
         std::chrono::microseconds intervalStartTimestamp = stats.getTimestampFirstPacket();
         std::chrono::microseconds intervalStartTimestamp = stats.getTimestampFirstPacket();
@@ -135,7 +136,7 @@ void pcap_processor::collect_statistics() {
 
 
         // An empty loop to know the capture duration, then choose a suitable time interval
         // An empty loop to know the capture duration, then choose a suitable time interval
         SnifferIterator lastpkt; 
         SnifferIterator lastpkt; 
-        for (SnifferIterator j = snifferOverview.begin(); j != snifferOverview.end();  snifferIteratorIncrement(j)) {lastpkt = j;}          
+        for (SnifferIterator j = snifferOverview.begin(); j != snifferOverview.end(); ++j, ++totalPackets) {lastpkt = j;}
 
 
         std::chrono::microseconds lastTimestamp = lastpkt->timestamp();                  
         std::chrono::microseconds lastTimestamp = lastpkt->timestamp();                  
         std::chrono::microseconds captureDuration = lastTimestamp - firstTimestamp;
         std::chrono::microseconds captureDuration = lastTimestamp - firstTimestamp;
@@ -147,6 +148,9 @@ void pcap_processor::collect_statistics() {
         std::chrono::duration<int, std::micro> timeInterval(timeInterval_microsec);
         std::chrono::duration<int, std::micro> timeInterval(timeInterval_microsec);
         std::chrono::microseconds barrier = timeInterval;
         std::chrono::microseconds barrier = timeInterval;
 
 
+        std::cout << "\n";
+        std::chrono::system_clock::time_point lastPrinted = std::chrono::system_clock::now();
+
         // Iterate over all packets and collect statistics
         // Iterate over all packets and collect statistics
         for (; i != sniffer.end(); i++) {
         for (; i != sniffer.end(); i++) {
             currentPktTimestamp = i->timestamp();
             currentPktTimestamp = i->timestamp();
@@ -163,8 +167,19 @@ void pcap_processor::collect_statistics() {
 
 
             stats.incrementPacketCount();
             stats.incrementPacketCount();
             this->process_packets(*i);
             this->process_packets(*i);
+
+            // Indicate progress once every second
+            if (std::chrono::system_clock::now() - lastPrinted >= std::chrono::seconds(1)) {
+                int packetCount = stats.getPacketCount();
+                std::cout << "\rInspected packets: ";
+                std::cout << std::fixed << std::setprecision(1) << (static_cast<float>(packetCount)*100/totalPackets) << "%";
+                std::cout << " (" << packetCount << "/" << totalPackets << ")" << std::flush;
+                lastPrinted = std::chrono::system_clock::now();
+            }
         }
         }
-        
+
+        std::cout << "\n";
+
         // Save timestamp of last packet into statistics
         // Save timestamp of last packet into statistics
         stats.setTimestampLastPacket(currentPktTimestamp);
         stats.setTimestampLastPacket(currentPktTimestamp);
     }
     }

+ 1 - 9
code_boost/src/cxx/utilities.cpp

@@ -74,14 +74,6 @@ std::string getIPv4Class(std::string ipAddress){
     return ipClass;
     return ipClass;
 }
 }
 
 
-/**
- * Advance iterator by 10 steps.
- * @param iterator to advance.
- */
-void snifferIteratorIncrement(Tins::SnifferIterator& iterator){
-    (((((((((iterator++)++)++)++)++)++)++)++)++)++;  
-}
-
 /**
 /**
  * Convert IP address from string to array of bytes.
  * Convert IP address from string to array of bytes.
  * @param IP to convert.
  * @param IP to convert.
@@ -194,4 +186,4 @@ bool check_tcpChecksum(std::string ipAddressSender, std::string ipAddressReceive
     calculatedChecsum = tcp_sum_calc(bufferArray_8.size(), ipAddressSender_bytes, ipAddressReceiver_bytes, padding, buff_16);
     calculatedChecsum = tcp_sum_calc(bufferArray_8.size(), ipAddressSender_bytes, ipAddressReceiver_bytes, padding, buff_16);
 
 
     return (calculatedChecsum == checksum);
     return (calculatedChecsum == checksum);
-}
+}

+ 0 - 2
code_boost/src/cxx/utilities.h

@@ -23,8 +23,6 @@ using namespace Tins;
 
 
 std::string getIPv4Class(std::string ipAddress);
 std::string getIPv4Class(std::string ipAddress);
 
 
-void snifferIteratorIncrement(Tins::SnifferIterator& iterator);
-
 void convertIPv4toArray(std::string IP, unsigned short IP_bytes[]);
 void convertIPv4toArray(std::string IP, unsigned short IP_bytes[]);
 
 
 void split_str(const std::string& s, char delim,std::vector<std::string>& v);
 void split_str(const std::string& s, char delim,std::vector<std::string>& v);