Browse Source

move redundant functions to utility library

move update_timestamp
move getIntervalPPS
move get_nth_random_element
move index_increment
Roey Regev 6 years ago
parent
commit
a7518d61f8

+ 1 - 49
code/Attack/DDoSAttack.py

@@ -12,6 +12,7 @@ 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
 from collections import deque
 from collections import deque
+from ID2TLib.Utility import *
 
 
 
 
 class DDoSAttack(BaseAttack.BaseAttack):
 class DDoSAttack(BaseAttack.BaseAttack):
@@ -72,54 +73,6 @@ class DDoSAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.VICTIM_BUFFER, randint(1000,10000))
         self.add_param_value(Param.VICTIM_BUFFER, randint(1000,10000))
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            if delay == 0:
-                # Calculate the request timestamp
-                # A distribution to imitate the bursty behavior of traffic
-                randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-                return timestamp + uniform(1 / pps, randomdelay.random())
-            else:
-                # Calculate the reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2 * delay: 70, 3 * delay: 20, 5 * delay: 7, 10 * delay: 3})
-                return timestamp + uniform(1 / pps + delay, 1 / pps + randomdelay.random())
-
-        def get_nth_random_element(*element_list):
-            """
-            Returns the n-th element of every list from an arbitrary number of given lists.
-            For example, list1 contains IP addresses, list 2 contains MAC addresses. Use of this function ensures that
-            the n-th IP address uses always the n-th MAC address.
-            :param element_list: An arbitrary number of lists.
-            :return: A tuple of the n-th element of every list.
-            """
-            range_max = min([len(x) for x in element_list])
-            if range_max > 0: range_max -= 1
-            n = randint(0, range_max)
-            return tuple(x[n] for x in element_list)
-
-        def index_increment(number: int, max: int):
-            if number + 1 < max:
-                return number + 1
-            else:
-                return 0
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            # In case the timestamp > capture max timestamp
-            return complement_interval_pps[-1][1]
-
         def get_attacker_config(ipAddress: str):
         def get_attacker_config(ipAddress: str):
             """
             """
             Returns the attacker configuration depending on the IP address, this includes the port for the next
             Returns the attacker configuration depending on the IP address, this includes the port for the next
@@ -151,7 +104,6 @@ class DDoSAttack(BaseAttack.BaseAttack):
                 attacker_ttl_mapping[ipAddress] = ttl
                 attacker_ttl_mapping[ipAddress] = ttl
             # return port and TTL
             # return port and TTL
             return next_port, ttl
             return next_port, ttl
-
         BUFFER_SIZE = 1000
         BUFFER_SIZE = 1000
 
 
         # Determine source IP and MAC address
         # Determine source IP and MAC address

+ 2 - 21
code/Attack/EternalBlueExploit.py

@@ -11,6 +11,7 @@ logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 # noinspection PyPep8
 from scapy.utils import RawPcapReader
 from scapy.utils import RawPcapReader
 from scapy.layers.inet import IP, Ether, TCP, RandShort
 from scapy.layers.inet import IP, Ether, TCP, RandShort
+from ID2TLib.Utility import *
 
 
 class EternalBlueExploit(BaseAttack.BaseAttack):
 class EternalBlueExploit(BaseAttack.BaseAttack):
     template_scan_pcap_path = "resources/Win7_eternalblue_scan.pcap"
     template_scan_pcap_path = "resources/Win7_eternalblue_scan.pcap"
@@ -78,27 +79,7 @@ class EternalBlueExploit(BaseAttack.BaseAttack):
         self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
         self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            # Calculate the request timestamp
-            # A distribution to imitate the bursty behavior of traffic
-            randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-            return timestamp + uniform(1 / pps, randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
+
 
 
         # Timestamp
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)

+ 1 - 21
code/Attack/JoomlaRegPrivExploit.py

@@ -11,6 +11,7 @@ logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 # noinspection PyPep8
 from scapy.utils import RawPcapReader
 from scapy.utils import RawPcapReader
 from scapy.layers.inet import IP, Ether, TCP, RandShort
 from scapy.layers.inet import IP, Ether, TCP, RandShort
+from ID2TLib.Utility import *
 
 
 
 
 class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
 class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
@@ -79,27 +80,6 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            # Calculate the request timestamp
-            # A distribution to imitate the bursty behavior of traffic
-            randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-            return timestamp + uniform(1 / pps, randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1]  # in case the timstamp > capture max timestamp
 
 
         # Timestamp
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)

+ 4 - 29
code/Attack/PortscanAttack.py

