3 Commits c7167456f3 ... 48844cbb47

Author SHA1 Message Date
  Patrick Jattke 48844cbb47 - Fixes several bugs introduced during restructure of get_packtes in the attack classes 8 years ago
  Patrick Jattke 491bbd5673 - Fixes a bug producing a wrong merged dataset when the input dataset passed by the constructor does not have a ".filextension" 8 years ago
  Patrick Jattke a7cbfc38a9 - Makes the PortscanAttack compatible to the new attack pcap writing architecture 8 years ago

+ 1 - 1
code/Attack/BaseAttack.py

@@ -326,7 +326,7 @@ class BaseAttack(metaclass=ABCMeta):
         if destination_path is not None and os.path.exists(destination_path):
         if destination_path is not None and os.path.exists(destination_path):
             destination = destination_path
             destination = destination_path
         else:
         else:
-            temp_file = tempfile.NamedTemporaryFile(delete=False)
+            temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pcap')
             destination = temp_file.name
             destination = temp_file.name
 
 
         # Write packets into pcap file
         # Write packets into pcap file

+ 13 - 4
code/Attack/DDoSAttack.py

@@ -1,11 +1,13 @@
 import logging
 import logging
-from random import randint, choice, uniform
+from random import randint, uniform
+
 from lea import Lea
 from lea import Lea
-from scipy.stats import stats, gamma
+from scipy.stats import gamma
 
 
 from Attack import BaseAttack
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
 from Attack.AttackParameters import ParameterTypes
+
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 # noinspection PyPep8
 from scapy.layers.inet import IP, Ether, TCP, RandShort
 from scapy.layers.inet import IP, Ether, TCP, RandShort
@@ -51,7 +53,10 @@ class DDoSAttack(BaseAttack.BaseAttack):
         # victim configuration
         # victim configuration
         random_ip_address = self.statistics.get_random_ip_address()
         random_ip_address = self.statistics.get_random_ip_address()
         self.add_param_value(Param.IP_DESTINATION, 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))
+        destination_mac = self.statistics.get_mac_address(random_ip_address)
+        if isinstance(destination_mac, list) and len(destination_mac) == 0:
+            destination_mac = self.generate_random_mac_address()
+        self.add_param_value(Param.MAC_DESTINATION, destination_mac)
         port_destination = self.statistics.process_db_query(
         port_destination = self.statistics.process_db_query(
             "SELECT portNumber FROM ip_ports WHERE portDirection='in' ORDER BY RANDOM() LIMIT 1;")
             "SELECT portNumber FROM ip_ports WHERE portDirection='in' ORDER BY RANDOM() LIMIT 1;")
         if port_destination is None:
         if port_destination is None:
@@ -180,8 +185,12 @@ class DDoSAttack(BaseAttack.BaseAttack):
                 path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
                 path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
                 packets = []
                 packets = []
 
 
+        if len(packets) > 0:
+            packets = sorted(packets, key=lambda pkt: pkt.time)
+            path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
+
         # Store timestamp of last packet
         # Store timestamp of last packet
         self.attack_end_utime = last_packet.time
         self.attack_end_utime = last_packet.time
 
 
         # return packets sorted by packet time_sec_start
         # return packets sorted by packet time_sec_start
-        return path_attack_pcap
+        return pkt_num, path_attack_pcap

+ 9 - 3
code/Attack/PortscanAttack.py

@@ -53,7 +53,10 @@ class PortscanAttack(BaseAttack.BaseAttack):
 
 
         random_ip_address = self.statistics.get_random_ip_address()
         random_ip_address = self.statistics.get_random_ip_address()
         self.add_param_value(Param.IP_DESTINATION, 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))
+        destination_mac = self.statistics.get_mac_address(random_ip_address)
+        if isinstance(destination_mac, list) and len(destination_mac) == 0:
+            destination_mac = self.generate_random_mac_address()
+        self.add_param_value(Param.MAC_DESTINATION, destination_mac)
 
 
         self.add_param_value(Param.PORT_DESTINATION, '1-1023,1720,1900,8080')
         self.add_param_value(Param.PORT_DESTINATION, '1-1023,1720,1900,8080')
         self.add_param_value(Param.PORT_OPEN, '8080,9232,9233')
         self.add_param_value(Param.PORT_OPEN, '8080,9232,9233')
