3 Commits c7167456f3 ... 48844cbb47

Author SHA1 Message Date
  Patrick Jattke 48844cbb47 - Fixes several bugs introduced during restructure of get_packtes in the attack classes 7 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" 7 years ago
  Patrick Jattke a7cbfc38a9 - Makes the PortscanAttack compatible to the new attack pcap writing architecture 7 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):
             destination = destination_path
         else:
-            temp_file = tempfile.NamedTemporaryFile(delete=False)
+            temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pcap')
             destination = temp_file.name
 
         # Write packets into pcap file

+ 13 - 4
code/Attack/DDoSAttack.py

@@ -1,11 +1,13 @@
 import logging
-from random import randint, choice, uniform
+from random import randint, uniform
+
 from lea import Lea
-from scipy.stats import stats, gamma
+from scipy.stats import gamma
 
 from Attack import BaseAttack
 from Attack.AttackParameters import Parameter as Param
 from Attack.AttackParameters import ParameterTypes
+
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 from scapy.layers.inet import IP, Ether, TCP, RandShort
@@ -51,7 +53,10 @@ class DDoSAttack(BaseAttack.BaseAttack):
         # victim configuration
         random_ip_address = self.statistics.get_random_ip_address()
         self.add_param_value(Param.IP_DESTINATION, random_ip_address)
-        self.add_param_value(Param.MAC_DESTINATION, self.statistics.get_mac_address(random_ip_address))
+        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(
             "SELECT portNumber FROM ip_ports WHERE portDirection='in' ORDER BY RANDOM() LIMIT 1;")
         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)
                 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
         self.attack_end_utime = last_packet.time
 
         # 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()
         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_OPEN, '8080,9232,9233')
@@ -156,7 +159,10 @@ class PortscanAttack(BaseAttack.BaseAttack):
                 # else: destination port is NOT OPEN -> no reply is sent by target
 
         # 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 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:])
 
 # 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_PRINT = ['-s']
-#     STATS_PLOT = ['-p', 'format=pdf']
+#     STATS_PLOT = ['-p']
 #
 #     QUERY_MODE_LOOP = ['-q']
 #     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 os
-import tempfile
 import sys
-from scapy.utils import PcapWriter
+
 from Attack.AttackParameters import Parameter
 from ID2TLib import LabelManager
 from ID2TLib import Statistics
@@ -44,8 +42,7 @@ class AttackController:
     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
-        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 params: The parameters for attack customization, see attack class for supported params.
         :return: The file path to the created pcap file.
@@ -83,21 +80,15 @@ class AttackController:
         # Write attack into pcap file
         print("Generating attack packets...", end=" ")
         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
         l = Label(attack, self.get_attack_start_utime(),
                   self.get_attack_end_utime(), attack_note)
         self.label_mgr.add_labels(l)
 
-        return pcap_dest_path
+        return temp_attack_pcap_path
 
     def get_attack_start_utime(self):
         """

+ 27 - 7
code/ID2TLib/Controller.py

@@ -1,5 +1,4 @@
 import os
-
 import sys
 
 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
         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.
         """
         # load attacks sequentially
         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
-        print('Deleting intermediate attack pcaps...', end="")
+        print('Deleting intermediate attack pcap...', end="")
         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.")
 
         # write label file with attacks

+ 0 - 6
code/ID2TLib/PcapFile.py

@@ -1,6 +1,5 @@
 import hashlib
 import os.path
-import sys
 
 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
         :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)
         file_out_path = pcap.merge_pcaps(attack_pcap_path)
-        print("done.")
-
         return file_out_path
 
     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})
 # Libs pthread and dl are prerequisites of SQLiteCpp
 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());
     if (h != std::string::npos) {
         new_filepath.replace(h, newExt.length(), newExt);
+    } else {
+        new_filepath.append(newExt);
     }
 
     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();) {
         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);
-
         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++;
-
             if (iterator_attack == sniffer_attack.end())
                 all_attack_pkts_processed = true;
         } 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++;
         }
     }
@@ -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
     // In this case append the remaining packets of the attack PCAP
     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;
 }
 
@@ -229,10 +241,11 @@ bool inline pcap_processor::file_exists(const std::string &filePath) {
  * Comment in if executable should be build & run
  * Comment out if library should be build
  */
-//int main() {
+///*int main() {
 //    std::cout << "Starting application." << std::endl;
 //    //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);
 ////    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);
 ////    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;
-//}
+//}*/
 
 /*
  * Comment out if executable should be build & run