Browse Source

add class to ip_statistics table and generate attacker IP in DDoS based on most used class in BG

aidmar.wainakh 6 years ago
parent
commit
8fdfacae5d

+ 40 - 6
code/Attack/BaseAttack.py

@@ -343,7 +343,7 @@ class BaseAttack(metaclass=ABCMeta):
     #########################################
 
     @staticmethod
-    def generate_random_ipv4_address(n: int = 1):
+    def generate_random_ipv4_address(ipClass, n: int = 1):
         """
         Generates n random IPv4 addresses.
         :param n: The number of IP addresses to be generated
@@ -352,16 +352,50 @@ class BaseAttack(metaclass=ABCMeta):
 
         def is_invalid(ipAddress: ipaddress.IPv4Address):
             return ipAddress.is_multicast or ipAddress.is_unspecified or ipAddress.is_loopback or \
-                   ipAddress.is_link_local or ipAddress.is_private or ipAddress.is_reserved
+                   ipAddress.is_link_local or ipAddress.is_reserved or ipAddress.is_private
+
+        # Aidmar - generate a random IP from specific class
+        #def generate_address():
+        #    return ipaddress.IPv4Address(random.randint(0, 2 ** 32 - 1))
+        def generate_address(ipClass):
+            print(ipClass)
+            """if "private" in ipClass:
+                ipClassesByte1 = {"A-private": 10, "B-private": 172, "C-private": 192}
+                b1 = ipClassesByte1[ipClass]
+
+                ipClassesByte2 = {"A-private": {0,255}, "B-private": {16,131}, "C-private": {168,168}}
+                minB2 = ipClassesByte1[ipClass][0]
+                maxB2 = ipClassesByte1[ipClass][1]
+                b2 = random.randint(minB2, maxB2)
+
+                b3b4 = random.randint(0, 2 ** 16 - 1)
+
+                ipAddress = ipaddress.IPv4Address(str(b1)+str(b2)+str(b3b4))
+            else:"""
+            if ipClass == "Unknown":
+                return ipaddress.IPv4Address(random.randint(0, 2 ** 32 - 1))
+            else:
+                if "private" in ipClass:
+                    ipClass = ipClass[0]
+                ipClassesByte1 = {"A": {1,126}, "B": {128,191}, "C":{192, 223}, "D":{224, 239}, "E":{240, 254}}
+                temp = list(ipClassesByte1[ipClass])
+                minB1 = temp[0]
+                maxB1 = temp[1]
+                b1 = random.randint(minB1, maxB1)
+                b2 = random.randint(1, 255)
+                b3 = random.randint(1, 255)
+                b4 = random.randint(1, 255)
+
+                ipAddress = ipaddress.IPv4Address(str(b1) +"."+ str(b2) + "." + str(b3) + "." + str(b4))
+
+            return ipAddress
 
-        def generate_address():
-            return ipaddress.IPv4Address(random.randint(0, 2 ** 32 - 1))
 
         ip_addresses = []
         for i in range(0, n):
-            address = generate_address()
+            address = generate_address(ipClass)
             while is_invalid(address):
-                address = generate_address()
+                address = generate_address(ipClass)
             ip_addresses.append(str(address))
 
         if n == 1:

+ 10 - 2
code/Attack/DDoSAttack.py

@@ -46,7 +46,11 @@ class DDoSAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
         # attacker configuration
         num_attackers = randint(1, 16)
-        self.add_param_value(Param.IP_SOURCE, self.generate_random_ipv4_address(num_attackers))
+        # Aidmar
+        # The most used IP class in background traffic
+        most_used_ip_class = self.statistics.process_db_query("most_used(ipClass)")
+
+        self.add_param_value(Param.IP_SOURCE, self.generate_random_ipv4_address(most_used_ip_class, num_attackers))
         self.add_param_value(Param.MAC_SOURCE, self.generate_random_mac_address(num_attackers))
         self.add_param_value(Param.PORT_SOURCE, str(RandShort()))
         self.add_param_value(Param.PACKETS_PER_SECOND, randint(1, 64))
@@ -154,7 +158,11 @@ class DDoSAttack(BaseAttack.BaseAttack):
         num_attackers = self.get_param_value(Param.NUMBER_ATTACKERS)
         if num_attackers is not None:  # user supplied Param.NUMBER_ATTACKERS
             # Create random attackers based on user input Param.NUMBER_ATTACKERS
-            ip_source_list = self.generate_random_ipv4_address(num_attackers)
+            # Aidmar
+            # The most used IP class in background traffic
+            most_used_ip_class = self.statistics.process_db_query("most_used(ipClass)")
+
+            ip_source_list = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)
             mac_source_list = self.generate_random_mac_address(num_attackers)
         else:  # user did not supply Param.NUMBER_ATTACKS
             # use default values for IP_SOURCE/MAC_SOURCE or overwritten values

+ 1 - 0
code/ID2TLib/StatsDatabase.py

@@ -180,6 +180,7 @@ class StatsDatabase:
             "most_used.ttlvalue": "SELECT ttlValue FROM ip_ttl GROUP BY ttlValue ORDER BY SUM(ttlCount) DESC LIMIT 1",
             "most_used.mssvalue": "SELECT mssValue FROM tcp_mss_dist GROUP BY mssValue ORDER BY SUM(mssCount) DESC LIMIT 1",
             "most_used.winsize": "SELECT winSize FROM tcp_syn_win GROUP BY winSize ORDER BY SUM(winCount) DESC LIMIT 1",
+            "most_used.ipclass": "SELECT class FROM ip_statistics GROUP BY class ORDER BY COUNT(*) DESC LIMIT 1",
 
             "least_used.ipaddress": "SELECT ipAddress FROM ip_statistics WHERE (pktsSent+pktsReceived) == (SELECT MIN(pktsSent+pktsReceived) from ip_statistics)",
             "least_used.macaddress": "SELECT * FROM (SELECT macAddress, COUNT(*) as occ from ip_mac GROUP BY macAddress ORDER BY occ ASC) WHERE occ=(SELECT COUNT(*) as occ from ip_mac GROUP BY macAddress ORDER BY occ ASC LIMIT 1)",

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

@@ -10,6 +10,74 @@
 #include <SQLiteCpp/SQLiteCpp.h>
 #include "statistics_db.h"
 
+// Aidmar
+// Aidmar
+/**
+ * Split a string.
+ * @param str string to be splitted 
+ * @param delimiter delimiter to use in splitting
+ * @return vector of substrings
+ */
+std::vector<std::string> split(std::string str, char delimiter) {
+  std::vector<std::string> internal;
+  std::stringstream ss(str); // Turn the string into a stream.
+  std::string tok;  
+  while(getline(ss, tok, delimiter)) {
+    internal.push_back(tok);
+  }  
+  return internal;
+}
+
+// Aidmar
+/**
+ * Get the class (A,B,C,D,E) of IP address.
+ * @param ipAddress IP that we get its class
+ */
+std::string getIPv4Class(std::string ipAddress){
+    std::string ipClass="Unknown";
+    
+    std::vector<std::string> ipBytes = split(ipAddress, '.');
+    
+    std::cout<< ipAddress << "\n";
+    
+    if(ipBytes.size()>1){
+    int b1 = std::stoi(ipBytes[0]);
+    int b2 = std::stoi(ipBytes[1]);
+    
+    if(b1 >= 1 && b1 <= 126){
+        if(b1 == 10)
+            ipClass = "A-private";
+        else
+            ipClass = "A";
+    }
+    else if(b1 == 127){
+        ipClass = "A-unused"; // cannot be used and is reserved for loopback and diagnostic functions.
+    }
+    else if (b1 >= 128 && b1 <= 191){
+        if(b1 == 172 && b2 >= 16 && b2 <= 31) 
+            ipClass = "B-private";
+        else
+            ipClass = "B";
+    }
+    else if (b1 >= 192 && b1 <= 223){
+         if(b1 == 192 && b2 == 168) 
+            ipClass = "C-private";
+         else
+            ipClass = "C";
+    }
+    else if (b1 >= 224 && b1 <= 239)
+        ipClass = "D"; // Reserved for Multicasting
+    else if (b1 >= 240 && b1 <= 254)
+        ipClass = "E"; // Experimental; used for research    
+    }
+    /*
+     // Could be done by using libtin IPv4Address
+    IPv4Range range = IPv4Address("192.168.1.0") / 24;
+    range.contains("192.168.1.250"); // Yey, it belongs to this network
+    range.contains("192.168.0.100"); // NOPE
+    */
+    return ipClass;
+}
 
 // Aidmar
 /**
@@ -139,6 +207,8 @@ void statistics::calculateIntervalIPsEntropy(std::chrono::microseconds interval)
 // Aidmar
 /**
  * Calculate cumulative entropy of source and destination IPs; the entropy for packets from the beginning of the pcap file. 
+ * The function write the results to filePath_ip_entropy.csv file.
+ * @param filePath The PCAP fiel path.
  */
 void statistics::addIPEntropy(std::string filePath){
     std::vector <std::string> IPs; 
@@ -315,8 +385,12 @@ void statistics::assignMacAddress(std::string ipAddress, std::string macAddress)
  * @param bytesSent The packet's size.
  */
 void statistics::addIpStat_packetSent(std::string filePath, std::string ipAddressSender, std::string ipAddressReceiver, long bytesSent, std::chrono::microseconds timestamp) {
+    
     // Aidmar - Adding IP as a sender for first time
     if(ip_statistics[ipAddressSender].pkts_sent==0){  
+        // Add the IP class
+        ip_statistics[ipAddressSender].ip_class = getIPv4Class(ipAddressSender);
+        
         // Caculate Mahoney anomaly score for ip.src
         float ipSrc_Mahoney_score = 0;
         // s_r: The number of IP sources (the different values)
@@ -337,8 +411,7 @@ void statistics::addIpStat_packetSent(std::string filePath, std::string ipAddres
                     pktCntNvlSndr = i->second.firstAppearAsSenderPktCount;
             }
             // The "time" since last anomalous (novel) IP was appeared
-            s_t = packetCount - pktCntNvlSndr + 1;
-        
+            s_t = packetCount - pktCntNvlSndr + 1;        
             ipSrc_Mahoney_score = (float)s_t*n/s_r;
         }
         
@@ -363,6 +436,9 @@ void statistics::addIpStat_packetSent(std::string filePath, std::string ipAddres
     
     // Aidmar - Adding IP as a receiver for first time
     if(ip_statistics[ipAddressReceiver].pkts_received==0){
+        // Add the IP class
+        ip_statistics[ipAddressReceiver].ip_class = getIPv4Class(ipAddressReceiver); 
+        
         // Caculate Mahoney anomaly score for ip.dst
         float ipDst_Mahoney_score = 0;
         // s_r: The number of IP sources (the different values)
@@ -459,7 +535,6 @@ Tins::Timestamp statistics::getTimestampLastPacket() {
     return timestamp_lastPacket;
 }
 
-
 /**
  * Calculates the capture duration.
  * @return a formatted string HH:MM:SS.mmmmmm with

+ 3 - 0
code_boost/src/cxx/statistics.h

@@ -138,6 +138,8 @@ struct entry_ipStat {
     long pkts_sent;
     float kbytes_received;
     float kbytes_sent;
+    // Aidmar
+    std::string ip_class;
     // Aidmar - to calculate Mahoney anomaly score
     long firstAppearAsSenderPktCount;
     long firstAppearAsReceiverPktCount;
@@ -152,6 +154,7 @@ struct entry_ipStat {
                && pkts_sent == other.pkts_sent
                && kbytes_sent == other.kbytes_sent
                && kbytes_received == other.kbytes_received
+               && ip_class == other.ip_class
                // Aidmar
                && firstAppearAsSenderPktCount == other.firstAppearAsSenderPktCount
                && firstAppearAsReceiverPktCount == other.firstAppearAsReceiverPktCount

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

@@ -30,9 +30,10 @@ void statistics_db::writeStatisticsIP(std::unordered_map<std::string, entry_ipSt
                 "pktsSent INTEGER, "
                 "kbytesReceived REAL, "
                 "kbytesSent REAL, "
+                "class TEXT, "
                 "PRIMARY KEY(ipAddress));";
         db->exec(createTable);
-        SQLite::Statement query(*db, "INSERT INTO ip_statistics VALUES (?, ?, ?, ?, ?)");
+        SQLite::Statement query(*db, "INSERT INTO ip_statistics VALUES (?, ?, ?, ?, ?, ?)");
         for (auto it = ipStatistics.begin(); it != ipStatistics.end(); ++it) {
             entry_ipStat e = it->second;
             query.bind(1, it->first);
@@ -40,6 +41,8 @@ void statistics_db::writeStatisticsIP(std::unordered_map<std::string, entry_ipSt
             query.bind(3, (int) e.pkts_sent);
             query.bind(4, e.kbytes_received);
             query.bind(5, e.kbytes_sent);
+            // Aidmar
+            query.bind(6, e.ip_class);
             query.exec();
             query.reset();
         }