@@ -156,7 +159,10 @@ class PortscanAttack(BaseAttack.BaseAttack):
                 # else: destination port is NOT OPEN -> no reply is sent by target
                 # 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 = packets[-1].time
+
+        # write attack packets to pcap
+        pcap_path = self.write_attack_pcap(sorted(packets, key=lambda pkt: pkt.time))
 
 
         # return packets sorted by packet time_sec_start
         # return packets sorted by packet time_sec_start
-        return sorted(packets, key=lambda pkt: pkt.time)
+        return len(packets), pcap_path

+ 17 - 11
code/CLI.py

@@ -109,22 +109,28 @@ if __name__ == '__main__':
     main(sys.argv[1:])
     main(sys.argv[1:])
 
 
 # if __name__ == '__main__':
 # if __name__ == '__main__':
-#     FILE = ['-i', '/mnt/hgfs/datasets/95M.pcap']
-#     FILE2 = ['-i', '/mnt/hgfs/datasets/95M_20161103-185151.pcap']
-#     FILE3 = ['-i', '/home/pjattke/temp/test_me_short.pcap']
-#     ATTACK_NO_PARAM = ['-a', 'DDoSAttack', 'attackers.count=10']
+#     INPUT = ['-i']
 #
 #
-#     ATTACK = ['-a', 'PortscanAttack', 'ip.src=10.2.2.4', 'mac.dst=05:AB:47:B5:19:11',
-#               'inject.at-timestamp=1449038705.316721', 'attack.note=Portscan2']
-#     ATTACK2 = ['-a', 'PortscanAttack', 'ip.dst=193.133.122.23', 'ip.src=192.124.34.12', 'inject.after-pkt=34']
+#     #    FILES = ['/root/datasets/201506021400_1G.pcap',
+#     #             '/root/datasets/201506021400_2G.pcap',
+#     #             '/root/datasets/201506021400_5G.pcap']
+#
+#     # FILES = ['/mnt/hgfs/datasets/201506021400_2G.pcap']
+#
+#     FILES = ['/home/pjattke/temp/test_me_short.pcap']
+#
+#     ATTACK_PS = ['-a', 'PortscanAttack', 'ip.src=10.2.2.4', 'mac.dst=05:AB:47:B5:19:11',
+#                  'inject.at-timestamp=1449038705.316721', 'attack.note=Portscan2']
+#     ATTACK_PS2 = ['-a', 'PortscanAttack', 'port.dst=1-1024', 'ip.src=3.3.3.3']
+#     ATTACK_DD = ['-a', 'DDoSAttack', 'ip.dst=9.9.9.9', 'attackers.count=10', 'packets.limit=100']
 #
 #
 #     STATS_RECALC = ['-r']
 #     STATS_RECALC = ['-r']
 #     STATS_PRINT = ['-s']
 #     STATS_PRINT = ['-s']
-#     STATS_PLOT = ['-p', 'format=pdf']
+#     STATS_PLOT = ['-p']
 #
 #
 #     QUERY_MODE_LOOP = ['-q']
 #     QUERY_MODE_LOOP = ['-q']
 #     QUERY_DB = ['-q', 'ipAddress(pktsSent > 1000, kbytesSent >= 20)']
 #     QUERY_DB = ['-q', 'ipAddress(pktsSent > 1000, kbytesSent >= 20)']
 #
 #
-#     main(FILE + STATS_PLOT)
-
-    # main(['-c', '/home/pjattke/Thesis/development/code/config'])
+#     for f in FILES:
+#         main(INPUT + [f] + ATTACK_PS2 + ATTACK_DD)  # Statistics Calculation
+#         #main(INPUT + ATTACK_DD)  # Attack Packet Generation -> insert exit() | Merging

+ 5 - 14
code/ID2TLib/AttackController.py

@@ -1,8 +1,6 @@
 import importlib
 import importlib
-import os
-import tempfile
 import sys
 import sys
