Browse Source

Add output parameter.
Due to the previous implementation, this requires a rebuild of ID2T.

dustin.born 7 years ago
parent
commit
23da4776b1

+ 3 - 2
code/CLI.py

@@ -65,7 +65,8 @@ class CLI(object):
         parser.add_argument('-t', '--extraTests', help='perform extra tests on the input pcap file, including calculating IP entropy'
                                                        'in interval-wise, TCP checksum, and checking payload availability.', action='store_true')
         parser.add_argument('--seed', help='random seed for the program, call the program with the same seed to get the same output')
-
+        parser.add_argument('-o', '--output', metavar="PCAP_FILE",
+                                 help='path to the output pcap file')
 
         # Attack arguments
         parser.add_argument('-a', '--attack', metavar="ATTACK", action='append',
@@ -149,7 +150,7 @@ class CLI(object):
         given queries.
         """
         # Create ID2T Controller
-        controller = Controller(self.args.input, self.args.extraTests)
+        controller = Controller(self.args.input, self.args.extraTests, self.args.output)
 
         # Load PCAP statistics
         controller.load_pcap_statistics(self.args.export, self.args.recalculate, self.args.statistics)

+ 13 - 6
code/ID2TLib/Controller.py

@@ -8,21 +8,25 @@ from ID2TLib.Statistics import Statistics
 
 
 class Controller:
-    def __init__(self, pcap_file_path: str, do_extra_tests: bool):
+    def __init__(self, in_pcap_file_path: str, do_extra_tests: bool, out_pcap_file_path):
         """
         Creates a new Controller, acting as a central coordinator for the whole application.
         :param pcap_file_path:
         """
         # Fields
-        self.pcap_src_path = pcap_file_path.strip()
+        self.in_pcap_src_path = in_pcap_file_path.strip()
+        if out_pcap_file_path:
+            self.out_pcap_src_path = out_pcap_file_path.strip()
+        else:
+            self.out_pcap_src_path = None
         self.pcap_dest_path = ''
         self.written_pcaps = []
         self.do_extra_tests = do_extra_tests
 
         # Initialize class instances
-        print("Input file: %s" % self.pcap_src_path)
-        self.pcap_file = PcapFile(self.pcap_src_path)
-        self.label_manager = LabelManager(self.pcap_src_path)
+        print("Input file: %s" % self.in_pcap_src_path)
+        self.pcap_file = PcapFile(self.in_pcap_src_path)
+        self.label_manager = LabelManager(self.in_pcap_src_path)
         self.statistics = Statistics(self.pcap_file)
         self.statistics.do_extra_tests = self.do_extra_tests
         self.statisticsDB = self.statistics.get_statistics_database()
@@ -68,7 +72,10 @@ class Controller:
         # 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(attacks_pcap_path)
+        if self.out_pcap_src_path:
+            self.pcap_dest_path = self.pcap_file.merge_attack_into(attacks_pcap_path, self.out_pcap_src_path)
+        else:
+            self.pcap_dest_path = self.pcap_file.merge_attack(attacks_pcap_path)
         print("done.")
 
         # delete intermediate PCAP files

+ 12 - 0
code/ID2TLib/PcapFile.py

@@ -24,6 +24,18 @@ class PcapFile(object):
         file_out_path = pcap.merge_pcaps(attack_pcap_path)
         return file_out_path
 
+    def merge_attack_into(self, attack_pcap_path: str, merged_out_path: str):
+        """
+        Merges the loaded PCAP with the PCAP at attack_pcap_path and stores the result in merged_out_path.
+
+        :param attack_pcap_path: The path to the PCAP file to merge with the PCAP at pcap_file_path
+        :param merged_out_path: The path to the output PCAP file
+        :return: The file path of the resulting PCAP file
+        """
+        pcap = pr.pcap_processor(self.pcap_file_path, "False")
+        file_out_path = pcap.merge_pcaps_into(attack_pcap_path, merged_out_path)
+        return file_out_path
+
     def get_file_hash(self):
         """
         Returns the hash for the loaded PCAP file. The hash is calculated bsaed on:

+ 65 - 0
code_boost/src/cxx/pcap_processor.cpp

@@ -103,6 +103,70 @@ std::string pcap_processor::merge_pcaps(const std::string pcap_path) {
     return new_filepath;
 }
 
+/**
+ * Merges two PCAP files, given by paths in filePath and parameter pcap_path.
+ * @param pcap_path The path to the file which should be merged with the loaded PCAP file.
+ * @param output_path: The path to the output file which the two PCAPs are merged into.
+ * @return The string containing the file path to the merged PCAP file.
+ */
+std::string pcap_processor::merge_pcaps_into(const std::string pcap_path, const std::string output_path) {
+    // If filename does not end with .pcap, add .pcap extension
+    std::string new_filepath = output_path;
+    const std::string &pcap_ext = ".pcap";
+    std::string::size_type h = new_filepath.rfind('.', new_filepath.length());
+    if (h != std::string::npos) {
+        if (new_filepath.compare(h, new_filepath.length() - h, pcap_ext) != 0) {
+            new_filepath.append(pcap_ext);
+        }
+    } else {
+        new_filepath.append(pcap_ext);
+    }
+
+    FileSniffer sniffer_base(filePath);
+    SnifferIterator iterator_base = sniffer_base.begin();
+
+    FileSniffer sniffer_attack(pcap_path);
+    SnifferIterator iterator_attack = sniffer_attack.begin();
+
+    PacketWriter writer(new_filepath, PacketWriter::ETH2);
+
+    bool all_attack_pkts_processed = false;
+    // Go through base PCAP and merge packets by timestamp
+    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) {
+            try {
+                writer.write(*iterator_attack);
+            } catch (serialization_error) {
+                std::cout << std::setprecision(15) << "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 {
+            try {
+                writer.write(*iterator_base);
+            } catch (serialization_error) {
+                    std::cout << "Could not serialize base packet with timestamp " << std::setprecision(15) << tstmp_attack << std::endl;
+            }
+            iterator_base++;
+        }
+    }    
+    
+    // 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++) {
+        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 " << std::setprecision(15) << tstmp_attack << std::endl;
+        }
+    }
+    return new_filepath;
+}
+
 /**
  * Collect statistics of the loaded PCAP file. Calls for each packet the method process_packets.
  */
@@ -337,6 +401,7 @@ using namespace boost::python;
 BOOST_PYTHON_MODULE (libpcapreader) {
     class_<pcap_processor>("pcap_processor", init<std::string, std::string>())
             .def("merge_pcaps", &pcap_processor::merge_pcaps)
+            .def("merge_pcaps_into", &pcap_processor::merge_pcaps_into)
             .def("collect_statistics", &pcap_processor::collect_statistics)
             .def("get_timestamp_mu_sec", &pcap_processor::get_timestamp_mu_sec)
             .def("write_to_database", &pcap_processor::write_to_database);

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

@@ -41,6 +41,8 @@ public:
 
     std::string merge_pcaps(const std::string pcap_path);
 
+    std::string merge_pcaps_into(const std::string pcap_path, const std::string output_path);
+
     void collect_statistics();
 
     void write_to_database(std::string database_path);