@@ -8,7 +8,7 @@ from lea import Lea
 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
-
+from ID2TLib.Utility import *
 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
 from scapy.layers.inet import IP, Ether, TCP
@@ -108,34 +108,9 @@ class PortscanAttack(BaseAttack.BaseAttack):
         return port_dst_shuffled
         return port_dst_shuffled
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            if delay == 0:
-                # Calculate request timestamp
-                # To imitate the bursty behavior of traffic
-                randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-                return timestamp + uniform(1/pps ,  randomdelay.random())
-            else:
-                # Calculate reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2*delay: 70, 3*delay: 20, 5*delay: 7, 10*delay: 3})
-                return timestamp + uniform(1 / pps + delay,  1 / pps + randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
+
+
+
 
 
         mac_source = self.get_param_value(Param.MAC_SOURCE)
         mac_source = self.get_param_value(Param.MAC_SOURCE)
         mac_destination = self.get_param_value(Param.MAC_DESTINATION)
         mac_destination = self.get_param_value(Param.MAC_DESTINATION)

+ 7 - 36
code/Attack/SMBLorisAttack.py

@@ -8,6 +8,8 @@ from lea import Lea
 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
+from ID2TLib.Utility import *
+from ID2TLib.SMBLib import *
 
 
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 # noinspection PyPep8
@@ -21,8 +23,6 @@ from scapy.layers.netbios import NBTSession
 # http://smbloris.com/
 # http://smbloris.com/
 
 
 class SMBLorisAttack(BaseAttack.BaseAttack):
 class SMBLorisAttack(BaseAttack.BaseAttack):
-    # SMB port
-    smb_port = 445
 
 
     def __init__(self):
     def __init__(self):
         """
         """
@@ -85,35 +85,6 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.ATTACK_DURATION, 30)
         self.add_param_value(Param.ATTACK_DURATION, 30)
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            if delay == 0:
-                # Calculate request timestamp
-                # To imitate the bursty behavior of traffic
-                randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-                return timestamp + uniform(1/pps ,  randomdelay.random())
-            else:
-                # Calculate reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2*delay: 70, 3*delay: 20, 5*delay: 7, 10*delay: 3})
-                return timestamp + uniform(1 / pps + delay,  1 / pps + randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
-
         def getIpData(ip_address: str):
         def getIpData(ip_address: str):
             """
             """
             :param ip_address: the ip of which (packet-)data shall be returned
             :param ip_address: the ip of which (packet-)data shall be returned
@@ -224,7 +195,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 victim_ip = IP(src=ip_destination, dst=ip_source_list[attacker], ttl=destination_ttl_value, flags='DF')
                 victim_ip = IP(src=ip_destination, dst=ip_source_list[attacker], ttl=destination_ttl_value, flags='DF')
 
 
                 # connection request from attacker (client)
                 # connection request from attacker (client)
-                syn_tcp = TCP(sport=sport, dport=self.smb_port, window=source_win_value, flags='S',
+                syn_tcp = TCP(sport=sport, dport=smb_port, window=source_win_value, flags='S',
                               seq=attacker_seq, options=[('MSS', source_mss_value)])
                               seq=attacker_seq, options=[('MSS', source_mss_value)])
                 attacker_seq += 1
                 attacker_seq += 1
                 syn = (attacker_ether / attacker_ip / syn_tcp)
                 syn = (attacker_ether / attacker_ip / syn_tcp)
@@ -233,7 +204,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(syn)
                 packets.append(syn)
 
 
                 # response from victim (server)
                 # response from victim (server)
-                synack_tcp = TCP(sport=self.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='SA',
+                synack_tcp = TCP(sport=smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='SA',
                                  window=destination_win_value, options=[('MSS', destination_mss_value)])
                                  window=destination_win_value, options=[('MSS', destination_mss_value)])
                 victim_seq += 1
                 victim_seq += 1
                 synack = (victim_ether / victim_ip / synack_tcp)
                 synack = (victim_ether / victim_ip / synack_tcp)
@@ -242,7 +213,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(synack)
                 packets.append(synack)
 
 
                 # acknowledgement from attacker (client)
                 # acknowledgement from attacker (client)
-                ack_tcp = TCP(sport=sport, dport=self.smb_port, seq=attacker_seq, ack=victim_seq, flags='A',
+                ack_tcp = TCP(sport=sport, dport=smb_port, seq=attacker_seq, ack=victim_seq, flags='A',
                               window=source_win_value, options=[('MSS', source_mss_value)])
                               window=source_win_value, options=[('MSS', source_mss_value)])
                 ack = (attacker_ether / attacker_ip / ack_tcp)
                 ack = (attacker_ether / attacker_ip / ack_tcp)
                 ack.time = timestamp_next_pkt
                 ack.time = timestamp_next_pkt
@@ -250,7 +221,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(ack)
                 packets.append(ack)
 
 
                 # send NBT session header paket with maximum LENGTH-field
                 # send NBT session header paket with maximum LENGTH-field
-                req_tcp = TCP(sport=sport, dport=self.smb_port, seq=attacker_seq, ack=victim_seq, flags='AP',
+                req_tcp = TCP(sport=sport, dport=smb_port, seq=attacker_seq, ack=victim_seq, flags='AP',
                               window=source_win_value, options=[('MSS', source_mss_value)])
                               window=source_win_value, options=[('MSS', source_mss_value)])
                 req_payload = NBTSession(TYPE=0x00, LENGTH=0x1FFFF)
                 req_payload = NBTSession(TYPE=0x00, LENGTH=0x1FFFF)
 
 
@@ -261,7 +232,7 @@ class SMBLorisAttack(BaseAttack.BaseAttack):
                 packets.append(req)
                 packets.append(req)
 
 
                 # final ack from victim (server)
                 # final ack from victim (server)
-                last_ack_tcp = TCP(sport=self.smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='A',
+                last_ack_tcp = TCP(sport=smb_port, dport=sport, seq=victim_seq, ack=attacker_seq, flags='A',
                                    window=destination_win_value, options=[('MSS', destination_mss_value)])
                                    window=destination_win_value, options=[('MSS', destination_mss_value)])
                 last_ack = (victim_ether / victim_ip / last_ack_tcp)
                 last_ack = (victim_ether / victim_ip / last_ack_tcp)
                 last_ack.time = timestamp_next_pkt
                 last_ack.time = timestamp_next_pkt

+ 0 - 29
code/Attack/SMBScanAttack.py

@@ -94,35 +94,6 @@ class SMBScanAttack(BaseAttack.BaseAttack):
         self.add_param_value(Param.IP_DESTINATION_END, "0.0.0.0")
         self.add_param_value(Param.IP_DESTINATION_END, "0.0.0.0")
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps, delay=0):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            if delay == 0:
-                # Calculate request timestamp
-                # To imitate the bursty behavior of traffic
-                randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-                return timestamp + uniform(1/pps ,  randomdelay.random())
-            else:
-                # Calculate reply timestamp
-                randomdelay = Lea.fromValFreqsDict({2*delay: 70, 3*delay: 20, 5*delay: 7, 10*delay: 3})
-                return timestamp + uniform(1 / pps + delay,  1 / pps + randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) for a specific time interval.
-
-            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
-            :param timestamp: the timestamp at which the packet rate is required.
-            :return: the corresponding packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp<=row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
-
         def get_ip_data(ip_address: str):
         def get_ip_data(ip_address: str):
             """
             """
             Gets the MSS, TTL and Windows Size values of a given IP
             Gets the MSS, TTL and Windows Size values of a given IP