-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
@@ -44,8 +42,7 @@ class AttackController:
     def process_attack(self, attack: str, params: str):
     def process_attack(self, attack: str, params: str):
         """
         """
         Takes as input the name of an attack (classname) and the attack parameters as string. Parses the string of
         Takes as input the name of an attack (classname) and the attack parameters as string. Parses the string of
-        attack parameters, creates the attack by writing the attack packets, merges these packets into the existing
-        dataset and stores the label file of the injected attacks.
+        attack parameters, creates the attack by writing the attack packets and returns the path of the written pcap.
         :param attack: The classname of the attack to injecect.
         :param attack: The classname of the attack to injecect.
         :param params: The parameters for attack customization, see attack class for supported params.
         :param params: The parameters for attack customization, see attack class for supported params.
         :return: The file path to the created pcap file.
         :return: The file path to the created pcap file.
@@ -83,21 +80,15 @@ class AttackController:
         # Write attack into pcap file
         # Write attack into pcap file
         print("Generating attack packets...", end=" ")
         print("Generating attack packets...", end=" ")
         sys.stdout.flush()  # force python to print text immediately
         sys.stdout.flush()  # force python to print text immediately
-        temp_attack_pcap_path = self.current_attack.generate_attack_pcap()
-        print("done.")
-
-        # Merge attack with existing pcap
-        pcap_dest_path = self.pcap_file.merge_attack(temp_attack_pcap_path)
-
-        # Delete temporary attack pcap
-        os.remove(temp_attack_pcap_path)
+        total_packets, temp_attack_pcap_path = self.current_attack.generate_attack_pcap()
+        print("done. (total: " + str(total_packets) + " pkts.)")
 
 
         # Store label into LabelManager
         # Store label into LabelManager
         l = Label(attack, self.get_attack_start_utime(),
         l = Label(attack, self.get_attack_start_utime(),
                   self.get_attack_end_utime(), attack_note)
                   self.get_attack_end_utime(), attack_note)
         self.label_mgr.add_labels(l)
         self.label_mgr.add_labels(l)
 
 
-        return pcap_dest_path
+        return temp_attack_pcap_path
 
 
     def get_attack_start_utime(self):
     def get_attack_start_utime(self):
         """
         """

+ 27 - 7
code/ID2TLib/Controller.py

@@ -1,5 +1,4 @@
 import os
 import os
-
 import sys
 import sys
 
 
 from ID2TLib.AttackController import AttackController
 from ID2TLib.AttackController import AttackController
@@ -42,19 +41,40 @@ class Controller:
         """
         """
         Creates the attack based on the attack name and the attack parameters given in the attacks_config. The
         Creates the attack based on the attack name and the attack parameters given in the attacks_config. The
         attacks_config is a list of attacks, e.g.
         attacks_config is a list of attacks, e.g.
-        [['PortscanAttack', 'ip.src="192.168.178.2",'dst.port=80'],['PortscanAttack', 'ip.src="10.10.10.2"]]
+        [['PortscanAttack', 'ip.src="192.168.178.2",'dst.port=80'],['PortscanAttack', 'ip.src="10.10.10.2"]].
+        Merges the individual temporary attack pcaps into one single pcap and merges this single pcap with the
+        input dataset.
         :param attacks_config: A list of attacks with their attack parameters.
         :param attacks_config: A list of attacks with their attack parameters.
         """
         """
         # load attacks sequentially
         # load attacks sequentially
         for attack in attacks_config:
         for attack in attacks_config:
-            self.pcap_dest_path = self.attack_controller.process_attack(attack[0], attack[1:])
-            self.written_pcaps.append(self.pcap_dest_path)
+            temp_attack_pcap = self.attack_controller.process_attack(attack[0], attack[1:])
+            self.written_pcaps.append(temp_attack_pcap)
+
+        # merge attack pcaps to get single attack pcap
+        if len(self.written_pcaps) > 1:
+            print("\nMerging temporary attack pcaps into single pcap file...", end=" ")
+            sys.stdout.flush()  # force python to print text immediately
+            attack_pcap_file = PcapFile(self.written_pcaps[0])
+            for attack in self.written_pcaps[1:]:
+                all_attacks_pcap = attack_pcap_file.merge_attack(attack)
+                os.remove(attack)  # remove merged pcap
+                # Create new PcapFile object for next iteration
+                attack_pcap_file = PcapFile(all_attacks_pcap)
+            print("done.")
+        else:
+            all_attacks_pcap = self.written_pcaps[0]
+
+        # merge single attack pcap with all attacks into base pcap
+        print("Merging base pcap with single attack pcap...", end=" ")
+        sys.stdout.flush()  # force python to print text immediately
+        self.pcap_dest_path = self.pcap_file.merge_attack(all_attacks_pcap)
+        print("done.")
 
 
         # delete intermediate PCAP files
         # delete intermediate PCAP files
