12 Commits 69e0d5b945 ... 564eb657dd

Author SHA1 Message Date
  Stefan Schmidt 564eb657dd Fixed format string truncation warning in statistics.cpp 5 years ago
  Stefan Schmidt 8ebd777723 Fixed comparison warning in botnet_comm_processor.cpp 5 years ago
  Jens Keim 8d752f372c Merge branch 'utc_timestamps' of stefan.schmidt/ID2T-toolkit into master 5 years ago
  Stefan Schmidt 4f6d449798 Fixed SMB2 "SystemTime" timestamp and test 5 years ago
  Stefan Schmidt 5f15213117 Made ID2T use UTC for timestamps to fix timezone-related problems 5 years ago
  Jens Keim 1fa1233925 add wheel pip package installation to build script 5 years ago
  Jens Keim 6e14fdd6dd fix Ubuntu dependency installation 5 years ago
  Carlos Garcia 0e838d296d Merge branch 'nmap_services_path_fix' of stefan.schmidt/ID2T-toolkit into master 5 years ago
  Stefan Schmidt 69e0d5b945 Fixed format string truncation warning in statistics.cpp 5 years ago
  Stefan Schmidt e7df66be69 Fixed comparison warning in botnet_comm_processor.cpp 5 years ago
  Stefan Schmidt 434e1c2175 Increased DB_VERSION, since the path fix can influence db contents 5 years ago
  Stefan Schmidt 1464229c6d Fixed ID2T not finding nmap-services-tcp.csv by passing through the resource path 5 years ago

+ 3 - 0
build.sh

@@ -34,6 +34,9 @@ fi
 # Activate the venv
 source .venv/bin/activate
 
+# Install wheel first
+pip3 install wheel
+
 # Install python packages
 pip3 install -r resources/requirements.txt
 

+ 1 - 1
code/Attack/BaseAttack.py

@@ -417,7 +417,7 @@ class BaseAttack(metaclass=abc.ABCMeta):
                 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", Util.RESOURCE_DIR).get_timestamp_mu_sec(int(value))
             if 0 <= int(value) <= self.statistics.get_packet_count() and ts >= 0:
                 is_valid = True
                 param_name = atkParam.Parameter.INJECT_AT_TIMESTAMP

+ 2 - 1
code/Core/LabelManager.py

@@ -2,6 +2,7 @@ import importlib
 import datetime as dt
 import os.path
 import xml.dom.minidom as minidom
+import pytz as pytz
 
 import ID2TLib.Label as Label
 import ID2TLib.TestLibrary as Lib
@@ -105,7 +106,7 @@ class LabelManager:
 
             # add timestamp in human-readable format
             timestamp_hr = doc.createElement(self.TAG_TIMESTAMP_HR)
-            timestamp_hr_text = dt.datetime.fromtimestamp(timestamp_entry).strftime('%Y-%m-%d %H:%M:%S.%f')
+            timestamp_hr_text = dt.datetime.fromtimestamp(timestamp_entry).astimezone(pytz.timezone('UTC')).strftime('%Y-%m-%d %H:%M:%S.%f')
             timestamp_hr.appendChild(doc.createTextNode(timestamp_hr_text))
             timestamp_root.appendChild(timestamp_hr)
 

+ 1 - 1
code/Core/Statistics.py

@@ -59,7 +59,7 @@ class Statistics:
 
         # Recalculate statistics if database does not exist OR param -r/--recalculate is provided
         if (not self.stats_db.get_db_exists()) or flag_recalculate_stats or self.stats_db.get_db_outdated():
-            self.pcap_proc = pr.pcap_processor(self.pcap_filepath, str(self.do_extra_tests))
+            self.pcap_proc = pr.pcap_processor(self.pcap_filepath, str(self.do_extra_tests), Util.RESOURCE_DIR)
             self.pcap_proc.collect_statistics()
             self.pcap_proc.write_to_database(self.path_db)
             outstring_datasource = "by PCAP file processor."

+ 1 - 1
code/ID2TLib/PcapFile.py