+ 1 - 22
code/Attack/SQLiAttack.py

@@ -11,6 +11,7 @@ logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 # noinspection PyPep8
 from scapy.utils import RawPcapReader
 from scapy.utils import RawPcapReader
 from scapy.layers.inet import IP, Ether, TCP, RandShort
 from scapy.layers.inet import IP, Ether, TCP, RandShort
+from ID2TLib.Utility import *
 
 
 
 
 class SQLiAttack(BaseAttack.BaseAttack):
 class SQLiAttack(BaseAttack.BaseAttack):
@@ -79,28 +80,6 @@ class SQLiAttack(BaseAttack.BaseAttack):
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            # Calculate the request timestamp
-            # A distribution to imitate the bursty behavior of traffic
-            randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-            return timestamp + uniform(1 / pps, randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1]  # in case the timstamp > capture max timestamp
-
         # Timestamp
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         pps = self.get_param_value(Param.PACKETS_PER_SECOND)
         pps = self.get_param_value(Param.PACKETS_PER_SECOND)

+ 1 - 21
code/Attack/SalityBotnet.py

@@ -11,6 +11,7 @@ logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
 # noinspection PyPep8
 # noinspection PyPep8
 from scapy.utils import RawPcapReader
 from scapy.utils import RawPcapReader
 from scapy.layers.inet import IP, Ether, TCP, RandShort
 from scapy.layers.inet import IP, Ether, TCP, RandShort