-        print('Deleting intermediate attack pcaps...', end="")
+        print('Deleting intermediate attack pcap...', end="")
         sys.stdout.flush()  # force python to print text immediately
         sys.stdout.flush()  # force python to print text immediately
-        for i in range(len(self.written_pcaps) - 1):
-            os.remove(self.written_pcaps[i])
+        os.remove(all_attacks_pcap)
         print("done.")
         print("done.")
 
 
         # write label file with attacks
         # write label file with attacks

+ 0 - 6
code/ID2TLib/PcapFile.py

@@ -1,6 +1,5 @@
 import hashlib
 import hashlib
 import os.path
 import os.path
-import sys
 
 
 import ID2TLib.libpcapreader as pr
 import ID2TLib.libpcapreader as pr
 
 
@@ -21,13 +20,8 @@ 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=" ")
-        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)
         file_out_path = pcap.merge_pcaps(attack_pcap_path)
         file_out_path = pcap.merge_pcaps(attack_pcap_path)
-        print("done.")
-
         return file_out_path
         return file_out_path
 
 
     def get_file_hash(self):
     def get_file_hash(self):

+ 4 - 0
code_boost/src/CMakeLists.txt

@@ -73,3 +73,7 @@ SET_target_properties(sqlite3 PROPERTIES POSITION_INDEPENDENT_CODE ON)
 ADD_LIBRARY(pcapreader SHARED ${SOURCE_FILES})
 ADD_LIBRARY(pcapreader SHARED ${SOURCE_FILES})
 # Libs pthread and dl are prerequisites of SQLiteCpp
 # Libs pthread and dl are prerequisites of SQLiteCpp
 TARGET_LINK_LIBRARIES(pcapreader ${Boost_LIBRARIES} "${TINS_LIBRARY}" SQLiteCpp sqlite3 pthread dl)
 TARGET_LINK_LIBRARIES(pcapreader ${Boost_LIBRARIES} "${TINS_LIBRARY}" SQLiteCpp sqlite3 pthread dl)
+
+# comment this out to build executable (for development)
+#ADD_EXECUTABLE(cpp-pcapreader ${SOURCE_FILES})
+#TARGET_LINK_LIBRARIES(cpp-pcapreader ${Boost_LIBRARIES} "${TINS_LIBRARY}" SQLiteCpp sqlite3 pthread dl)

+ 24 - 10
code_boost/src/cxx/pcap_processor.cpp