@@ -21,7 +21,7 @@ class PcapFile(object):
         :param attack_pcap_path: The path to the PCAP file to merge with the PCAP at pcap_file_path
         :return: The file path of the resulting PCAP file
         """
-        pcap = pr.pcap_processor(self.pcap_file_path, "False")
+        pcap = pr.pcap_processor(self.pcap_file_path, "False", Util.RESOURCE_DIR)
         file_out_path = pcap.merge_pcaps(attack_pcap_path)
         return file_out_path
 

+ 3 - 4
code/ID2TLib/Utility.py

@@ -7,6 +7,7 @@ import lea
 import xdg.BaseDirectory as BaseDir
 import scapy.layers.inet as inet
 import scipy.stats as stats
+import pytz as pytz
 
 CACHE_DIR = os.path.join(BaseDir.xdg_cache_home, 'id2t')
 CODE_DIR = os.path.dirname(os.path.abspath(__file__)) + "/../"
@@ -72,7 +73,7 @@ def update_timestamp(timestamp: float, pps: float, delay: float=0, inj_pps: floa
 
 
 def get_timestamp_from_datetime_str(time: str):
-    return dt.datetime.strptime(time, "%Y-%m-%d %H:%M:%S.%f").timestamp()
+    return pytz.timezone('UTC').localize(dt.datetime.strptime(time, "%Y-%m-%d %H:%M:%S.%f")).timestamp()
 
 
 def get_interval_pps(complement_interval_pps, timestamp):
@@ -189,9 +190,7 @@ def get_filetime_format(timestamp):
     :param timestamp: a timestamp in seconds
     :return: MS FILETIME timestamp
     """
-    boot_datetime = dt.datetime.fromtimestamp(timestamp)
-    if boot_datetime.tzinfo is None or boot_datetime.tzinfo.utcoffset(boot_datetime) is None:
-        boot_datetime = boot_datetime.replace(tzinfo=boot_datetime.tzname())
+    boot_datetime = dt.datetime.fromtimestamp(timestamp).astimezone(pytz.timezone('UTC'))
     boot_filetime = 116444736000000000 + (cal.timegm(boot_datetime.timetuple()) * 10000000)
     return boot_filetime + (boot_datetime.microsecond * 10)
 

+ 1 - 1
code/Test/test_SMBScanAttack.py

@@ -7,7 +7,7 @@ sha_dest_mac_only = 'c42a1775db981a139abd42d031273805cbebd2316b0d8c097217c12193f
 sha_multiple_victims_macos = 'b9a9f423d4154bc38723214124ad74dfdd07a39753563d21f5b453a8c069914a'
 sha_one_victim_linux = '3bb17444446334cf4feee9dd7cbeabd17acbb5ef48525fb3963591f30c37d17a'
 sha_port_shuffle = '08bdecc68fa1a2d1b0dd9802d7d025d42d90b9184d1fb6e1bcab234fac7db1b4'
-sha_smb2 = 'ef525fb61612a3db90bd0bbfaf4412f682933954357c941e1d8ac05c9ec373d4'
+sha_smb2 = '315bc052fd045f8738021062e8b5f77a33c649adfed490d3c9da94c97ba32f95'
 sha_ip_src_shuffle = '1d699ca109c62000b77b53002f1087ebf5ccc2c2dead1dbc5c18b5f6311273d0'
 sha_victim_range_winxp_hosting = 'bd624da4e3b7a3f06b8154ed9d6274d498b589aaaa11c2d0dc207a80ab7205b9'
 

+ 5 - 5
code/Test/test_internalQueries.py

@@ -22,10 +22,10 @@ class UnitTestInternalQueries(unittest.TestCase):
                           ("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'),
+                          ("Last unknown PDU", '1970-01-01 00:07:39.604899'),
                           ('Capture duration', '384.454345703125', 'seconds'),
-                          ('Capture start', '\t1970-01-01 01:01:45.647675'),
-                          ('Capture end', '\t1970-01-01 01:08:10.102034')])
+                          ('Capture start', '\t1970-01-01 00:01:45.647675'),
+                          ('Capture end', '\t1970-01-01 00:08:10.102034')])
 
     def test_get_packet_count(self):
         self.assertEqual(controller.statistics.get_packet_count(), 1998)
@@ -34,10 +34,10 @@ class UnitTestInternalQueries(unittest.TestCase):
         self.assertEqual(controller.statistics.get_capture_duration(), '384.454345703125')
 
     def test_get_pcap_timestamp_start(self):
-        self.assertEqual(controller.statistics.get_pcap_timestamp_start(), '1970-01-01 01:01:45.647675')
+        self.assertEqual(controller.statistics.get_pcap_timestamp_start(), '1970-01-01 00:01:45.647675')
 
     def test_get_pcap_timestamp_end(self):