+from ID2TLib.Utility import *
 
 
 
 
 class SalityBotnet(BaseAttack.BaseAttack):
 class SalityBotnet(BaseAttack.BaseAttack):
@@ -57,27 +58,6 @@ class SalityBotnet(BaseAttack.BaseAttack):
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
                               self.statistics.get_pps_received(most_used_ip_address)) / 2)
 
 
     def generate_attack_pcap(self):
     def generate_attack_pcap(self):
-        def update_timestamp(timestamp, pps):
-            """
-            Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
-
-            :return: Timestamp to be used for the next packet.
-            """
-            # Calculate the request timestamp
-            # A distribution to imitate the bursty behavior of traffic
-            randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
-            return timestamp + uniform(1 / pps, randomdelay.random())
-
-        def getIntervalPPS(complement_interval_pps, timestamp):
-            """
-            Gets the packet rate (pps) in specific time interval.
-
-            :return: the corresponding packet rate for packet rate (pps) .
-            """
-            for row in complement_interval_pps:
-                if timestamp <= row[0]:
-                    return row[1]
-            return complement_interval_pps[-1][1]  # in case the timstamp > capture max timestamp
 
 
         # Timestamp
         # Timestamp
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
         timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)

+ 56 - 2
code/ID2TLib/Utility.py

@@ -1,4 +1,6 @@
-from random import randint
+import logging
+
+from random import randint, uniform
 from datetime import datetime, timedelta, tzinfo
 from datetime import datetime, timedelta, tzinfo
 from calendar import timegm
 from calendar import timegm
 
 
@@ -9,6 +11,58 @@ from scapy.layers.netbios import *
 platforms = {"win7", "win10", "winxp", "win8.1", "macos", "linux", "win8", "winvista", "winnt", "win2000"}
 platforms = {"win7", "win10", "winxp", "win8.1", "macos", "linux", "win8", "winvista", "winnt", "win2000"}
 
 
 
 
+def update_timestamp(timestamp, pps, delay=0):
+    """
+    Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
+
+    :return: Timestamp to be used for the next packet.
+    """
+    if delay == 0:
+        # Calculate request timestamp
+        # To imitate the bursty behavior of traffic
+        randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
+        return timestamp + uniform(1 / pps, randomdelay.random())
+    else:
+        # Calculate reply timestamp
+        randomdelay = Lea.fromValFreqsDict({2 * delay: 70, 3 * delay: 20, 5 * delay: 7, 10 * delay: 3})
+        return timestamp + uniform(1 / pps + delay, 1 / pps + randomdelay.random())
+
+
+def getIntervalPPS(complement_interval_pps, timestamp):
+            """
+            Gets the packet rate (pps) for a specific time interval.
+
+            :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
+            :param timestamp: the timestamp at which the packet rate is required.
+            :return: the corresponding packet rate (pps) .
+            """
+            for row in complement_interval_pps:
+                if timestamp<=row[0]:
+                    return row[1]
+            return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
+
+
+def get_nth_random_element(*element_list):
+            """
+            Returns the n-th element of every list from an arbitrary number of given lists.
+            For example, list1 contains IP addresses, list 2 contains MAC addresses. Use of this function ensures that
+            the n-th IP address uses always the n-th MAC address.
+            :param element_list: An arbitrary number of lists.
+            :return: A tuple of the n-th element of every list.
+            """
+            range_max = min([len(x) for x in element_list])
+            if range_max > 0: range_max -= 1
+            n = randint(0, range_max)
+            return tuple(x[n] for x in element_list)
+
+
+def index_increment(number: int, max: int):
+            if number + 1 < max:
+                return number + 1
+            else:
+                return 0
+
+
 def get_rnd_os():
 def get_rnd_os():
     """
     """
     Chooses random platform over an operating system probability distribution
     Chooses random platform over an operating system probability distribution
@@ -113,4 +167,4 @@ def get_rnd_boot_time(timestamp, platform="winxp"):
         uptime_in_days = Lea.fromValFreqsDict({3: 50, 7: 25, 14: 12.5, 31: 6.25, 92: 3.125, 183: 1.5625,
         uptime_in_days = Lea.fromValFreqsDict({3: 50, 7: 25, 14: 12.5, 31: 6.25, 92: 3.125, 183: 1.5625,
                                                365: 0.78125, 1461: 0.78125})
                                                365: 0.78125, 1461: 0.78125})
     timestamp -= randint(0, uptime_in_days.random()*86400)
     timestamp -= randint(0, uptime_in_days.random()*86400)
-    return timestamp
+    return timestamp