@@ -50,6 +50,8 @@ std::string pcap_processor::merge_pcaps(const std::string pcap_path) {
     std::string::size_type h = new_filepath.rfind('.', new_filepath.length());
     std::string::size_type h = new_filepath.rfind('.', new_filepath.length());
     if (h != std::string::npos) {
     if (h != std::string::npos) {
         new_filepath.replace(h, newExt.length(), newExt);
         new_filepath.replace(h, newExt.length(), newExt);
+    } else {
+        new_filepath.append(newExt);
     }
     }
 
 
     FileSniffer sniffer_base(filePath);
     FileSniffer sniffer_base(filePath);
@@ -65,15 +67,21 @@ std::string pcap_processor::merge_pcaps(const std::string pcap_path) {
     for (; iterator_base != sniffer_base.end();) {
     for (; iterator_base != sniffer_base.end();) {
         auto tstmp_base = (iterator_base->timestamp().seconds()) + (iterator_base->timestamp().microseconds()*1e-6);
         auto tstmp_base = (iterator_base->timestamp().seconds()) + (iterator_base->timestamp().microseconds()*1e-6);
         auto tstmp_attack = (iterator_attack->timestamp().seconds()) + (iterator_attack->timestamp().microseconds()*1e-6);
         auto tstmp_attack = (iterator_attack->timestamp().seconds()) + (iterator_attack->timestamp().microseconds()*1e-6);
-
         if (!all_attack_pkts_processed && tstmp_attack <= tstmp_base) {
         if (!all_attack_pkts_processed && tstmp_attack <= tstmp_base) {
-            writer.write(*iterator_attack);
+            try {
+                writer.write(*iterator_attack);
+            } catch (serialization_error) {
+                std::cout << "Could not serialize attack packet with timestamp " << tstmp_attack << std::endl;
+            }
             iterator_attack++;
             iterator_attack++;
-
             if (iterator_attack == sniffer_attack.end())
             if (iterator_attack == sniffer_attack.end())
                 all_attack_pkts_processed = true;
                 all_attack_pkts_processed = true;
         } else {
         } else {
-            writer.write(*iterator_base);
+            try {
+                writer.write(*iterator_base);
+            } catch (serialization_error) {
+                    std::cout << "Could not serialize base packet with timestamp " << tstmp_attack << std::endl;
+            }
             iterator_base++;
             iterator_base++;
         }
         }
     }
     }
@@ -81,9 +89,13 @@ std::string pcap_processor::merge_pcaps(const std::string pcap_path) {
     // This may happen if the base PCAP is smaller than the attack PCAP
     // This may happen if the base PCAP is smaller than the attack PCAP
     // In this case append the remaining packets of the attack PCAP
     // In this case append the remaining packets of the attack PCAP
     for (; iterator_attack != sniffer_attack.end(); iterator_attack++) {
     for (; iterator_attack != sniffer_attack.end(); iterator_attack++) {
-        writer.write(*iterator_attack);
+        try {
+            writer.write(*iterator_attack);
+        } catch (serialization_error) {
+            auto tstmp_attack = (iterator_attack->timestamp().seconds()) + (iterator_attack->timestamp().microseconds()*1e-6);
+            std::cout << "Could not serialize attack packet with timestamp " << tstmp_attack << std::endl;
+        }
     }
     }
-
     return new_filepath;
     return new_filepath;
 }
 }
 
 
@@ -229,10 +241,11 @@ bool inline pcap_processor::file_exists(const std::string &filePath) {
  * Comment in if executable should be build & run
  * Comment in if executable should be build & run
  * Comment out if library should be build
  * Comment out if library should be build
  */
  */
-//int main() {
+///*int main() {
 //    std::cout << "Starting application." << std::endl;
 //    std::cout << "Starting application." << std::endl;
 //    //pcap_processor pcap = pcap_processor("/mnt/hgfs/datasets/95M.pcap");
 //    //pcap_processor pcap = pcap_processor("/mnt/hgfs/datasets/95M.pcap");
-//    pcap_processor pcap = pcap_processor("/home/pjattke/temp/test_me_short.pcap");
+////pcap_processor pcap = pcap_processor("/home/pjattke/temp/test_me_short.pcap");
+//    pcap_processor pcap = pcap_processor("/tmp/tmp0hhz2oia");
 ////long double t = pcap.get_timestamp_mu_sec(87);
 ////long double t = pcap.get_timestamp_mu_sec(87);
 ////    std::cout << t << std::endl;
 ////    std::cout << t << std::endl;
 //
 //
@@ -244,11 +257,12 @@ bool inline pcap_processor::file_exists(const std::string &filePath) {
 ////    printf("Elapsed time is %.2lf seconds.", dif);
 ////    printf("Elapsed time is %.2lf seconds.", dif);
 ////    pcap.stats.writeToDatabase("/home/pjattke/myDB.sqlite3");
 ////    pcap.stats.writeToDatabase("/home/pjattke/myDB.sqlite3");
 //
 //
-//    pcap.merge_pcaps("/home/pjattke/temp/temp_attack.pcap");
+//    std::string path = pcap.merge_pcaps("/tmp/tmp0okkfdx_");
+//    std::cout << path << std::endl;
 //
 //
 //
 //
 //    return 0;
 //    return 0;
-//}
+//}*/
 
 
 /*
 /*
  * Comment out if executable should be build & run
  * Comment out if executable should be build & run