-        self.assertEqual(controller.statistics.get_pcap_timestamp_end(), '1970-01-01 01:08:10.102034')
+        self.assertEqual(controller.statistics.get_pcap_timestamp_end(), '1970-01-01 00:08:10.102034')
 
     # FIXME: This seems to be the only testcase where float values differ slightly between macOS and Linux
     def test_get_general_file_statistics(self):

+ 3 - 3
code_boost/src/cxx/pcap_processor.cpp

@@ -9,12 +9,12 @@ using namespace Tins;
  * Creates a new pcap_processor object.
  * @param path The path where the PCAP to get analyzed is locatated.
  */
-pcap_processor::pcap_processor(std::string path, std::string extraTests) {
+pcap_processor::pcap_processor(std::string path, std::string extraTests, std::string resourcePath) : stats(resourcePath) {
     filePath = path;
     hasUnrecognized = false;
     if(extraTests == "True")
         stats.setDoExtraTests(true);
-    else stats.setDoExtraTests(false);;
+    else stats.setDoExtraTests(false);
 }
 
 /**
@@ -419,7 +419,7 @@ bool inline pcap_processor::file_exists(const std::string &filePath) {
  */
 PYBIND11_MODULE (libpcapreader, m) {
     py::class_<pcap_processor>(m, "pcap_processor")
-            .def(py::init<std::string, std::string>())
+            .def(py::init<std::string, std::string, std::string>())
             .def("merge_pcaps", &pcap_processor::merge_pcaps)
             .def("collect_statistics", &pcap_processor::collect_statistics)
             .def("get_timestamp_mu_sec", &pcap_processor::get_timestamp_mu_sec)

+ 1 - 1
code_boost/src/cxx/pcap_processor.h

@@ -23,7 +23,7 @@ public:
     /*
     * Class constructor
     */
-    pcap_processor(std::string path, std::string extraTests);
+    pcap_processor(std::string path, std::string extraTests, std::string resource_path);
 
     /*
      * Attributes

+ 4 - 3
code_boost/src/cxx/statistics.cpp

@@ -472,7 +472,8 @@ void statistics::incrementUnrecognizedPDUCount(const std::string &srcMac, const
 /**
  * Creates a new statistics object.
  */
-statistics::statistics(void) {
+statistics::statistics(std::string resourcePath) {
+    this->resourcePath = resourcePath;
 }
 
 /**
@@ -666,7 +667,7 @@ std::string statistics::getFormattedTimestamp(time_t seconds, suseconds_t micros
     tv.tv_sec = seconds;
     tv.tv_usec = microseconds;
     char tmbuf[20], buf[64];
-    auto nowtm = localtime(&(tv.tv_sec));
+    auto nowtm = gmtime(&(tv.tv_sec));
     strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
     snprintf(buf, sizeof(buf), "%s.%06u", tmbuf, static_cast<uint>(tv.tv_usec));
     return std::string(buf);
@@ -756,7 +757,7 @@ void statistics::writeToDatabase(std::string database_path) {
         float avgBandwidthOutInKBits = (sumBandwidthOut / senderCountIP) * 8;
 
         // Create database and write information
-        statistics_db db(database_path);
+        statistics_db db(database_path, resourcePath);
         db.writeStatisticsFile(packetCount, getCaptureDurationSeconds(),
                                getFormattedTimestamp(timestamp_firstPacket.seconds(), timestamp_firstPacket.microseconds()),
                                getFormattedTimestamp(timestamp_lastPacket.seconds(), timestamp_lastPacket.microseconds()),

+ 2 - 1
code_boost/src/cxx/statistics.h

@@ -515,7 +515,7 @@ public:
     /*
      * Constructor
      */
-    statistics();
+    statistics(std::string resourcePath);
 
     /*
      * Methods
@@ -618,6 +618,7 @@ private:
     Tins::Timestamp timestamp_lastPacket;
     float sumPacketSize = 0;
     int packetCount = 0;
+    std::string resourcePath;
 
     /* Extra tests includes:
      * - calculate IPs entropies for intervals

+ 4 - 61
code_boost/src/cxx/statistics_db.cpp

@@ -13,7 +13,7 @@ namespace py = pybind11;
  * a new database at database_path.
  * @param database_path The file path of the database.
  */
-statistics_db::statistics_db(std::string database_path) {
+statistics_db::statistics_db(std::string database_path, std::string resourcePath) {
     // Append file extension if not present
     if (database_path.find(".sqlite3") == database_path.npos) {
         database_path += ".sqlite3";
@@ -21,6 +21,8 @@ statistics_db::statistics_db(std::string database_path) {
     // creates the DB if not existing, opens the DB for read+write access
     db.reset(new SQLite::Database(database_path, SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE));
 
+    this->resourcePath = resourcePath;
+
     // Read ports and services into portServices vector
     readPortServicesFromNmap();
 }
@@ -637,7 +639,7 @@ void statistics_db::readPortServicesFromNmap()
     std::string portnumber;
     std::string service;
     std::string dump;
-    std::string nmapPath = getNmapPath();
+    std::string nmapPath = resourcePath + "nmap-services-tcp.csv";
     std::ifstream reader;
 
     reader.open(nmapPath, std::ios::in);
@@ -667,65 +669,6 @@ void statistics_db::readPortServicesFromNmap()
     }
 }
 
-/**
- * Gets the path to nmap-services-tcp.csv and makes sure the file is reached from any working directory within "/code"
- * because the working directory can be different when running tests. Checks if the file/path exists and warns the user.
- */
-std::string statistics_db::getNmapPath()
-{
-    //The different working directory paths according to how the database is built:
-    //<ID2T> stands for the directory id2t.sh is located in
-    //From tests(e.g. pycharm)  /<ID2T>/code/Test
-    //From run_tests.sh         /<ID2T>/code
-    //From id2t.sh              /<ID2T>
-    std::string filename = "nmap-services-tcp.csv";
-    std::string resourcesDir = "/resources/";
-    std::string codeDir = "/code";
-    std::string testDir = "/code/Test";
-    char buff[FILENAME_MAX];
-    // Working directory
-    std::string dir(getcwd(buff, FILENAME_MAX));
-
-    // Check if working directory is id2t.sh directory(try to reach file from working directory)
-    if(pathExists(dir + resourcesDir + filename))
-    {
-        return dir + resourcesDir + filename;
-    }
-
-    // If working directory is test directory(happens if tests are called from pycharm for example)
-    else if(dir.rfind(testDir) == (dir.size()-testDir.size()))
-    {
-        // Remove test directory from path
-        dir = dir.substr(0, (dir.size()-testDir.size()));
-    }
-
-    // If working directory is code directory(happens if tests are called with testscript)
-    else if(dir.rfind(codeDir) == (dir.size()-codeDir.size()))
-    {
-        // Remove code directory from path
-        dir = dir.substr(0, (dir.size()-codeDir.size()));
-    }
-
-    dir = dir + resourcesDir + filename;
-
-    return dir;
-}
-
-bool statistics_db::pathExists(std::string path)
-{
-    std::ifstream file;
-    file.open(path, std::ios::in);
-    if(file.is_open())
-    {
-        file.close();
-        return true;
-    }
-
-    else
-    {
-        return false;
-    }
-}
 /**
  * Writes the unrecognized PDUs into the database.
  * @param unrecognized_PDUs The unrecognized PDUs from class statistics.

+ 4 - 6
code_boost/src/cxx/statistics_db.h

@@ -17,12 +17,12 @@ public:
     /*
      * Constructor: Creates new database / Opens existing database
      */
-    statistics_db(std::string database_path);
+    statistics_db(std::string database_path, std::string resourcePath);
 
     /*
      * Database version: Increment number on every change in the C++ code!
      */
-    static const int DB_VERSION = 11;
+    static const int DB_VERSION = 13;
 
     /*
      * Methods for writing values into database
@@ -60,10 +60,6 @@ public:
 
     void readPortServicesFromNmap();
 
-    std::string getNmapPath();
-
-    bool pathExists(std::string path);
-
     void writeStatisticsUnrecognizedPDUs(const std::unordered_map<unrecognized_PDU, unrecognized_PDU_stat> &unrecognized_PDUs);
 
 
@@ -74,6 +70,8 @@ private:
     // Vector which contains all ports and their corresponding services
     std::unordered_map<int, std::string> portServices;
 
+    std::string resourcePath;
+
 };
 
 

+ 1 - 1
resources/install_dependencies.sh

@@ -59,7 +59,7 @@ install_pkg_ubuntu()
     if [ $? != 0 ]; then
         # Install all missing packages
         echo -e "Packages: Installing..."
-        $SUDO "apt-get install $APT_PKGS"
+        $SUDO apt-get install $APT_PKGS
     else
         echo -e "Packages: Found."
     fi