Example #1
0
    def get_ip_data(self, ip_address: str):
        """
        :param ip_address: the ip of which (packet-)data shall be returned
        :return: MSS, TTL and Window Size values of the given IP
        """
        # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
        mss_dist = self.statistics.get_mss_distribution(ip_address)
        if len(mss_dist) > 0:
            mss_prob_dict = lea.Lea.fromValFreqsDict(mss_dist)
            mss_value = mss_prob_dict.random()
        else:
            mss_value = Util.handle_most_used_outputs(self.most_used_mss_value)

        # Set TTL based on TTL distribution of IP address
        ttl_dist = self.statistics.get_ttl_distribution(ip_address)
        if len(ttl_dist) > 0:
            ttl_prob_dict = lea.Lea.fromValFreqsDict(ttl_dist)
            ttl_value = ttl_prob_dict.random()
        else:
            ttl_value = Util.handle_most_used_outputs(self.most_used_ttl_value)

        # Set Window Size based on Window Size distribution of IP address
        win_dist = self.statistics.get_win_distribution(ip_address)
        if len(win_dist) > 0:
            win_prob_dict = lea.Lea.fromValFreqsDict(win_dist)
            win_value = win_prob_dict.random()
        else:
            win_value = Util.handle_most_used_outputs(self.most_used_win_size)

        return mss_value, ttl_value, win_value
Example #2
0
def get_smb_platform_data(platform: str, timestamp: float):
    """
    Gets platform-dependent data for SMB 2 packets

    :param platform: the platform for which to get SMB 2 packet data
    :param timestamp: a timestamp for calculating the boot-time
    :return: server_guid, security_blob, capabilities, data_size and server_start_time of the given platform
    """
    Util.check_platform(platform)
    if platform == "linux":
        server_guid = "ubuntu"
        security_blob = security_blob_ubuntu
        capabilities = 0x5
        data_size = 0x800000
        server_start_time = 0
    elif platform == "macos":
        server_guid = binascii.b2a_hex(os.urandom(15)).decode()
        security_blob = security_blob_macos
        capabilities = 0x6
        data_size = 0x400000
        server_start_time = 0
    else:
        server_guid = binascii.b2a_hex(os.urandom(15)).decode()
        security_blob = security_blob_windows
        capabilities = 0x7
        data_size = 0x100000
        server_start_time = Util.get_filetime_format(
            Util.get_rnd_boot_time(timestamp))
    return server_guid, security_blob, capabilities, data_size, server_start_time
Example #3
0
def get_smb_version(platform: str):
    """
    Returns SMB version based on given platform

    :param platform: the platform as string
    :return: SMB version as string
    """
    Util.check_platform(platform)
    if platform is "linux":
        return rnd.choice(list(smb_versions_per_samba.values()))
    elif platform is "macos":
        return "2.1"
    else:
        return smb_versions_per_win[platform]
Example #4
0
 def test_get_rnd_x86_nop_with_sideeffects(self):
     result = Utility.get_rnd_x86_nop(1000, False)
     for i in range(0, len(result)):
         with self.subTest(i=i):
             self.assertTrue(
                 result[i].to_bytes(1, "little") in Utility.x86_nops or
                 result[i].to_bytes(1, "little") in Utility.x86_pseudo_nops)
Example #5
0
    def init_params(self):
        """
        Initialize the parameters of this attack using the user supplied command line parameters.
        Use the provided statistics to calculate default parameters and to process user
        supplied queries.
        """

        # PARAMETERS: initialize with default values
        # (values are overwritten if user specifies them)
        most_used_ip_address = self.statistics.get_most_used_ip_address()

        # The most used IP class in background traffic
        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
        num_attackers = rnd.randint(1, 16)
        source_ip = self.generate_random_ipv4_address(most_used_ip_class, num_attackers)

        self.add_param_value(atkParam.Parameter.IP_SOURCE, source_ip)
        self.add_param_value(atkParam.Parameter.MAC_SOURCE, self.generate_random_mac_address(num_attackers))

        random_ip_address = self.statistics.get_random_ip_address()
        # ip-dst should be valid and not equal to ip.src
        while not self.is_valid_ip_address(random_ip_address) or random_ip_address == source_ip:
            random_ip_address = self.statistics.get_random_ip_address()

        self.add_param_value(atkParam.Parameter.IP_DESTINATION, 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(atkParam.Parameter.MAC_DESTINATION, destination_mac)
        self.add_param_value(atkParam.Parameter.PACKETS_PER_SECOND,
                             (self.statistics.get_pps_sent(most_used_ip_address) +
                              self.statistics.get_pps_received(most_used_ip_address)) / 2)
        self.add_param_value(atkParam.Parameter.INJECT_AFTER_PACKET, rnd.randint(0, self.statistics.get_packet_count()))
        self.add_param_value(atkParam.Parameter.ATTACK_DURATION, 30)
Example #6
0
    def init_params(self):
        """
        Initialize the parameters of this attack using the user supplied command line parameters.
        Use the provided statistics to calculate default parameters and to process user
        supplied queries.
        """
        # PARAMETERS: initialize with default values
        # (values are overwritten if user specifies them)
        self.add_param_value(atkParam.Parameter.INJECT_AFTER_PACKET, rnd.randint(0, self.statistics.get_packet_count()))
        # attacker configuration
        num_attackers = rnd.randint(1, 16)
        # The most used IP class in background traffic
        most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())

        self.add_param_value(atkParam.Parameter.IP_SOURCE,
                             self.generate_random_ipv4_address(most_used_ip_class, num_attackers))
        self.add_param_value(atkParam.Parameter.MAC_SOURCE, self.generate_random_mac_address(num_attackers))
        self.default_port = int(inet.RandShort())
        self.add_param_value(atkParam.Parameter.PORT_SOURCE, self.default_port)
        self.add_param_value(atkParam.Parameter.PACKETS_PER_SECOND, 0)
        self.add_param_value(atkParam.Parameter.ATTACK_DURATION, rnd.randint(5, 30))

        # victim configuration
        random_ip_address = self.statistics.get_random_ip_address()
        self.add_param_value(atkParam.Parameter.IP_DESTINATION, 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(atkParam.Parameter.MAC_DESTINATION, destination_mac)
        self.add_param_value(atkParam.Parameter.VICTIM_BUFFER, rnd.randint(1000, 10000))

        self.add_param_value(atkParam.Parameter.BANDWIDTH_MAX, 0)
        self.add_param_value(atkParam.Parameter.BANDWIDTH_MIN_LOCAL, 0)
        self.add_param_value(atkParam.Parameter.BANDWIDTH_MIN_PUBLIC, 0)
        self.add_param_value(atkParam.Parameter.LATENCY_MAX, 0)
Example #7
0
    def init_params(self):
        """
        Initialize the parameters of this attack using the user supplied command line parameters.
        Use the provided statistics to calculate default parameters and to process user
        supplied queries.
        """

        # PARAMETERS: initialize with default values
        # (values are overwritten if user specifies them)
        most_used_ip_address = self.statistics.get_most_used_ip_address()

        self.add_param_value(atkParam.Parameter.IP_SOURCE,
                             most_used_ip_address)
        self.add_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE, 'False')
        self.add_param_value(
            atkParam.Parameter.MAC_SOURCE,
            self.statistics.get_mac_address(most_used_ip_address))

        self.add_param_value(atkParam.Parameter.TARGET_COUNT, 200)
        self.add_param_value(atkParam.Parameter.IP_DESTINATION, "1.1.1.1")

        self.add_param_value(atkParam.Parameter.PORT_SOURCE,
                             rnd.randint(1024, 65535))
        self.add_param_value(atkParam.Parameter.PORT_SOURCE_RANDOMIZE, 'True')
        self.add_param_value(
            atkParam.Parameter.PACKETS_PER_SECOND,
            (self.statistics.get_pps_sent(most_used_ip_address) +
             self.statistics.get_pps_received(most_used_ip_address)) / 2)

        self.add_param_value(
            atkParam.Parameter.INJECT_AFTER_PACKET,
            rnd.randint(0, self.statistics.get_packet_count()))
        start = Util.get_timestamp_from_datetime_str(
            self.statistics.get_pcap_timestamp_start())
        end = Util.get_timestamp_from_datetime_str(
            self.statistics.get_pcap_timestamp_end())
        self.add_param_value(atkParam.Parameter.INJECT_AT_TIMESTAMP,
                             (start + end) / 2)
        self.add_param_value(atkParam.Parameter.INJECT_PPS, 0)

        self.add_param_value(atkParam.Parameter.HOSTING_PERCENTAGE, 0.5)
        self.add_param_value(atkParam.Parameter.HOSTING_IP, "1.1.1.1")
        self.add_param_value(atkParam.Parameter.HOSTING_VERSION,
                             SMBLib.get_smb_version(platform=self.host_os))
        self.add_param_value(atkParam.Parameter.SOURCE_PLATFORM,
                             Util.get_rnd_os())
        self.add_param_value(atkParam.Parameter.PROTOCOL_VERSION, "1")
Example #8
0
 def test_get_ip_range_backwards(self):
     end = "192.168.178.254"
     start = "192.168.179.1"
     result = [
         "192.168.179.1", "192.168.179.0", "192.168.178.255",
         "192.168.178.254"
     ]
     self.assertEqual(Utility.get_ip_range(start, end), result)
Example #9
0
 def test_get_rnd_x86_nop_without_sideeffects(self):
     result = Utility.get_rnd_x86_nop(1000, True)
     for i in range(0, len(result)):
         with self.subTest(i=i):
             self.assertIn(result[i].to_bytes(1, "little"),
                           Utility.x86_nops)
             self.assertNotIn(result[i].to_bytes(1, "little"),
                              Utility.x86_pseudo_nops)
Example #10
0
    def generate_attack_packets(self) -> None:
        ip_attacker = self.get_param_value(atkParam.Parameter.IP_SOURCE)
        mac_attacker = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        ip_amplifier = self.get_param_value(atkParam.Parameter.IP_DESTINATION)
        mac_amplifier = self.get_param_value(
            atkParam.Parameter.MAC_DESTINATION)
        ip_victim = self.get_param_value(atkParam.Parameter.IP_VICTIM)

        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)

        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        self.attack_start_utime = timestamp_next_pkt

        attack_duration = self.get_param_value(
            atkParam.Parameter.ATTACK_DURATION)
        attack_ends_time = timestamp_next_pkt + attack_duration

        _, src_ttl, _ = self.get_ip_data(ip_attacker)
        sport = Util.generate_source_port_from_platform('linux')

        # Use MAC of the actual source, but the IP of the victim
        attacker_ether = inet.Ether(src=mac_attacker, dst=mac_amplifier)
        attacker_ip = inet.IP(src=ip_victim,
                              dst=ip_amplifier,
                              ttl=src_ttl,
                              flags='DF')

        while timestamp_next_pkt <= attack_ends_time:
            request_udp = inet.UDP(sport=sport, dport=Memcd.memcached_port)
            request_memcd = Memcd.Memcached_Request(Request=b'stats\r\n',
                                                    RequestID=inet.RandShort())
            request = (attacker_ether / attacker_ip / request_udp /
                       request_memcd)
            request.time = timestamp_next_pkt

            self.packets.append(request)

            timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
Example #11
0
    def __init__(self):
        """
        Creates a new instance of the SMBScanAttack.
        This Attack injects TCP Syn Requests to the port 445 of several ips and related response into the output
        pcap file.
        If port 445 is open, it will simulate and inject the SMB Protocol Negotiation too.
        """
        # Initialize attack
        super(SMBScanAttack,
              self).__init__("SmbScan Attack", "Injects an SMB scan",
                             "Scanning/Probing")

        self.host_os = Util.get_rnd_os()

        # Define allowed parameters and their type
        self.supported_params.update({
            atkParam.Parameter.IP_SOURCE:
            atkParam.ParameterTypes.TYPE_IP_ADDRESS,
            atkParam.Parameter.IP_DESTINATION:
            atkParam.ParameterTypes.TYPE_IP_ADDRESS,
            atkParam.Parameter.TARGET_COUNT:
            atkParam.ParameterTypes.TYPE_INTEGER_POSITIVE,
            atkParam.Parameter.HOSTING_PERCENTAGE:
            atkParam.ParameterTypes.TYPE_PERCENTAGE,
            atkParam.Parameter.PORT_SOURCE:
            atkParam.ParameterTypes.TYPE_PORT,
            atkParam.Parameter.MAC_SOURCE:
            atkParam.ParameterTypes.TYPE_MAC_ADDRESS,
            atkParam.Parameter.INJECT_AT_TIMESTAMP:
            atkParam.ParameterTypes.TYPE_FLOAT,
            atkParam.Parameter.INJECT_AFTER_PACKET:
            atkParam.ParameterTypes.TYPE_PACKET_POSITION,
            atkParam.Parameter.IP_SOURCE_RANDOMIZE:
            atkParam.ParameterTypes.TYPE_BOOLEAN,
            atkParam.Parameter.PACKETS_PER_SECOND:
            atkParam.ParameterTypes.TYPE_FLOAT,
            atkParam.Parameter.INJECT_PPS:
            atkParam.ParameterTypes.TYPE_FLOAT,
            atkParam.Parameter.PORT_SOURCE_RANDOMIZE:
            atkParam.ParameterTypes.TYPE_BOOLEAN,
            atkParam.Parameter.HOSTING_IP:
            atkParam.ParameterTypes.TYPE_IP_ADDRESS,
            atkParam.Parameter.HOSTING_VERSION:
            atkParam.ParameterTypes.TYPE_STRING,
            atkParam.Parameter.SOURCE_PLATFORM:
            atkParam.ParameterTypes.TYPE_STRING,
            atkParam.Parameter.PROTOCOL_VERSION:
            atkParam.ParameterTypes.TYPE_STRING
        })
Example #12
0
    def choose_attack(input_name):
        """"
        Finds the attack best matching to input_name

        :param input_name: The name of the attack the user put in
        :return: The best matching attack in case one was found
        """

        import Attack

        # Find all attacks, exclude some classes
        package = Attack
        available_attacks = []
        for _, name, __ in pkgutil.iter_modules(package.__path__):
            if name != 'BaseAttack' and name != 'AttackParameters':
                available_attacks.append(name)

        highest_sim = 0.0
        highest_sim_attack = None
        for attack in available_attacks:
            # Check if attack name is accurate
            if input_name == attack:
                return attack
            # Compares input with one of the available attacks
            # Makes comparison with lowercase version with generic endings removed
            # List of generic attack name endings can be found in ID2TLib.Utility
            counter_check = attack.lower()
            if not any(ending in input_name for ending in Util.generic_attack_names):
                counter_check = Util.remove_generic_ending(counter_check)
            similarity = difflib.SequenceMatcher(None, input_name.lower(), counter_check).ratio()
            # Exact match, return appropriate attack name
            if similarity == 1.0:
                return attack
            # Found more likely match
            if similarity > highest_sim:
                highest_sim = similarity
                highest_sim_attack = attack

        # Found no exactly matching attack name, print best match and exit
        if highest_sim >= 0.6:
            print('Found no attack of name ' + input_name + '. The closest match was ' + highest_sim_attack +
                  '.  Use ./id2t -l for a list of available attacks.')
            exit(1)
        # Found no reasonably matching attack name, recommend -l and exit
        else:
            print('Found no attack of name ' + input_name + ' or one similar to it.'
                                                            ' Use ./id2t -l for an overview of available attacks.')
            exit(1)
Example #13
0
    def get_reply_latency(self,
                          ip_src,
                          ip_dst,
                          default: int = 0,
                          mode: str = None):
        """
        Gets the minimum and the maximum reply latency for all the connections of a specific IP.

        :param ip_src: The source IP for which to retrieve the reply latency.
        :param ip_dst: The destination IP for which to retrieve the reply latency.
        :param default: The default value to return if no latency could be calculated.
        :param mode: either "local" or "public"
        :return minimum and maximum latency
        """
        if not mode:
            mode = Util.get_network_mode(ip_src, ip_dst)
        minimum = {"local": 900, "public": 3000}

        if default != 0:
            minimum[mode] = default

        result = self.statistics.process_db_query\
                ("SELECT minLatency, maxLatency FROM ip_statistics WHERE ipAddress in ('{0}, {1}');".
                 format(ip_src, ip_dst))

        min_latency = minimum[mode]
        max_latency = minimum[mode]

        for ip in result:
            # retrieve minimum latency
            if ip[0]:
                retrieved = ip[0]
            else:
                retrieved = np.median(self.all_min_latencies)
            min_latency = min(min_latency, retrieved)

            # retrieve maximum latency
            if ip[1]:
                retrieved = ip[1]
            else:
                retrieved = np.median(self.all_max_latencies)
            max_latency = min(max_latency, retrieved)

        min_latency = int(
            min_latency) * 10**-6  # convert from micro to seconds
        max_latency = int(max_latency) * 10**-6
        return min_latency, max_latency
Example #14
0
    def get_remaining_bandwidth(self,
                                timestamp: int = 0,
                                ip_src: str = "",
                                ip_dst: str = "",
                                custom_max_bandwidth: float = 0,
                                custom_bandwidth_local: float = 0,
                                custom_bandwidth_public: float = 0):
        """
        This function calculates the remaining bandwidth based on the maximum bandwidth available and the kbytes already
        sent inside the interval corresponding to the timestamp given.

        !!! custom_max_bandwidth is mutually exclusive to custom_bandwidth_local and/or custom_bandwidth_public
        :param timestamp: the timestamp of the current packet
        :param ip_src: the source IP
        :param ip_dst: the destination IP
        :param custom_max_bandwidth: maximum bandwidth to be set as a hard limit, discarding the pcaps bandwidth
        :param custom_bandwidth_local: bandwidth minimum for local traffic
        :param custom_bandwidth_public: bandwidth minimum for public traffic
        :return: the remaining bandwidth in kbyte/s
        """
        mode = Util.get_network_mode(ip_src, ip_dst)

        if custom_max_bandwidth != 0:
            bandwidth = custom_max_bandwidth
        else:
            bandwidth = self.statistics.get_kbyte_rate(
                mode, custom_bandwidth_local, custom_bandwidth_public)

        remaining_bandwidth = bandwidth

        current_table = self.statistics.stats_db.get_current_interval_statistics_table(
        )
        kbytes_sent, interval = self.statistics.get_interval_stat(
            table_name=current_table, field="kbytes", timestamp=timestamp)
        if not kbytes_sent:
            kbytes_sent = 0
        kbytes_sent = kbytes_sent

        duration = self.statistics.get_current_interval_len()
        used_bandwidth = float((kbytes_sent * 1000) / duration)
        remaining_bandwidth -= used_bandwidth
        return remaining_bandwidth, interval
Example #15
0
    def init_params(self):
        """
        Initialize the parameters of this attack using the user supplied command line parameters.
        Use the provided statistics to calculate default parameters and to process user
        supplied queries.

        """
        # PARAMETERS: initialize with default values
        # (values are overwritten if user specifies them)
        most_used_ip_address = self.statistics.get_most_used_ip_address()

        # The most used IP class in background traffic
        most_used_ip_class = Util.handle_most_used_outputs(
            self.statistics.get_most_used_ip_class())
        attacker_ip = self.generate_random_ipv4_address(most_used_ip_class)
        self.add_param_value(atkParam.Parameter.IP_DESTINATION, attacker_ip)
        self.add_param_value(atkParam.Parameter.MAC_DESTINATION,
                             self.generate_random_mac_address())

        random_ip_address = self.statistics.get_random_ip_address()
        # victim should be valid and not equal to attacker
        while not self.is_valid_ip_address(
                random_ip_address) or random_ip_address == attacker_ip:
            random_ip_address = self.statistics.get_random_ip_address()

        self.add_param_value(atkParam.Parameter.IP_SOURCE, random_ip_address)
        victim_mac = self.statistics.get_mac_address(random_ip_address)
        if isinstance(victim_mac, list) and len(victim_mac) == 0:
            victim_mac = self.generate_random_mac_address()
        self.add_param_value(atkParam.Parameter.MAC_SOURCE, victim_mac)
        self.add_param_value(
            atkParam.Parameter.PACKETS_PER_SECOND,
            (self.statistics.get_pps_sent(most_used_ip_address) +
             self.statistics.get_pps_received(most_used_ip_address)) / 2)
        self.add_param_value(
            atkParam.Parameter.INJECT_AFTER_PACKET,
            rnd.randint(0, self.statistics.get_packet_count()))
        self.add_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE, 'False')
        self.add_param_value(atkParam.Parameter.CUSTOM_PAYLOAD, '')
        self.add_param_value(atkParam.Parameter.CUSTOM_PAYLOAD_FILE, '')
Example #16
0
        def append_ips(
                ip_address_input: t.List[str]) -> t.Tuple[bool, t.List[str]]:
            """
            Recursive appending function to handle lists and ranges of IP addresses.

            :param ip_address_input: The IP address(es) as list of strings, comma-separated or dash-separated string.
            :return: List of all given IP addresses.
            """
            ip_list = []
            is_valid = True
            for ip in ip_address_input:
                if '-' in ip:
                    ip_range = ip.split('-')
                    ip_range = Util.get_ip_range(ip_range[0], ip_range[1])
                    is_valid, ips = append_ips(ip_range)
                    ip_list.extend(ips)
                else:
                    try:
                        ipaddress.ip_address(ip)
                        ip_list.append(ip)
                    except ValueError:
                        return False, ip_list
            return is_valid, ip_list
Example #17
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)

        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        # store start time of attack
        self.attack_start_utime = timestamp_next_pkt

        # Initialize parameters
        ip_victim = self.get_param_value(atkParam.Parameter.IP_SOURCE)
        ip_attacker = self.get_param_value(atkParam.Parameter.IP_DESTINATION)
        mac_victim = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        mac_attacker = self.get_param_value(atkParam.Parameter.MAC_DESTINATION)

        custom_payload = self.get_param_value(
            atkParam.Parameter.CUSTOM_PAYLOAD)
        custom_payload_len = len(custom_payload)
        custom_payload_limit = 1000
        Util.check_payload_len(custom_payload_len, custom_payload_limit)

        self.packets = []

        # Create random victim if specified
        if self.get_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE):
            # The most used IP class in background traffic
            most_used_ip_class = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ip_class())
            ip_victim = self.generate_random_ipv4_address(
                most_used_ip_class, 1)
            mac_victim = self.generate_random_mac_address()

        # Get MSS, TTL and Window size value for victim/attacker IP
        victim_mss_value, victim_ttl_value, victim_win_value = self.get_ip_data(
            ip_victim)
        attacker_mss_value, attacker_ttl_value, attacker_win_value = self.get_ip_data(
            ip_attacker)

        min_delay, max_delay = self.get_reply_delay(ip_attacker)

        attacker_seq = rnd.randint(1000, 50000)
        victim_seq = rnd.randint(1000, 50000)

        sport = Util.generate_source_port_from_platform("win7")

        # connection request from victim (client)
        victim_ether = inet.Ether(src=mac_victim, dst=mac_attacker)
        victim_ip = inet.IP(src=ip_victim,
                            dst=ip_attacker,
                            ttl=victim_ttl_value,
                            flags='DF')
        request_tcp = inet.TCP(sport=sport,
                               dport=ftp_port,
                               window=victim_win_value,
                               flags='S',
                               seq=victim_seq,
                               options=[('MSS', victim_mss_value)])
        victim_seq += 1
        syn = (victim_ether / victim_ip / request_tcp)
        syn.time = timestamp_next_pkt
        timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps,
                                                   min_delay)
        self.packets.append(syn)

        # response from attacker (server)
        attacker_ether = inet.Ether(src=mac_attacker, dst=mac_victim)
        attacker_ip = inet.IP(src=ip_attacker,
                              dst=ip_victim,
                              ttl=attacker_ttl_value,
                              flags='DF')
        reply_tcp = inet.TCP(sport=ftp_port,
                             dport=sport,
                             seq=attacker_seq,
                             ack=victim_seq,
                             flags='SA',
                             window=attacker_win_value,
                             options=[('MSS', attacker_mss_value)])
        attacker_seq += 1
        synack = (attacker_ether / attacker_ip / reply_tcp)
        synack.time = timestamp_next_pkt
        timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps,
                                                   min_delay)
        self.packets.append(synack)

        # acknowledgement from victim (client)
        ack_tcp = inet.TCP(sport=sport,
                           dport=ftp_port,
                           seq=victim_seq,
                           ack=attacker_seq,
                           flags='A',
                           window=victim_win_value,
                           options=[('MSS', victim_mss_value)])
        ack = (victim_ether / victim_ip / ack_tcp)
        ack.time = timestamp_next_pkt
        timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
        self.packets.append(ack)

        # FTP exploit packet
        ftp_tcp = inet.TCP(sport=ftp_port,
                           dport=sport,
                           seq=attacker_seq,
                           ack=victim_seq,
                           flags='PA',
                           window=attacker_win_value,
                           options=[('MSS', attacker_mss_value)])

        characters = b'220'
        characters += Util.get_rnd_bytes(2065, Util.forbidden_chars)
        characters += b'\x96\x72\x01\x68'
        characters += Util.get_rnd_x86_nop(10, False, Util.forbidden_chars)

        custom_payload_file = self.get_param_value(
            atkParam.Parameter.CUSTOM_PAYLOAD_FILE)

        # Generation of payload of the FTP exploit packet
        if custom_payload == '':
            if custom_payload_file == '':
                payload = Util.get_rnd_bytes(custom_payload_limit,
                                             Util.forbidden_chars)
            else:
                payload = ID2TLib.Utility.get_bytes_from_file(
                    custom_payload_file)
                Util.check_payload_len(len(payload), custom_payload_limit)
                payload += Util.get_rnd_x86_nop(
                    custom_payload_limit - len(payload), False,
                    Util.forbidden_chars)
        else:
            encoded_payload = custom_payload.encode()
            payload = Util.get_rnd_x86_nop(
                custom_payload_limit - custom_payload_len, False,
                Util.forbidden_chars)
            payload += encoded_payload

        characters += payload
        characters += Util.get_rnd_x86_nop(20, False, Util.forbidden_chars)
        characters += b'\r\n'

        ftp_tcp.add_payload(characters)

        ftp_buff = (attacker_ether / attacker_ip / ftp_tcp)
        ftp_buff.time = timestamp_next_pkt
        timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
        self.packets.append(ftp_buff)
        attacker_seq += len(ftp_tcp.payload)

        # Fin Ack from attacker
        fin_ack_tcp = inet.TCP(sport=ftp_port,
                               dport=sport,
                               seq=attacker_seq,
                               ack=victim_seq,
                               flags='FA',
                               window=attacker_win_value,
                               options=[('MSS', attacker_mss_value)])

        fin_ack = (attacker_ether / attacker_ip / fin_ack_tcp)
        fin_ack.time = timestamp_next_pkt
        timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps,
                                                   min_delay)
        self.packets.append(fin_ack)

        # Ack from victim on FTP packet
        ftp_ack_tcp = inet.TCP(sport=sport,
                               dport=ftp_port,
                               seq=victim_seq,
                               ack=attacker_seq,
                               flags='A',
                               window=victim_win_value,
                               options=[('MSS', victim_mss_value)])
        ftp_ack = (victim_ether / victim_ip / ftp_ack_tcp)
        ftp_ack.time = timestamp_next_pkt
        timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
        self.packets.append(ftp_ack)

        # Ack from victim on Fin/Ack of attacker
        fin_ack_ack_tcp = inet.TCP(sport=sport,
                                   dport=ftp_port,
                                   seq=victim_seq,
                                   ack=attacker_seq + 1,
                                   flags='A',
                                   window=victim_win_value,
                                   options=[('MSS', victim_mss_value)])
        fin_ack_ack = (victim_ether / victim_ip / fin_ack_ack_tcp)
        fin_ack_ack.time = timestamp_next_pkt
        self.packets.append(fin_ack_ack)
Example #18
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        buffer_size = 1000

        # Determine source IP and MAC address
        num_attackers = self.get_param_value(
            atkParam.Parameter.NUMBER_ATTACKERS)
        if (num_attackers is not None) and (num_attackers is not 0):
            # user supplied atkParam.Parameter.NUMBER_ATTACKERS
            # The most used IP class in background traffic
            most_used_ip_class = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ip_class())
            # Create random attackers based on user input atkParam.Parameter.NUMBER_ATTACKERS
            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 atkParam.Parameter.NUMBER_ATTACKS
            # use default values for IP_SOURCE/MAC_SOURCE or overwritten values
            # if user supplied any values for those params
            ip_source_list = self.get_param_value(atkParam.Parameter.IP_SOURCE)
            mac_source_list = self.get_param_value(
                atkParam.Parameter.MAC_SOURCE)

        # Make sure IPs and MACs are lists
        if not isinstance(ip_source_list, list):
            ip_source_list = [ip_source_list]

        if not isinstance(mac_source_list, list):
            mac_source_list = [mac_source_list]

        # Generate MACs for each IP that has no corresponding MAC yet
        if (num_attackers is None) or (num_attackers is 0):
            if len(ip_source_list) > len(mac_source_list):
                mac_source_list.extend(
                    self.generate_random_mac_address(
                        len(ip_source_list) - len(mac_source_list)))
            num_attackers = min(len(ip_source_list), len(mac_source_list))

        # Initialize parameters
        self.packets = col.deque(maxlen=buffer_size)

        port_source_list = self.get_param_value(atkParam.Parameter.PORT_SOURCE)
        if not isinstance(port_source_list, list):
            port_source_list = [port_source_list]
        mac_destination = self.get_param_value(
            atkParam.Parameter.MAC_DESTINATION)
        ip_destination = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)

        most_used_ip_address = self.statistics.get_most_used_ip_address()
        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)
        if pps == 0:
            result = self.statistics.process_db_query(
                "SELECT MAX(maxPktRate) FROM ip_statistics WHERE ipAddress='" +
                ip_destination + "';")
            if result is not None and not 0:
                pps = num_attackers * result
            else:
                result = self.statistics.process_db_query(
                    "SELECT MAX(maxPktRate) FROM ip_statistics WHERE ipAddress='"
                    + most_used_ip_address + "';")
                pps = num_attackers * result

        # Calculate complement packet rates of the background traffic for each interval
        attacker_pps = pps / num_attackers
        complement_interval_attacker_pps = self.statistics.calculate_complement_packet_rates(
            attacker_pps)

        # Check ip.src == ip.dst
        self.ip_src_dst_equal_check(ip_source_list, ip_destination)

        port_destination = self.get_param_value(
            atkParam.Parameter.PORT_DESTINATION)
        if not port_destination:  # user did not define port_dest
            port_destination = self.statistics.process_db_query(
                "SELECT portNumber FROM ip_ports WHERE portDirection='in' AND ipAddress='"
                + ip_destination +
                "' AND portCount==(SELECT MAX(portCount) FROM ip_ports WHERE portDirection='in' AND ipAddress='"
                + ip_destination + "');")
        if not port_destination:  # no port was retrieved
            port_destination = self.statistics.process_db_query(
                "SELECT portNumber FROM (SELECT portNumber, SUM(portCount) as occ FROM ip_ports WHERE "
                "portDirection='in' GROUP BY portNumber ORDER BY occ DESC) WHERE occ=(SELECT SUM(portCount) "
                "FROM ip_ports WHERE portDirection='in' GROUP BY portNumber ORDER BY SUM(portCount) DESC LIMIT 1);"
            )
        if not port_destination:
            port_destination = max(1, int(inet.RandShort()))

        port_destination = Util.handle_most_used_outputs(port_destination)

        self.path_attack_pcap = None

        min_delay, max_delay = self.get_reply_delay(ip_destination)
        victim_buffer = self.get_param_value(atkParam.Parameter.VICTIM_BUFFER)

        attack_duration = self.get_param_value(
            atkParam.Parameter.ATTACK_DURATION)
        pkts_num = int(pps * attack_duration)

        source_win_sizes = self.statistics.get_rnd_win_size(pkts_num)

        destination_win_dist = self.statistics.get_win_distribution(
            ip_destination)
        if len(destination_win_dist) > 0:
            destination_win_prob_dict = lea.Lea.fromValFreqsDict(
                destination_win_dist)
            destination_win_value = destination_win_prob_dict.random()
        else:
            destination_win_value = self.statistics.get_most_used_win_size()

        destination_win_value = Util.handle_most_used_outputs(
            destination_win_value)

        # MSS that was used by IP destination in background traffic
        mss_dst = self.statistics.get_most_used_mss(ip_destination)
        if mss_dst is None:
            mss_dst = self.statistics.get_most_used_mss_value()

        mss_dst = Util.handle_most_used_outputs(mss_dst)

        # Stores triples of (timestamp, source_id, destination_id) for each timestamp.
        # Victim has id=0. Attacker tuple does not need to specify the destination because it's always the victim.
        timestamps_tuples = []
        # For each attacker(id), stores the current source-ports of SYN-packets
        # which still have to be acknowledged by the victim, as a "FIFO" for each attacker
        previous_attacker_port = []
        replies_count = 0
        self.total_pkt_num = 0
        # For each attacker, generate his own packets, then merge all packets
        for attacker in range(num_attackers):
            # Initialize empty port "FIFO" for current attacker
            previous_attacker_port.append([])
            # Calculate timestamp of first SYN-packet of attacker
            timestamp_next_pkt = self.get_param_value(
                atkParam.Parameter.INJECT_AT_TIMESTAMP)
            attack_ends_time = timestamp_next_pkt + attack_duration
            timestamp_next_pkt = rnd.uniform(
                timestamp_next_pkt,
                Util.update_timestamp(timestamp_next_pkt, attacker_pps))
            attacker_pkts_num = int(pkts_num / num_attackers) + rnd.randint(
                0, 100)
            timestamp_prv_reply = 0
            for pkt_num in range(attacker_pkts_num):
                # Stop the attack when it exceeds the duration
                if timestamp_next_pkt > attack_ends_time:
                    break

                # Add timestamp of attacker SYN-packet. Attacker tuples do not need to specify destination
                timestamps_tuples.append((timestamp_next_pkt, attacker + 1))

                # Calculate timestamp of victim ACK-packet
                timestamp_reply = Util.update_timestamp(
                    timestamp_next_pkt, attacker_pps, min_delay)
                while timestamp_reply <= timestamp_prv_reply:
                    timestamp_reply = Util.update_timestamp(
                        timestamp_prv_reply, attacker_pps, min_delay)
                timestamp_prv_reply = timestamp_reply

                # Add timestamp of victim ACK-packet(victim always has id=0)
                timestamps_tuples.append((timestamp_reply, 0, attacker + 1))

                # Calculate timestamp for next attacker SYN-packet
                attacker_pps = max(
                    Util.get_interval_pps(complement_interval_attacker_pps,
                                          timestamp_next_pkt),
                    (pps / num_attackers) / 2)
                timestamp_next_pkt = Util.update_timestamp(
                    timestamp_next_pkt, attacker_pps)

        # Sort timestamp-triples according to their timestamps in ascending order
        timestamps_tuples.sort(key=lambda tmstmp: tmstmp[0])
        self.attack_start_utime = timestamps_tuples[0][0]

        # For each triple, generate packet
        for timestamp in timestamps_tuples:

            # If current current triple is an attacker
            if timestamp[1] != 0:

                attacker_id = timestamp[1] - 1
                # Build request package
                # Select one IP address and its corresponding MAC address
                ip_source = ip_source_list[attacker_id]
                mac_source = mac_source_list[attacker_id]

                # Determine source port
                (port_source,
                 ttl_value) = Util.get_attacker_config(ip_source_list,
                                                       ip_source)

                # If source ports were specified by the user, get random port from specified ports
                if port_source_list[0] != self.default_port:
                    port_source = rnd.choice(port_source_list)

                # Push port of current attacker SYN-packet into port "FIFO" of the current attacker
                # only if victim can still respond, otherwise, memory is wasted
                if replies_count <= victim_buffer:
                    previous_attacker_port[attacker_id].insert(0, port_source)

                request_ether = inet.Ether(dst=mac_destination, src=mac_source)
                request_ip = inet.IP(src=ip_source,
                                     dst=ip_destination,
                                     ttl=ttl_value)
                # Random win size for each packet
                source_win_size = rnd.choice(source_win_sizes)
                request_tcp = inet.TCP(sport=port_source,
                                       dport=port_destination,
                                       flags='S',
                                       ack=0,
                                       window=source_win_size)

                request = (request_ether / request_ip / request_tcp)
                request.time = timestamp[0]
                # Append request
                self.packets.append(request)
                self.total_pkt_num += 1

            # If current triple is the victim
            else:

                # Build reply package
                if replies_count <= victim_buffer:
                    attacker_id = timestamp[2] - 1

                    reply_ether = inet.Ether(src=mac_destination,
                                             dst=mac_source_list[attacker_id])
                    reply_ip = inet.IP(src=ip_destination,
                                       dst=ip_source_list[attacker_id],
                                       flags='DF')
                    # Pop port from attacker's port "FIFO" into destination port
                    reply_tcp = inet.TCP(
                        sport=port_destination,
                        dport=previous_attacker_port[attacker_id].pop(),
                        seq=0,
                        ack=1,
                        flags='SA',
                        window=destination_win_value,
                        options=[('MSS', mss_dst)])
                    reply = (reply_ether / reply_ip / reply_tcp)

                    reply.time = timestamp[0]
                    self.packets.append(reply)
                    replies_count += 1
                    self.total_pkt_num += 1

            # every 1000 packets write them to the pcap file (append)
            if (self.total_pkt_num > 0) and (self.total_pkt_num % buffer_size
                                             == 0) and (len(self.packets) > 0):
                self.last_packet = self.packets[-1]
                self.attack_end_utime = self.last_packet.time
                self.packets = sorted(self.packets, key=lambda pkt: pkt.time)
                self.path_attack_pcap = self.write_attack_pcap(
                    self.packets, True, self.path_attack_pcap)
                self.packets = []
Example #19
0
    def process_attack(self, attack: str, params: str, time=False):
        """
        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 and returns the path of the written pcap.

        :param attack: The classname of the attack to inject.
        :param params: The parameters for attack customization, see attack class for supported params.
        :param time: Measure packet generation time or not.
        :return: The file path to the created pcap file.
        """
        attack = self.choose_attack(attack)

        self.create_attack(attack, self.seed)

        print("Validating and adding attack parameters.")

        # Add attack parameters if provided
        params_dict = []
        if isinstance(params, list) and params:
            # Convert attack param list into dictionary
            for entry in params:
                params_dict.append(entry.split('='))
            params_dict = dict(params_dict)
            # Check if Parameter.INJECT_AT_TIMESTAMP and Parameter.INJECT_AFTER_PACKET are provided at the same time
            # if TRUE: delete Parameter.INJECT_AT_TIMESTAMP (lower priority) and use Parameter.INJECT_AFTER_PACKET
            if (atkParam.Parameter.INJECT_AFTER_PACKET.value in params_dict) and (
                        atkParam.Parameter.INJECT_AT_TIMESTAMP.value in params_dict):
                print("CONFLICT: Parameters", atkParam.Parameter.INJECT_AT_TIMESTAMP.value, "and",
                      atkParam.Parameter.INJECT_AFTER_PACKET.value,
                      "given at the same time. Ignoring", atkParam.Parameter.INJECT_AT_TIMESTAMP.value, "and using",
                      atkParam.Parameter.INJECT_AFTER_PACKET.value, "instead to derive the timestamp.")
                del params_dict[atkParam.Parameter.INJECT_AT_TIMESTAMP.value]

            # Extract attack_note parameter, if not provided returns an empty string
            key_attack_note = "attack.note"
            attack_note = params_dict.get(key_attack_note, "")
            params_dict.pop(key_attack_note, None)  # delete entry if found, otherwise return an empty string

            # Pass paramters to attack controller
            self.set_params(params_dict)
        else:
            attack_note = "This attack used only (random) default parameters."

        self.current_attack.init_objects()

        print("Generating attack packets...", end=" ")
        sys.stdout.flush()  # force python to print text immediately
        if time:
            self.current_attack.set_start_time()
        # Generate attack packets
        self.current_attack.generate_attack_packets()
        if time:
            self.current_attack.set_finish_time()
        duration = self.current_attack.get_packet_generation_time()
        # Write attack into pcap file
        attack_result = self.current_attack.generate_attack_pcap()

        self.total_packets = attack_result[0]
        temp_attack_pcap_path = attack_result[1]
        if len(attack_result) == 3:
            # Extract the list of additional files, if available
            self.additional_files += attack_result[2]
        print("done. (total: " + str(self.total_packets) + " pkts", end="")
        if time:
            print(" in ", duration, " seconds", end="")
        print(".)")

        # Warning if attack duration gets exceeded by more than 1 second
        if atkParam.Parameter.ATTACK_DURATION in self.current_attack.supported_params and \
                        self.current_attack.get_param_value(atkParam.Parameter.ATTACK_DURATION) != 0:
            attack_duration = self.current_attack.get_param_value(atkParam.Parameter.ATTACK_DURATION)
            packet_duration = abs(self.current_attack.attack_end_utime - self.current_attack.attack_start_utime)
            time_diff = abs(attack_duration - packet_duration)
            if self.current_attack.exceeding_packets > 0 and time_diff > 1:
                exceeding_packets = ""
                if self.current_attack.exceeding_packets:
                    exceeding_packets = " ({} attack pkts)".format(self.current_attack.exceeding_packets)
                print("Warning: attack duration was exceeded by {0} seconds{1}.".format(time_diff, exceeding_packets))
            elif time_diff > 1:
                print("Warning: attack duration was not reached by generated pkts by {} seconds.".format(time_diff))

        # Warning if pcap length gets exceeded
        pcap_end = Util.get_timestamp_from_datetime_str(self.statistics.get_pcap_timestamp_end())
        time_diff = pcap_end - self.current_attack.attack_end_utime
        if time_diff < 0:
            print("Warning: end of pcap exceeded by " + str(round(abs(time_diff), 2)) + " seconds.")

        # Store label into LabelManager
        label = Label.Label(attack, self.get_attack_start_utime(), self.get_attack_end_utime(),
                            self.total_packets, self.seed, self.current_attack.params, attack_note)
        self.label_mgr.add_labels(label)

        return temp_attack_pcap_path, duration
Example #20
0
 def test_generate_source_port_from_platform_oldwin_maxport(self):
     self.assertTrue(1024 <= Utility.generate_source_port_from_platform(
         "winxp", 5000) <= 5000)
Example #21
0
 def test_generate_source_port_from_platform_linux(self):
     self.assertTrue(32768 <= Utility.generate_source_port_from_platform(
         "linux") <= 61000)
Example #22
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """

        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)

        # Calculate complement packet rates of the background traffic for each interval
        complement_interval_pps = self.statistics.calculate_complement_packet_rates(
            pps)

        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        # store start time of attack
        self.attack_start_utime = timestamp_next_pkt
        timestamp_prv_reply, timestamp_confirm = 0, 0

        # Initialize parameters
        ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)

        dest_ip_count = self.get_param_value(atkParam.Parameter.TARGET_COUNT)
        ip_addr_count = self.statistics.get_ip_address_count()
        if ip_addr_count < dest_ip_count + 1:
            dest_ip_count = ip_addr_count

        # Check for user defined target IP addresses
        ip_destinations = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)
        if isinstance(ip_destinations, list):
            dest_ip_count = dest_ip_count - len(ip_destinations)
        elif ip_destinations is not "1.1.1.1":
            dest_ip_count = dest_ip_count - 1
            ip_destinations = [ip_destinations]
        else:
            ip_destinations = []

        # Take random targets from pcap
        rnd_ips = self.statistics.get_random_ip_address(dest_ip_count)
        if not isinstance(rnd_ips, list):
            rnd_ips = [rnd_ips]
        ip_destinations = ip_destinations + rnd_ips

        # Make sure the source IP is not part of targets
        if ip_source in ip_destinations and isinstance(ip_destinations, list):
            ip_destinations.remove(ip_source)
        self.add_param_value(atkParam.Parameter.IP_DESTINATION,
                             ip_destinations)

        ip_destinations = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)

        # Calculate the amount of IP addresses which are hosting SMB
        host_percentage = self.get_param_value(
            atkParam.Parameter.HOSTING_PERCENTAGE)
        rnd_ip_count = len(ip_destinations) * host_percentage

        # Check for user defined IP addresses which are hosting SMB
        hosting_ip = self.get_param_value(atkParam.Parameter.HOSTING_IP)
        if isinstance(hosting_ip, list):
            rnd_ip_count = rnd_ip_count - len(hosting_ip)
        elif hosting_ip is not "1.1.1.1":
            rnd_ip_count = rnd_ip_count - 1
            hosting_ip = [hosting_ip]
        else:
            hosting_ip = []

        hosting_ip = hosting_ip + ip_destinations[:int(rnd_ip_count)]
        self.add_param_value(atkParam.Parameter.HOSTING_IP, hosting_ip)

        # Shuffle targets
        rnd.shuffle(ip_destinations)

        # FIXME: Handle mac addresses correctly
        mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        mac_dest = self.get_param_value(atkParam.Parameter.MAC_DESTINATION)

        # Check smb version
        smb_version = self.get_param_value(atkParam.Parameter.PROTOCOL_VERSION)
        if smb_version not in SMBLib.smb_versions:
            SMBLib.invalid_smb_version(smb_version)
        hosting_version = self.get_param_value(
            atkParam.Parameter.HOSTING_VERSION)
        if hosting_version not in SMBLib.smb_versions:
            SMBLib.invalid_smb_version(hosting_version)
        # Check source platform
        src_platform = self.get_param_value(
            atkParam.Parameter.SOURCE_PLATFORM).lower()
        self.packets = []

        # randomize source ports according to platform, if specified
        if self.get_param_value(atkParam.Parameter.PORT_SOURCE_RANDOMIZE):
            sport = Util.generate_source_port_from_platform(src_platform)
        else:
            sport = self.get_param_value(atkParam.Parameter.PORT_SOURCE)

        # No destination IP was specified, but a destination MAC was specified, generate IP that fits MAC
        if isinstance(ip_destinations, list) and isinstance(mac_dest, str):
            ip_destinations = self.statistics.get_ip_address_from_mac(mac_dest)
            if len(ip_destinations) == 0:
                ip_destinations = self.generate_random_ipv4_address(
                    "Unknown", 1)
            # Check ip.src == ip.dst
            self.ip_src_dst_equal_check(ip_source, ip_destinations)

        ip_dests = []
        if isinstance(ip_destinations, list):
            ip_dests = ip_destinations
        else:
            ip_dests.append(ip_destinations)

        if isinstance(ip_dests, list):
            rnd.shuffle(ip_dests)

        # Randomize source IP, if specified
        if self.get_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE):
            ip_source = self.generate_random_ipv4_address("Unknown", 1)
            while ip_source in ip_dests:
                ip_source = self.generate_random_ipv4_address("Unknown", 1)
            mac_source = self.statistics.get_mac_address(str(ip_source))
            if len(mac_source) == 0:
                mac_source = self.generate_random_mac_address()

        # Get MSS, TTL and Window size value for source IP
        source_mss_value, source_ttl_value, source_win_value = self.get_ip_data(
            ip_source)

        mac_dests = self.statistics.get_mac_addresses(ip_dests)
        first_timestamp_smb = self.statistics.get_pcap_timestamp_start()[:19]

        # get inject pss
        inject_pps = self.get_param_value(atkParam.Parameter.INJECT_PPS)

        for ip in ip_dests:

            if ip != ip_source:

                # Get destination Mac Address
                mac_destination = ""
                if ip in mac_dests.keys():
                    mac_destination = mac_dests[ip]
                if len(mac_destination) == 0:
                    if isinstance(mac_dest, str):
                        ip_from_mac = self.statistics.get_ip_address_from_mac(
                            mac_dest)
                        if len(ip_from_mac) != 0:
                            ip = ip_from_mac
                            self.ip_src_dst_equal_check(ip_source, ip)
                        mac_destination = mac_dest
                    else:
                        mac_destination = self.generate_random_mac_address()

                # Get MSS, TTL and Window size value for destination IP
                destination_mss_value, destination_ttl_value, destination_win_value = self.get_ip_data(
                    ip)

                min_delay, max_delay = self.get_reply_delay(ip)

                # New connection, new random TCP sequence numbers
                attacker_seq = rnd.randint(1000, 50000)
                victim_seq = rnd.randint(1000, 50000)

                # Randomize source port for each connection if specified
                if self.get_param_value(
                        atkParam.Parameter.PORT_SOURCE_RANDOMIZE):
                    sport = Util.generate_source_port_from_platform(
                        src_platform, sport)

                # 1) Build request package
                request_ether = inet.Ether(src=mac_source, dst=mac_destination)
                request_ip = inet.IP(src=ip_source,
                                     dst=ip,
                                     ttl=source_ttl_value,
                                     flags='DF')
                request_tcp = inet.TCP(sport=sport,
                                       dport=SMBLib.smb_port,
                                       window=source_win_value,
                                       flags='S',
                                       seq=attacker_seq,
                                       options=[('MSS', source_mss_value)])
                attacker_seq += 1
                request = (request_ether / request_ip / request_tcp)
                request.time = timestamp_next_pkt

                # Append request
                self.packets.append(request)

                # Update timestamp for next package
                timestamp_reply = Util.update_timestamp(
                    timestamp_next_pkt,
                    pps,
                    min_delay,
                    inj_pps=inject_pps,
                    inj_timestamp=self.attack_start_utime)
                while timestamp_reply <= timestamp_prv_reply:
                    timestamp_reply = Util.update_timestamp(
                        timestamp_prv_reply,
                        pps,
                        min_delay,
                        inj_pps=inject_pps,
                        inj_timestamp=self.attack_start_utime)
                timestamp_prv_reply = timestamp_reply

                if ip in hosting_ip:

                    # 2) Build TCP packages for ip that hosts SMB

                    # destination sends SYN, ACK
                    reply_ether = inet.Ether(src=mac_destination,
                                             dst=mac_source)
                    reply_ip = inet.IP(src=ip,
                                       dst=ip_source,
                                       ttl=destination_ttl_value,
                                       flags='DF')
                    reply_tcp = inet.TCP(sport=SMBLib.smb_port,
                                         dport=sport,
                                         seq=victim_seq,
                                         ack=attacker_seq,
                                         flags='SA',
                                         window=destination_win_value,
                                         options=[('MSS',
                                                   destination_mss_value)])
                    victim_seq += 1
                    reply = (reply_ether / reply_ip / reply_tcp)
                    reply.time = timestamp_reply
                    self.packets.append(reply)

                    # requester confirms, ACK
                    confirm_ether = request_ether
                    confirm_ip = request_ip
                    confirm_tcp = inet.TCP(sport=sport,
                                           dport=SMBLib.smb_port,
                                           seq=attacker_seq,
                                           ack=victim_seq,
                                           window=source_win_value,
                                           flags='A')
                    confirm = (confirm_ether / confirm_ip / confirm_tcp)
                    timestamp_confirm = Util.update_timestamp(
                        timestamp_reply, pps, min_delay)
                    confirm.time = timestamp_confirm
                    self.packets.append(confirm)

                    # 3) Build SMB Negotiation packets
                    smb_mid = rnd.randint(1, 65535)
                    smb_pid = rnd.randint(1, 65535)
                    smb_req_tail_arr = []
                    smb_req_tail_size = 0

                    # select dialects based on smb version
                    if smb_version is "1":
                        smb_req_dialects = SMBLib.smb_dialects[0:6]
                    else:
                        smb_req_dialects = SMBLib.smb_dialects
                    if len(smb_req_dialects) == 0:
                        smb_req_tail_arr.append(
                            SMBNegociate_Protocol_Request_Tail())
                        smb_req_tail_size = len(
                            SMBNegociate_Protocol_Request_Tail())
                    else:
                        for dia in smb_req_dialects:
                            smb_req_tail_arr.append(
                                SMBNegociate_Protocol_Request_Tail(
                                    BufferData=dia))
                            smb_req_tail_size += len(
                                SMBNegociate_Protocol_Request_Tail(
                                    BufferData=dia))

                    # Creation of SMB Negotiate Protocol Request packet
                    smb_req_head = SMBNegociate_Protocol_Request_Header(
                        Flags2=0x2801,
                        PID=smb_pid,
                        MID=smb_mid,
                        ByteCount=smb_req_tail_size)
                    smb_req_length = len(smb_req_head) + smb_req_tail_size
                    smb_req_net_bio = NBTSession(TYPE=0x00,
                                                 LENGTH=smb_req_length)
                    smb_req_tcp = inet.TCP(sport=sport,
                                           dport=SMBLib.smb_port,
                                           flags='PA',
                                           seq=attacker_seq,
                                           ack=victim_seq)
                    smb_req_ip = inet.IP(src=ip_source,
                                         dst=ip,
                                         ttl=source_ttl_value)
                    smb_req_ether = inet.Ether(src=mac_source,
                                               dst=mac_destination)
                    attacker_seq += len(smb_req_net_bio) + len(
                        smb_req_head) + smb_req_tail_size

                    smb_req_combined = (smb_req_ether / smb_req_ip /
                                        smb_req_tcp / smb_req_net_bio /
                                        smb_req_head)

                    for i in range(0, len(smb_req_tail_arr)):
                        smb_req_combined = smb_req_combined / smb_req_tail_arr[
                            i]

                    timestamp_smb_req = Util.update_timestamp(
                        timestamp_confirm, pps, min_delay)
                    smb_req_combined.time = timestamp_smb_req
                    self.packets.append(smb_req_combined)

                    # destination confirms SMB request package
                    reply_tcp = inet.TCP(sport=SMBLib.smb_port,
                                         dport=sport,
                                         seq=victim_seq,
                                         ack=attacker_seq,
                                         window=destination_win_value,
                                         flags='A')
                    confirm_smb_req = (reply_ether / reply_ip / reply_tcp)
                    timestamp_reply = Util.update_timestamp(
                        timestamp_smb_req, pps, min_delay)
                    confirm_smb_req.time = timestamp_reply
                    self.packets.append(confirm_smb_req)

                    # smb response package
                    first_timestamp = time.mktime(
                        time.strptime(first_timestamp_smb,
                                      "%Y-%m-%d %H:%M:%S"))
                    server_guid, security_blob, capabilities, data_size, server_start_time =\
                        SMBLib.get_smb_platform_data(self.host_os, first_timestamp)

                    timestamp_smb_rsp = Util.update_timestamp(
                        timestamp_reply, pps, min_delay)
                    diff = timestamp_smb_rsp - timestamp_smb_req
                    begin = Util.get_filetime_format(timestamp_smb_req +
                                                     diff * 0.1)
                    end = Util.get_filetime_format(timestamp_smb_rsp -
                                                   diff * 0.1)
                    system_time = rnd.randint(begin, end)

                    # Creation of SMB Negotiate Protocol Response packets
                    if smb_version is not "1" and hosting_version is not "1":
                        smb_rsp_packet = SMB2.SMB2_SYNC_Header(Flags=1)
                        smb_rsp_negotiate_body =\
                            SMB2.SMB2_Negotiate_Protocol_Response(DialectRevision=0x02ff, SecurityBufferOffset=124,
                                                                  SecurityBufferLength=len(security_blob),
                                                                  SecurityBlob=security_blob, Capabilities=capabilities,
                                                                  MaxTransactSize=data_size, MaxReadSize=data_size,
                                                                  MaxWriteSize=data_size, SystemTime=system_time,
                                                                  ServerStartTime=server_start_time,
                                                                  ServerGuid=server_guid)
                        smb_rsp_length = len(smb_rsp_packet) + len(
                            smb_rsp_negotiate_body)
                    else:
                        smb_rsp_packet =\
                            SMBNegociate_Protocol_Response_Advanced_Security(Start="\xffSMB", PID=smb_pid, MID=smb_mid,
                                                                             DialectIndex=5, SecurityBlob=security_blob)
                        smb_rsp_length = len(smb_rsp_packet)
                    smb_rsp_net_bio = NBTSession(TYPE=0x00,
                                                 LENGTH=smb_rsp_length)
                    smb_rsp_tcp = inet.TCP(sport=SMBLib.smb_port,
                                           dport=sport,
                                           flags='PA',
                                           seq=victim_seq,
                                           ack=attacker_seq)
                    smb_rsp_ip = inet.IP(src=ip,
                                         dst=ip_source,
                                         ttl=destination_ttl_value)
                    smb_rsp_ether = inet.Ether(src=mac_destination,
                                               dst=mac_source)
                    victim_seq += len(smb_rsp_net_bio) + len(smb_rsp_packet)
                    if smb_version is not "1" and hosting_version is not "1":
                        victim_seq += len(smb_rsp_negotiate_body)

                    smb_rsp_combined = (smb_rsp_ether / smb_rsp_ip /
                                        smb_rsp_tcp / smb_rsp_net_bio /
                                        smb_rsp_packet)
                    if smb_version is not "1" and hosting_version is not "1":
                        smb_rsp_combined = (smb_rsp_combined /
                                            smb_rsp_negotiate_body)

                    smb_rsp_combined.time = timestamp_smb_rsp
                    self.packets.append(smb_rsp_combined)

                    # source confirms SMB response package
                    confirm_tcp = inet.TCP(sport=sport,
                                           dport=SMBLib.smb_port,
                                           seq=attacker_seq,
                                           ack=victim_seq,
                                           window=source_win_value,
                                           flags='A')
                    confirm_smb_res = (confirm_ether / confirm_ip /
                                       confirm_tcp)
                    timestamp_confirm = Util.update_timestamp(
                        timestamp_smb_rsp, pps, min_delay)
                    confirm_smb_res.time = timestamp_confirm
                    self.packets.append(confirm_smb_res)

                    # attacker sends FIN ACK
                    confirm_tcp = inet.TCP(sport=sport,
                                           dport=SMBLib.smb_port,
                                           seq=attacker_seq,
                                           ack=victim_seq,
                                           window=source_win_value,
                                           flags='FA')
                    source_fin_ack = (confirm_ether / confirm_ip / confirm_tcp)
                    timestamp_src_fin_ack = Util.update_timestamp(
                        timestamp_confirm, pps, min_delay)
                    source_fin_ack.time = timestamp_src_fin_ack
                    attacker_seq += 1
                    self.packets.append(source_fin_ack)

                    # victim sends FIN ACK
                    reply_tcp = inet.TCP(sport=SMBLib.smb_port,
                                         dport=sport,
                                         seq=victim_seq,
                                         ack=attacker_seq,
                                         window=destination_win_value,
                                         flags='FA')
                    destination_fin_ack = (reply_ether / reply_ip / reply_tcp)
                    timestamp_dest_fin_ack = Util.update_timestamp(
                        timestamp_src_fin_ack, pps, min_delay)
                    victim_seq += 1
                    destination_fin_ack.time = timestamp_dest_fin_ack
                    self.packets.append(destination_fin_ack)

                    # source sends final ACK
                    confirm_tcp = inet.TCP(sport=sport,
                                           dport=SMBLib.smb_port,
                                           seq=attacker_seq,
                                           ack=victim_seq,
                                           window=source_win_value,
                                           flags='A')
                    final_ack = (confirm_ether / confirm_ip / confirm_tcp)
                    timestamp_final_ack = Util.update_timestamp(
                        timestamp_dest_fin_ack, pps, min_delay)
                    final_ack.time = timestamp_final_ack
                    self.packets.append(final_ack)

                else:
                    # Build RST package
                    reply_ether = inet.Ether(src=mac_destination,
                                             dst=mac_source)
                    reply_ip = inet.IP(src=ip,
                                       dst=ip_source,
                                       ttl=destination_ttl_value,
                                       flags='DF')
                    reply_tcp = inet.TCP(sport=SMBLib.smb_port,
                                         dport=sport,
                                         seq=0,
                                         ack=attacker_seq,
                                         flags='RA',
                                         window=destination_win_value,
                                         options=[('MSS',
                                                   destination_mss_value)])
                    reply = (reply_ether / reply_ip / reply_tcp)
                    reply.time = timestamp_reply
                    self.packets.append(reply)

            pps = max(
                Util.get_interval_pps(complement_interval_pps,
                                      timestamp_next_pkt), 10)
            timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
Example #23
0
 def test_generate_source_port_from_platform_newwinmac_firstport(self):
     self.assertTrue(49152 <= Utility.generate_source_port_from_platform(
         "win7") <= 65535)
Example #24
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """

        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)

        # Initialize parameters
        self.packets = []
        mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)

        # Pick a DNS server from the background traffic
        ip_dns_server = self.statistics.process_db_query(
            "SELECT ipAddress FROM ip_protocols WHERE protocolName='DNS' AND protocolCount=(SELECT MAX(protocolCount) "
            "FROM ip_protocols WHERE protocolName='DNS');")
        ip_dns_server = Util.handle_most_used_outputs(ip_dns_server)
        if not ip_dns_server or ip_source == ip_dns_server:
            ip_dns_server = self.statistics.get_random_ip_address()
        mac_dns_server = self.statistics.get_mac_address(ip_dns_server)

        # Bot original config in the template PCAP
        origin_mac_src = "08:00:27:e5:d7:b0"
        origin_ip_src = "10.0.2.15"

        origin_mac_dns_server = "52:54:00:12:35:02"
        origin_ip_dns_server = "10.0.2.2"

        ttl_map = {}

        ip_map = {
            origin_ip_src: ip_source,
            origin_ip_dns_server: ip_dns_server
        }
        mac_map = {
            origin_mac_src: mac_source,
            origin_mac_dns_server: mac_dns_server
        }

        # Inject Sality botnet
        # Read sality_botnet pcap file
        exploit_raw_packets = scapy.utils.RawPcapReader(
            self.template_attack_pcap_path)

        for self.pkt_num, pkt in enumerate(exploit_raw_packets):
            eth_frame = inet.Ether(pkt[0])
            ip_pkt = eth_frame.payload

            # Ether
            if eth_frame.getfieldval("src") in mac_map:
                eth_frame.setfieldval("src",
                                      mac_map[eth_frame.getfieldval("src")])
            if eth_frame.getfieldval("dst") in mac_map:
                eth_frame.setfieldval("dst",
                                      mac_map[eth_frame.getfieldval("dst")])

            # IP
            if ip_pkt.getfieldval("src") in ip_map:
                ip_pkt.setfieldval("src", ip_map[ip_pkt.getfieldval("src")])
            if ip_pkt.getfieldval("dst") in ip_map:
                ip_pkt.setfieldval("dst", ip_map[ip_pkt.getfieldval("dst")])

            # TTL
            if ip_pkt.getfieldval("ttl") not in ttl_map:
                source_ttl = self.statistics.get_most_used_ttl(
                    ip_pkt.getfieldval("src"))
                if not source_ttl:
                    source_ttl = self.statistics.process_db_query(
                        "SELECT ttlValue FROM ip_ttl;")
                    if isinstance(source_ttl, list):
                        source_ttl = rnd.choice(source_ttl)
                ttl_map[ip_pkt.getfieldval("ttl")] = source_ttl
            ip_pkt.setfieldval("ttl", ttl_map[ip_pkt.getfieldval("ttl")])

            new_pkt = (eth_frame / ip_pkt)
            new_pkt.time = timestamp_next_pkt

            timestamp_next_pkt = self.timestamp_controller.next_timestamp()

            self.packets.append(new_pkt)

        exploit_raw_packets.close()
Example #25
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)

        # calculate complement packet rates of BG traffic per interval
        complement_interval_pps = self.statistics.calculate_complement_packet_rates(
            pps)

        # Initialize parameters
        self.packets = []
        mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)
        # FIXME: why is port_source never used?
        port_source = self.get_param_value(atkParam.Parameter.PORT_SOURCE)
        mac_destination = self.get_param_value(
            atkParam.Parameter.MAC_DESTINATION)
        ip_destination = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)
        port_destination = self.get_param_value(
            atkParam.Parameter.PORT_DESTINATION)

        # Check ip.src == ip.dst
        self.ip_src_dst_equal_check(ip_source, ip_destination)

        # Set TTL based on TTL distribution of IP address
        source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
        if len(source_ttl_dist) > 0:
            source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
            source_ttl_value = source_ttl_prob_dict.random()
        else:
            source_ttl_value = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ttl_value())

        destination_ttl_dist = self.statistics.get_ttl_distribution(
            ip_destination)
        if len(destination_ttl_dist) > 0:
            destination_ttl_prob_dict = lea.Lea.fromValFreqsDict(
                destination_ttl_dist)
            destination_ttl_value = destination_ttl_prob_dict.random()
        else:
            destination_ttl_value = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ttl_value())

        # Set Window Size based on Window Size distribution of IP address
        source_win_dist = self.statistics.get_win_distribution(ip_source)
        if len(source_win_dist) > 0:
            source_win_prob_dict = lea.Lea.fromValFreqsDict(source_win_dist)
        else:
            source_win_dist = self.statistics.get_win_distribution(
                self.statistics.get_most_used_ip_address())
            source_win_prob_dict = lea.Lea.fromValFreqsDict(source_win_dist)

        destination_win_dist = self.statistics.get_win_distribution(
            ip_destination)
        if len(destination_win_dist) > 0:
            destination_win_prob_dict = lea.Lea.fromValFreqsDict(
                destination_win_dist)
        else:
            destination_win_dist = self.statistics.get_win_distribution(
                self.statistics.get_most_used_ip_address())
            destination_win_prob_dict = lea.Lea.fromValFreqsDict(
                destination_win_dist)

        # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
        mss_value = Util.handle_most_used_outputs(
            self.statistics.get_most_used_mss_value())
        if not mss_value:
            mss_value = 1465

        # Inject EternalBlue exploit packets
        # Read Win7_eternalblue_exploit pcap file
        source_origin_wins, destination_origin_wins = {}, {}
        exploit_raw_packets = scapy.utils.RawPcapReader(
            self.template_attack_pcap_path)

        port_source = rnd.randint(
            self.minDefaultPort,
            self.maxDefaultPort)  # experiments show this range of ports
        # conversations = {(ip.src, ip.dst, port.src, port.dst): packets}
        conversations, order_list_conversations = self.packets_to_convs(
            exploit_raw_packets)
        exploit_raw_packets.close()

        conv_start_timesamp = timestamp_next_pkt
        for conv_index, conv in enumerate(order_list_conversations):
            # the distance between the starts of the converstaions
            conv_start_timesamp = conv_start_timesamp + rnd.uniform(
                0.001, 0.01)
            timestamp_next_pkt = conv_start_timesamp

            conv_pkts = conversations[conv]
            inter_arrival_times = self.get_inter_arrival_time(conv_pkts)

            if conv_index == len(
                    order_list_conversations) - 2:  # Not the last conversation
                timestamp_next_pkt = self.packets[-1].time + rnd.uniform(
                    0.001, 0.01)

            if conv_index != len(
                    order_list_conversations) - 1:  # Not the last conversation
                port_source += 2
                for self.pkt_num, pkt in enumerate(conv_pkts):
                    eth_frame = inet.Ether(pkt[0])
                    ip_pkt = eth_frame.payload
                    tcp_pkt = ip_pkt.payload

                    if self.pkt_num == 0:
                        if tcp_pkt.getfieldval("dport") == SMBLib.smb_port:
                            orig_ip_dst = ip_pkt.getfieldval("dst")

                    # Request
                    if ip_pkt.getfieldval("dst") == orig_ip_dst:  # victim IP
                        # Ether
                        eth_frame.setfieldval("src", mac_source)
                        eth_frame.setfieldval("dst", mac_destination)
                        # IP
                        ip_pkt.setfieldval("src", ip_source)
                        ip_pkt.setfieldval("dst", ip_destination)
                        ip_pkt.setfieldval("ttl", source_ttl_value)
                        # TCP
                        tcp_pkt.setfieldval("sport", port_source)
                        tcp_pkt.setfieldval("dport", port_destination)
                        # Window Size
                        source_origin_win = tcp_pkt.getfieldval("window")
                        if source_origin_win not in source_origin_wins:
                            source_origin_wins[
                                source_origin_win] = source_win_prob_dict.random(
                                )
                        new_win = source_origin_wins[source_origin_win]
                        tcp_pkt.setfieldval("window", new_win)
                        # MSS
                        tcp_options = tcp_pkt.getfieldval("options")
                        if tcp_options:
                            if tcp_options[0][0] == "MSS":
                                tcp_options[0] = ("MSS", mss_value)
                                tcp_pkt.setfieldval("options", tcp_options)

                        new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                        new_pkt.time = timestamp_next_pkt

                        pps = max(
                            Util.get_interval_pps(complement_interval_pps,
                                                  timestamp_next_pkt), 10)
                        timestamp_next_pkt = Util.update_timestamp(
                            timestamp_next_pkt, pps) + inter_arrival_times[
                                self.pkt_num]  # float(timeSteps.random())

                    # Reply
                    else:
                        # Ether
                        eth_frame.setfieldval("src", mac_destination)
                        eth_frame.setfieldval("dst", mac_source)
                        # IP
                        ip_pkt.setfieldval("src", ip_destination)
                        ip_pkt.setfieldval("dst", ip_source)
                        ip_pkt.setfieldval("ttl", destination_ttl_value)
                        # TCP
                        tcp_pkt.setfieldval("dport", port_source)
                        tcp_pkt.setfieldval("sport", port_destination)
                        # Window Size
                        destination_origin_win = tcp_pkt.getfieldval("window")
                        if destination_origin_win not in destination_origin_wins:
                            destination_origin_wins[
                                destination_origin_win] = destination_win_prob_dict.random(
                                )
                        new_win = destination_origin_wins[
                            destination_origin_win]
                        tcp_pkt.setfieldval("window", new_win)
                        # MSS
                        tcp_options = tcp_pkt.getfieldval("options")
                        if tcp_options:
                            if tcp_options[0][0] == "MSS":
                                tcp_options[0] = ("MSS", mss_value)
                                tcp_pkt.setfieldval("options", tcp_options)

                        new_pkt = (eth_frame / ip_pkt / tcp_pkt)

                        pps = max(
                            Util.get_interval_pps(complement_interval_pps,
                                                  timestamp_next_pkt), 10)
                        timestamp_next_pkt = Util.update_timestamp(
                            timestamp_next_pkt, pps) + inter_arrival_times[
                                self.pkt_num]  # float(timeSteps.random())

                        new_pkt.time = timestamp_next_pkt

                    self.packets.append(new_pkt)

            else:  # Last conversation where the victim start a connection with the attacker
                timestamp_next_pkt = self.packets[-1].time + rnd.uniform(
                    0.001, 0.01)
                port_source = rnd.randint(self.minDefaultPort,
                                          self.maxDefaultPort)
                for self.pkt_num, pkt in enumerate(conv_pkts):
                    eth_frame = inet.Ether(pkt[0])
                    ip_pkt = eth_frame.payload
                    tcp_pkt = ip_pkt.payload

                    # Request
                    if tcp_pkt.getfieldval("dport") == self.last_conn_dst_port:
                        # Ether
                        eth_frame.setfieldval("src", mac_destination)
                        eth_frame.setfieldval("dst", mac_source)
                        # IP
                        ip_pkt.setfieldval("src", ip_destination)
                        ip_pkt.setfieldval("dst", ip_source)
                        ip_pkt.setfieldval("ttl", destination_ttl_value)
                        # TCP
                        tcp_pkt.setfieldval("sport", port_source)
                        # destination port is fixed 4444
                        # Window Size
                        destination_origin_win = tcp_pkt.getfieldval("window")
                        if destination_origin_win not in destination_origin_wins:
                            destination_origin_wins[
                                destination_origin_win] = destination_win_prob_dict.random(
                                )
                        new_win = destination_origin_wins[
                            destination_origin_win]
                        tcp_pkt.setfieldval("window", new_win)
                        # MSS
                        tcp_options = tcp_pkt.getfieldval("options")
                        if tcp_options:
                            if tcp_options[0][0] == "MSS":
                                tcp_options[0] = ("MSS", mss_value)
                                tcp_pkt.setfieldval("options", tcp_options)

                        new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                        new_pkt.time = timestamp_next_pkt

                        pps = max(
                            Util.get_interval_pps(complement_interval_pps,
                                                  timestamp_next_pkt), 10)
                        timestamp_next_pkt = Util.update_timestamp(
                            timestamp_next_pkt, pps) + inter_arrival_times[
                                self.pkt_num]  # float(timeSteps.random())

                    # Reply
                    else:
                        # Ether
                        eth_frame.setfieldval("src", mac_source)
                        eth_frame.setfieldval("dst", mac_destination)
                        # IP
                        ip_pkt.setfieldval("src", ip_source)
                        ip_pkt.setfieldval("dst", ip_destination)
                        ip_pkt.setfieldval("ttl", source_ttl_value)
                        # TCP
                        tcp_pkt.setfieldval("dport", port_source)
                        # source port is fixed 4444
                        # Window Size
                        source_origin_win = tcp_pkt.getfieldval("window")
                        if source_origin_win not in source_origin_wins:
                            source_origin_wins[
                                source_origin_win] = source_win_prob_dict.random(
                                )
                        new_win = source_origin_wins[source_origin_win]
                        tcp_pkt.setfieldval("window", new_win)
                        # MSS
                        tcp_options = tcp_pkt.getfieldval("options")
                        if tcp_options:
                            if tcp_options[0][0] == "MSS":
                                tcp_options[0] = ("MSS", mss_value)
                                tcp_pkt.setfieldval("options", tcp_options)

                        new_pkt = (eth_frame / ip_pkt / tcp_pkt)

                        pps = max(
                            Util.get_interval_pps(complement_interval_pps,
                                                  timestamp_next_pkt), 10)
                        timestamp_next_pkt = Util.update_timestamp(
                            timestamp_next_pkt, pps) + inter_arrival_times[
                                self.pkt_num]  # float(timeSteps.random())

                        new_pkt.time = timestamp_next_pkt

                    self.packets.append(new_pkt)
Example #26
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        mac_destination = self.get_param_value(
            atkParam.Parameter.MAC_DESTINATION)

        # Determine ports
        dest_ports = self.get_param_value(atkParam.Parameter.PORT_DESTINATION)
        if self.get_param_value(atkParam.Parameter.PORT_DEST_ORDER_DESC):
            dest_ports.reverse()
        elif self.get_param_value(atkParam.Parameter.PORT_DEST_SHUFFLE):
            rnd.shuffle(dest_ports)
        if self.get_param_value(atkParam.Parameter.PORT_SOURCE_RANDOMIZE):
            # FIXME: why is sport never used?
            sport = rnd.randint(1, 65535)
        else:
            sport = self.get_param_value(atkParam.Parameter.PORT_SOURCE)

        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        # store start time of attack
        self.attack_start_utime = timestamp_next_pkt

        # Initialize parameters
        self.packets = []
        ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)
        if isinstance(ip_source, list):
            ip_source = ip_source[0]
        ip_destination = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)
        if not isinstance(ip_destination, list):
            ip_destination = [ip_destination]

        # Check ip.src == ip.dst
        self.ip_src_dst_catch_equal(ip_source, ip_destination)

        for ip in ip_destination:
            # Select open ports
            ports_open = self.get_param_value(atkParam.Parameter.PORT_OPEN)
            if ports_open == 1:  # user did not specify open ports
                # the ports that were already used by ip.dst (direction in) in the background traffic are open ports
                ports_used_by_ip_dst = self.statistics.process_db_query(
                    "SELECT portNumber FROM ip_ports WHERE portDirection='in' AND ipAddress='"
                    + ip + "'")
                if ports_used_by_ip_dst:
                    ports_open = ports_used_by_ip_dst
                else:  # if no ports were retrieved from database
                    # Take open ports from nmap-service file
                    # ports_temp = self.get_ports_from_nmap_service_dst(100)
                    # ports_open = ports_temp[0:rnd.randint(1,10)]
                    # OR take open ports from the most used ports in traffic statistics
                    ports_open = self.statistics.process_db_query(
                        "SELECT portNumber FROM ip_ports GROUP BY portNumber ORDER BY SUM(portCount) DESC LIMIT "
                        + str(rnd.randint(1, 10)))
            # in case of one open port, convert ports_open to array
            if not isinstance(ports_open, list):
                ports_open = [ports_open]

            # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
            source_mss_dist = self.statistics.get_mss_distribution(ip_source)
            if len(source_mss_dist) > 0:
                source_mss_prob_dict = lea.Lea.fromValFreqsDict(
                    source_mss_dist)
                source_mss_value = source_mss_prob_dict.random()
            else:
                source_mss_value = Util.handle_most_used_outputs(
                    self.statistics.get_most_used_mss_value())
            destination_mss_dist = self.statistics.get_mss_distribution(ip)
            if len(destination_mss_dist) > 0:
                destination_mss_prob_dict = lea.Lea.fromValFreqsDict(
                    destination_mss_dist)
                destination_mss_value = destination_mss_prob_dict.random()
            else:
                destination_mss_value = Util.handle_most_used_outputs(
                    self.statistics.get_most_used_mss_value())

            # Set TTL based on TTL distribution of IP address
            source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
            if len(source_ttl_dist) > 0:
                source_ttl_prob_dict = lea.Lea.fromValFreqsDict(
                    source_ttl_dist)
                source_ttl_value = source_ttl_prob_dict.random()
            else:
                source_ttl_value = Util.handle_most_used_outputs(
                    self.statistics.get_most_used_ttl_value())
            destination_ttl_dist = self.statistics.get_ttl_distribution(ip)
            if len(destination_ttl_dist) > 0:
                destination_ttl_prob_dict = lea.Lea.fromValFreqsDict(
                    destination_ttl_dist)
                destination_ttl_value = destination_ttl_prob_dict.random()
            else:
                destination_ttl_value = Util.handle_most_used_outputs(
                    self.statistics.get_most_used_ttl_value())

            # Set Window Size based on Window Size distribution of IP address
            source_win_dist = self.statistics.get_win_distribution(ip_source)
            if len(source_win_dist) > 0:
                source_win_prob_dict = lea.Lea.fromValFreqsDict(
                    source_win_dist)
                source_win_value = source_win_prob_dict.random()
            else:
                source_win_value = Util.handle_most_used_outputs(
                    self.statistics.get_most_used_win_size())
            destination_win_dist = self.statistics.get_win_distribution(ip)
            if len(destination_win_dist) > 0:
                destination_win_prob_dict = lea.Lea.fromValFreqsDict(
                    destination_win_dist)
                destination_win_value = destination_win_prob_dict.random()
            else:
                destination_win_value = Util.handle_most_used_outputs(
                    self.statistics.get_most_used_win_size())

            min_delay, max_delay = self.get_reply_latency(ip_source, ip)

            for dport in dest_ports:
                # Parameters changing each iteration
                if self.get_param_value(
                        atkParam.Parameter.IP_SOURCE_RANDOMIZE) and isinstance(
                            ip_source, list):
                    ip_source = rnd.choice(ip_source)

                # 1) Build request package
                request_ether = inet.Ether(src=mac_source, dst=mac_destination)
                request_ip = inet.IP(src=ip_source,
                                     dst=ip,
                                     ttl=source_ttl_value)

                # Random src port for each packet
                sport = rnd.randint(1, 65535)

                request_tcp = inet.TCP(sport=sport,
                                       dport=dport,
                                       window=source_win_value,
                                       flags='S',
                                       options=[('MSS', source_mss_value)])

                request = (request_ether / request_ip / request_tcp)

                request.time = timestamp_next_pkt
                # Append request
                self.packets.append(request)

                # 2) Build reply (for open ports) package
                if dport in ports_open:  # destination port is OPEN
                    reply_ether = inet.Ether(src=mac_destination,
                                             dst=mac_source)
                    reply_ip = inet.IP(src=ip,
                                       dst=ip_source,
                                       ttl=destination_ttl_value,
                                       flags='DF')
                    reply_tcp = inet.TCP(sport=dport,
                                         dport=sport,
                                         seq=0,
                                         ack=1,
                                         flags='SA',
                                         window=destination_win_value,
                                         options=[('MSS',
                                                   destination_mss_value)])
                    reply = (reply_ether / reply_ip / reply_tcp)

                    timestamp_reply = self.timestamp_controller.next_timestamp(
                        latency=min_delay)

                    reply.time = timestamp_reply
                    self.packets.append(reply)

                    # requester confirms
                    confirm_ether = request_ether
                    confirm_ip = request_ip
                    confirm_tcp = inet.TCP(sport=sport,
                                           dport=dport,
                                           seq=1,
                                           window=0,
                                           flags='R')
                    confirm = (confirm_ether / confirm_ip / confirm_tcp)
                    self.timestamp_controller.set_timestamp(timestamp_reply)
                    timestamp_confirm = self.timestamp_controller.next_timestamp(
                        latency=min_delay)
                    confirm.time = timestamp_confirm
                    self.packets.append(confirm)

                    # else: destination port is NOT OPEN -> no reply is sent by target

                self.timestamp_controller.set_timestamp(timestamp_next_pkt)
                timestamp_next_pkt = self.timestamp_controller.next_timestamp()
Example #27
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)

        # calculate complement packet rates of BG traffic per interval
        complement_interval_pps = self.statistics.calculate_complement_packet_rates(
            pps)

        # Initialize parameters
        self.packets = []
        mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)
        port_source = self.get_param_value(atkParam.Parameter.PORT_SOURCE)
        mac_destination = self.get_param_value(
            atkParam.Parameter.MAC_DESTINATION)
        ip_destination = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)
        port_destination = self.get_param_value(
            atkParam.Parameter.PORT_DESTINATION)

        # Check ip.src == ip.dst
        self.ip_src_dst_equal_check(ip_source, ip_destination)

        # Set TTL based on TTL distribution of IP address
        source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
        if len(source_ttl_dist) > 0:
            source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
            source_ttl_value = source_ttl_prob_dict.random()
        else:
            source_ttl_value = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ttl_value())

        destination_ttl_dist = self.statistics.get_ttl_distribution(
            ip_destination)
        if len(destination_ttl_dist) > 0:
            destination_ttl_prob_dict = lea.Lea.fromValFreqsDict(
                destination_ttl_dist)
            destination_ttl_value = destination_ttl_prob_dict.random()
        else:
            destination_ttl_value = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ttl_value())

        # Set Window Size based on Window Size distribution of IP address
        source_win_dist = self.statistics.get_win_distribution(ip_source)
        if len(source_win_dist) > 0:
            source_win_prob_dict = lea.Lea.fromValFreqsDict(source_win_dist)
        else:
            source_win_dist = self.statistics.get_win_distribution(
                self.statistics.get_most_used_ip_address())
            source_win_prob_dict = lea.Lea.fromValFreqsDict(source_win_dist)

        destination_win_dist = self.statistics.get_win_distribution(
            ip_destination)
        if len(destination_win_dist) > 0:
            destination_win_prob_dict = lea.Lea.fromValFreqsDict(
                destination_win_dist)
        else:
            destination_win_dist = self.statistics.get_win_distribution(
                self.statistics.get_most_used_ip_address())
            destination_win_prob_dict = lea.Lea.fromValFreqsDict(
                destination_win_dist)

        # Set MSS (Maximum Segment Size) based on MSS distribution of IP address
        mss_value = Util.handle_most_used_outputs(
            self.statistics.get_most_used_mss_value())
        if not mss_value:
            mss_value = 1465

        # Scan (MS17)
        # Read Win7_eternalblue_scan pcap file
        orig_ip_dst = None
        exploit_raw_packets = scapy.utils.RawPcapReader(
            self.template_scan_pcap_path)
        inter_arrival_times = self.get_inter_arrival_time(exploit_raw_packets)
        exploit_raw_packets.close()
        exploit_raw_packets = scapy.utils.RawPcapReader(
            self.template_scan_pcap_path)

        source_origin_wins, destination_origin_wins = {}, {}

        for self.pkt_num, pkt in enumerate(exploit_raw_packets):
            eth_frame = inet.Ether(pkt[0])
            ip_pkt = eth_frame.payload
            tcp_pkt = ip_pkt.payload

            if self.pkt_num == 0:
                if tcp_pkt.getfieldval("dport") == SMBLib.smb_port:
                    orig_ip_dst = ip_pkt.getfieldval("dst")  # victim IP

            # Request
            if ip_pkt.getfieldval("dst") == orig_ip_dst:  # victim IP
                # Ether
                eth_frame.setfieldval("src", mac_source)
                eth_frame.setfieldval("dst", mac_destination)
                # IP
                ip_pkt.setfieldval("src", ip_source)
                ip_pkt.setfieldval("dst", ip_destination)
                ip_pkt.setfieldval("ttl", source_ttl_value)
                # TCP
                tcp_pkt.setfieldval("sport", port_source)
                tcp_pkt.setfieldval("dport", port_destination)
                # Window Size (mapping)
                source_origin_win = tcp_pkt.getfieldval("window")
                if source_origin_win not in source_origin_wins:
                    source_origin_wins[
                        source_origin_win] = source_win_prob_dict.random()
                new_win = source_origin_wins[source_origin_win]
                tcp_pkt.setfieldval("window", new_win)
                # MSS
                tcp_options = tcp_pkt.getfieldval("options")
                if tcp_options:
                    if tcp_options[0][0] == "MSS":
                        tcp_options[0] = ("MSS", mss_value)
                        tcp_pkt.setfieldval("options", tcp_options)

                new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                new_pkt.time = timestamp_next_pkt

                pps = max(
                    Util.get_interval_pps(complement_interval_pps,
                                          timestamp_next_pkt), 10)
                timestamp_next_pkt = Util.update_timestamp(
                    timestamp_next_pkt, pps) + inter_arrival_times[
                        self.pkt_num]  # float(timeSteps.random())
            # Reply
            else:
                # Ether
                eth_frame.setfieldval("src", mac_destination)
                eth_frame.setfieldval("dst", mac_source)
                # IP
                ip_pkt.setfieldval("src", ip_destination)
                ip_pkt.setfieldval("dst", ip_source)
                ip_pkt.setfieldval("ttl", destination_ttl_value)
                # TCP
                tcp_pkt.setfieldval("dport", port_source)
                tcp_pkt.setfieldval("sport", port_destination)
                # Window Size
                destination_origin_win = tcp_pkt.getfieldval("window")
                if destination_origin_win not in destination_origin_wins:
                    destination_origin_wins[
                        destination_origin_win] = destination_win_prob_dict.random(
                        )
                new_win = destination_origin_wins[destination_origin_win]
                tcp_pkt.setfieldval("window", new_win)
                # MSS
                tcp_options = tcp_pkt.getfieldval("options")
                if tcp_options:
                    if tcp_options[0][0] == "MSS":
                        tcp_options[0] = ("MSS", mss_value)
                        tcp_pkt.setfieldval("options", tcp_options)

                new_pkt = (eth_frame / ip_pkt / tcp_pkt)
                timestamp_next_pkt = Util.update_timestamp(
                    timestamp_next_pkt, pps) + inter_arrival_times[
                        self.pkt_num]  # + float(timeSteps.random())
                new_pkt.time = timestamp_next_pkt

            self.packets.append(new_pkt)

        exploit_raw_packets.close()
Example #28
0
 def test_get_smb_platform_data_win(self):
     guid, blob, cap, d_size, time = SMBLib.get_smb_platform_data("win7", 100)
     self.assertEqual((blob, cap, d_size), (SMBLib.security_blob_windows, 0x7, 0x100000))
     self.assertTrue(isinstance(guid, str) and len(guid) > 0)
     self.assertTrue(time <= Utility.get_filetime_format(100))
Example #29
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        buffer_size = 1000

        # Determine source IP and MAC address
        num_attackers = self.get_param_value(atkParam.Parameter.NUMBER_ATTACKERS)
        if (num_attackers is not None) and (num_attackers is not 0):
            # user supplied atkParam.Parameter.NUMBER_ATTACKERS
            # The most used IP class in background traffic
            most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
            # Create random attackers based on user input atkParam.Parameter.NUMBER_ATTACKERS
            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 atkParam.Parameter.NUMBER_ATTACKS
            # use default values for IP_SOURCE/MAC_SOURCE or overwritten values
            # if user supplied any values for those params
            ip_source_list = self.get_param_value(atkParam.Parameter.IP_SOURCE)
            mac_source_list = self.get_param_value(atkParam.Parameter.MAC_SOURCE)

        # Make sure IPs and MACs are lists
        if not isinstance(ip_source_list, list):
            ip_source_list = [ip_source_list]

        if not isinstance(mac_source_list, list):
            mac_source_list = [mac_source_list]

        # Generate MACs for each IP that has no corresponding MAC yet
        if (num_attackers is None) or (num_attackers is 0):
            if len(ip_source_list) > len(mac_source_list):
                mac_source_list.extend(self.generate_random_mac_address(len(ip_source_list)-len(mac_source_list)))
            num_attackers = min(len(ip_source_list), len(mac_source_list))

        # Initialize parameters
        self.packets = col.deque(maxlen=buffer_size)

        port_source_list = self.get_param_value(atkParam.Parameter.PORT_SOURCE)
        if not isinstance(port_source_list, list):
            port_source_list = [port_source_list]
        mac_destination = self.get_param_value(atkParam.Parameter.MAC_DESTINATION)
        ip_destination = self.get_param_value(atkParam.Parameter.IP_DESTINATION)

        most_used_ip_address = self.statistics.get_most_used_ip_address()
        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)
        if pps == 0:
            result = self.statistics.process_db_query(
                "SELECT MAX(maxPktRate) FROM ip_statistics WHERE ipAddress='" + ip_destination + "';")
            if result is not None and not 0:
                pps = num_attackers * result
            else:
                result = self.statistics.process_db_query(
                    "SELECT MAX(maxPktRate) FROM ip_statistics WHERE ipAddress='" + most_used_ip_address + "';")
                pps = num_attackers * result

        # Calculate complement packet rates of the background traffic for each interval
        attacker_pps = pps / num_attackers
        #complement_interval_attacker_pps = self.statistics.calculate_complement_packet_rates(attacker_pps)

        # Check ip.src == ip.dst
        self.ip_src_dst_catch_equal(ip_source_list, ip_destination)

        port_destination = self.get_param_value(atkParam.Parameter.PORT_DESTINATION)
        if not port_destination:  # user did not define port_dest
            port_destination = self.statistics.process_db_query(
                "SELECT portNumber FROM ip_ports WHERE portDirection='in' AND ipAddress='" + ip_destination +
                "' AND portCount==(SELECT MAX(portCount) FROM ip_ports WHERE portDirection='in' AND ipAddress='" +
                ip_destination + "');")
        if not port_destination:  # no port was retrieved
            port_destination = self.statistics.process_db_query(
                "SELECT portNumber FROM (SELECT portNumber, SUM(portCount) as occ FROM ip_ports WHERE "
                "portDirection='in' GROUP BY portNumber ORDER BY occ DESC) WHERE occ=(SELECT SUM(portCount) "
                "FROM ip_ports WHERE portDirection='in' GROUP BY portNumber ORDER BY SUM(portCount) DESC LIMIT 1);")
        if not port_destination:
            port_destination = max(1, int(inet.RandShort()))

        port_destination = Util.handle_most_used_outputs(port_destination)

        self.path_attack_pcap = None

        victim_buffer = self.get_param_value(atkParam.Parameter.VICTIM_BUFFER)

        attack_duration = self.get_param_value(atkParam.Parameter.ATTACK_DURATION)
        pkts_num = int(pps * attack_duration)

        source_win_sizes = self.statistics.get_rnd_win_size(pkts_num)

        destination_win_dist = self.statistics.get_win_distribution(ip_destination)
        if len(destination_win_dist) > 0:
            destination_win_prob_dict = lea.Lea.fromValFreqsDict(destination_win_dist)
            destination_win_value = destination_win_prob_dict.random()
        else:
            destination_win_value = self.statistics.get_most_used_win_size()

        destination_win_value = Util.handle_most_used_outputs(destination_win_value)

        # MSS that was used by IP destination in background traffic
        mss_dst = self.statistics.get_most_used_mss(ip_destination)
        if mss_dst is None:
            mss_dst = self.statistics.get_most_used_mss_value()

        mss_dst = Util.handle_most_used_outputs(mss_dst)

        # get user defined bandwidth
        bandwidth_max = self.get_param_value(atkParam.Parameter.BANDWIDTH_MAX)
        bandwidth_min_local = self.get_param_value(atkParam.Parameter.BANDWIDTH_MIN_LOCAL)
        bandwidth_min_public = self.get_param_value(atkParam.Parameter.BANDWIDTH_MIN_PUBLIC)

        # check user defined latency
        latency_limit = None
        latency_max = self.get_param_value(atkParam.Parameter.LATENCY_MAX)
        if latency_max != 0:
            latency_limit = latency_max

        # Stores triples of (timestamp, source_id, destination_id) for each timestamp.
        # Victim has id=0. Attacker tuple does not need to specify the destination because it's always the victim.
        timestamps_tuples = []
        # For each attacker(id), stores the current source-ports of SYN-packets
        # which still have to be acknowledged by the victim, as a "FIFO" for each attacker
        previous_attacker_port = []
        replies_count = 0
        self.total_pkt_num = 0
        already_used_pkts = 0
        sum_diff = 0

        self.attack_start_utime = self.get_param_value(atkParam.Parameter.INJECT_AT_TIMESTAMP)
        self.timestamp_controller.set_pps(attacker_pps)
        attack_ends_time = self.timestamp_controller.get_timestamp() + attack_duration

        # For each attacker, generate his own packets, then merge all packets
        for attacker in range(num_attackers):
            # set latency limit to either the minimal latency occurring in the pcap, the default or the user specified limit
            # get minimal and maximal latency found in the pcap
            if not latency_limit:
                min_latency, max_latency = self.get_reply_latency(ip_source_list[attacker], ip_destination)
                latency_limit = min_latency

            # Initialize empty port "FIFO" for current attacker
            previous_attacker_port.append([])
            # Calculate timestamp of first SYN-packet of attacker
            timestamp_next_pkt = self.timestamp_controller.reset_timestamp()
            if attacker != 0:
                timestamp_next_pkt = rnd.uniform(timestamp_next_pkt,
                                                 self.timestamp_controller.next_timestamp(latency=latency_limit))
            # calculate each attackers packet count without exceeding the total number of attackers
            attacker_pkts_num = 0
            if already_used_pkts < pkts_num:
                random_offset = rnd.randint(0, int(pkts_num / num_attackers / 2))
                if attacker == num_attackers-1:
                    random_offset = 0
                attacker_pkts_num = int((pkts_num - already_used_pkts) / (num_attackers - attacker)) + random_offset
                already_used_pkts += attacker_pkts_num
                # each attacker gets a different pps according to his pkt count offset
                ratio = float(attacker_pkts_num) / float(pkts_num)
                attacker_pps = pps * ratio
                self.timestamp_controller.set_pps(attacker_pps)

            for pkt_num in range(attacker_pkts_num):
                # Count attack packets that exceed the attack duration
                if timestamp_next_pkt > attack_ends_time:
                    diff = timestamp_next_pkt-attack_ends_time
                    sum_diff += diff
                    self.exceeding_packets += 1

                # Add timestamp of attacker SYN-packet. Attacker tuples do not need to specify destination
                timestamps_tuples.append((timestamp_next_pkt, attacker+1))

                # Calculate timestamp of victim ACK-packet
                timestamp_reply = self.timestamp_controller.next_timestamp(latency=latency_limit)

                # Add timestamp of victim ACK-packet(victim always has id=0)
                timestamps_tuples.append((timestamp_reply, 0, attacker+1))

                # Calculate timestamp for next attacker SYN-packet
                self.timestamp_controller.set_timestamp(timestamp_next_pkt)
                timestamp_next_pkt = self.timestamp_controller.next_timestamp()

        # Sort timestamp-triples according to their timestamps in ascending order
        timestamps_tuples.sort(key=lambda tmstmp: tmstmp[0])
        self.attack_start_utime = timestamps_tuples[0][0]

        sent_bytes = 0
        previous_interval = 0
        interval_count = 0
        full_interval = None
        reply = None

        # For each triple, generate packet
        for timestamp in timestamps_tuples:
            # tuple layout: [timestamp, attacker_id]

            # If current current triple is an attacker
            if timestamp[1] != 0:

                attacker_id = timestamp[1]-1
                # Build request package
                # Select one IP address and its corresponding MAC address
                ip_source = ip_source_list[attacker_id]
                mac_source = mac_source_list[attacker_id]

                # Determine source port
                (port_source, ttl_value) = Util.get_attacker_config(ip_source_list, ip_source)

                # If source ports were specified by the user, get random port from specified ports
                if port_source_list[0] != self.default_port:
                    port_source = rnd.choice(port_source_list)

                # Push port of current attacker SYN-packet into port "FIFO" of the current attacker
                # only if victim can still respond, otherwise, memory is wasted
                if replies_count <= victim_buffer:
                    previous_attacker_port[attacker_id].insert(0, port_source)

                request_ether = inet.Ether(dst=mac_destination, src=mac_source)
                request_ip = inet.IP(src=ip_source, dst=ip_destination, ttl=ttl_value)
                # Random win size for each packet
                source_win_size = rnd.choice(source_win_sizes)
                request_tcp = inet.TCP(sport=port_source, dport=port_destination, flags='S', ack=0,
                                       window=source_win_size)

                request = (request_ether / request_ip / request_tcp)
                request.time = timestamp[0]

                pkt = request

            # If current triple is the victim
            else:

                # Build reply package
                if replies_count <= victim_buffer:
                    attacker_id = timestamp[2]-1
                    ip_source = ip_source_list[attacker_id]

                    reply_ether = inet.Ether(src=mac_destination, dst=mac_source_list[attacker_id])
                    reply_ip = inet.IP(src=ip_destination, dst=ip_source, flags='DF')
                    # Pop port from attacker's port "FIFO" into destination port
                    reply_tcp = inet.TCP(sport=port_destination, dport=previous_attacker_port[attacker_id].pop(), seq=0,
                                         ack=1, flags='SA', window=destination_win_value, options=[('MSS', mss_dst)])
                    reply = (reply_ether / reply_ip / reply_tcp)

                    reply.time = timestamp[0]

                    pkt = reply

            bytes = len(pkt)

            remaining_bytes, current_interval = self.get_remaining_bandwidth(pkt.time, ip_source, ip_destination,
                                                                             bandwidth_max, bandwidth_min_local,
                                                                             bandwidth_min_public)
            if previous_interval != current_interval:
                sent_bytes = 0
                interval_count += 1

            previous_interval = current_interval

            if current_interval != full_interval:
                remaining_bytes *= 1000
                remaining_bytes -= sent_bytes

                if remaining_bytes >= bytes:
                    sent_bytes += bytes
                    self.packets.append(pkt)
                    self.total_pkt_num += 1
                    if pkt == reply:
                        replies_count += 1
                else:
                    print("Warning: generated attack packets exceeded bandwidth. Packets in interval {} "
                          "were omitted.".format(interval_count))
                    full_interval = current_interval

            # every 1000 packets write them to the pcap file (append)
            if (self.total_pkt_num > 0) and (self.total_pkt_num % buffer_size == 0) and (len(self.packets) > 0):
                self.last_packet = self.packets[-1]
                self.attack_end_utime = self.last_packet.time
                self.packets = sorted(self.packets, key=lambda pkt: pkt.time)
                self.path_attack_pcap = self.write_attack_pcap(self.packets, True, self.path_attack_pcap)
                self.packets = []
Example #30
0
    def generate_attack_packets(self):
        """
        Creates the attack packets.
        """
        # Timestamp
        timestamp_next_pkt = self.get_param_value(
            atkParam.Parameter.INJECT_AT_TIMESTAMP)
        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)

        # Calculate complement packet rates of BG traffic per interval
        complement_interval_pps = self.statistics.calculate_complement_packet_rates(
            pps)

        # Initialize parameters
        self.packets = []
        mac_source = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
        ip_source = self.get_param_value(atkParam.Parameter.IP_SOURCE)
        if isinstance(ip_source, list):
            ip_source = ip_source[0]
        mac_destination = self.get_param_value(
            atkParam.Parameter.MAC_DESTINATION)
        ip_destination = self.get_param_value(
            atkParam.Parameter.IP_DESTINATION)
        if isinstance(ip_destination, list):
            ip_destination = ip_destination[0]
        port_destination = self.get_param_value(
            atkParam.Parameter.PORT_DESTINATION)

        target_host = self.get_param_value(atkParam.Parameter.TARGET_HOST)
        target_uri = "/"  # self.get_param_value(atkParam.Parameter.TARGET_URI)

        # Check ip.src == ip.dst
        self.ip_src_dst_equal_check(ip_source, ip_destination)

        # Set TTL based on TTL distribution of IP address
        source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
        if len(source_ttl_dist) > 0:
            source_ttl_prob_dict = lea.Lea.fromValFreqsDict(source_ttl_dist)
            source_ttl_value = source_ttl_prob_dict.random()
        else:
            source_ttl_value = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ttl_value())

        destination_ttl_dist = self.statistics.get_ttl_distribution(
            ip_destination)
        if len(destination_ttl_dist) > 0:
            destination_ttl_prob_dict = lea.Lea.fromValFreqsDict(
                destination_ttl_dist)
            destination_ttl_value = destination_ttl_prob_dict.random()
        else:
            destination_ttl_value = Util.handle_most_used_outputs(
                self.statistics.get_most_used_ttl_value())

        # Inject SQLi Attack
        # Read SQLi Attack pcap file
        orig_ip_dst = None
        exploit_raw_packets = scapy.utils.RawPcapReader(
            self.template_attack_pcap_path)
        inter_arrival_times, inter_arrival_time_dist = self.get_inter_arrival_time(
            exploit_raw_packets, True)
        time_steps = lea.Lea.fromValFreqsDict(inter_arrival_time_dist)
        exploit_raw_packets.close()
        exploit_raw_packets = scapy.utils.RawPcapReader(
            self.template_attack_pcap_path)

        port_source = rnd.randint(
            self.minDefaultPort,
            self.maxDefaultPort)  # experiments show this range of ports

        # Random TCP sequence numbers
        global attacker_seq
        attacker_seq = rnd.randint(1000, 50000)
        global victim_seq
        victim_seq = rnd.randint(1000, 50000)

        for self.pkt_num, pkt in enumerate(exploit_raw_packets):
            eth_frame = inet.Ether(pkt[0])
            ip_pkt = eth_frame.payload
            tcp_pkt = ip_pkt.payload
            str_tcp_seg = str(tcp_pkt.payload)

            # Clean payloads
            eth_frame.payload = b''
            ip_pkt.payload = b''
            tcp_pkt.payload = b''

            # FIXME: no getfieldval in class bytes
            if self.pkt_num == 0:
                prev_orig_port_source = tcp_pkt.getfieldval("sport")
                orig_ip_dst = ip_pkt.getfieldval("dst")  # victim IP

            # Last connection
            if tcp_pkt.getfieldval("dport") != 80 and tcp_pkt.getfieldval(
                    "sport") != 80:
                # New connection, new random TCP sequence numbers
                attacker_seq = rnd.randint(1000, 50000)
                victim_seq = rnd.randint(1000, 50000)
                # First packet in a connection has ACK = 0
                tcp_pkt.setfieldval("ack", 0)

            # Attacker --> vicitm
            if ip_pkt.getfieldval("dst") == orig_ip_dst:  # victim IP

                # There are 363 TCP connections with different source ports, for each of them we generate random port
                if tcp_pkt.getfieldval("sport") != prev_orig_port_source and tcp_pkt.getfieldval("dport") != 4444 \
                        and (tcp_pkt.getfieldval("dport") == 80 or tcp_pkt.getfieldval("sport") == 80):
                    port_source = rnd.randint(self.minDefaultPort,
                                              self.maxDefaultPort)
                    prev_orig_port_source = tcp_pkt.getfieldval("sport")
                    # New connection, new random TCP sequence numbers
                    attacker_seq = rnd.randint(1000, 50000)
                    victim_seq = rnd.randint(1000, 50000)
                    # First packet in a connection has ACK = 0
                    tcp_pkt.setfieldval("ack", 0)

                # Ether
                eth_frame.setfieldval("src", mac_source)
                eth_frame.setfieldval("dst", mac_destination)
                # IP
                ip_pkt.setfieldval("src", ip_source)
                ip_pkt.setfieldval("dst", ip_destination)
                ip_pkt.setfieldval("ttl", source_ttl_value)

                # TCP

                # Regular connection
                if tcp_pkt.getfieldval("dport") == 80 or tcp_pkt.getfieldval(
                        "sport") == 80:
                    tcp_pkt.setfieldval("sport", port_source)
                    tcp_pkt.setfieldval("dport", port_destination)

                str_tcp_seg = self.modify_http_header(str_tcp_seg, '/ATutor',
                                                      target_uri, orig_ip_dst,
                                                      target_host)

                # TCP Seq, Ack
                if tcp_pkt.getfieldval("ack") != 0:
                    tcp_pkt.setfieldval("ack", victim_seq)
                tcp_pkt.setfieldval("seq", attacker_seq)
                if not (tcp_pkt.getfieldval("flags") == 16
                        and len(str_tcp_seg) == 0):  # flags=A:
                    attacker_seq += max(len(str_tcp_seg), 1)

                new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
                new_pkt.time = timestamp_next_pkt

                pps = max(
                    Util.get_interval_pps(complement_interval_pps,
                                          timestamp_next_pkt), 10)
                timestamp_next_pkt = Util.update_timestamp(
                    timestamp_next_pkt, pps) + float(time_steps.random())

            # Victim --> attacker
            else:
                # Ether
                eth_frame.setfieldval("src", mac_destination)
                eth_frame.setfieldval("dst", mac_source)
                # IP
                ip_pkt.setfieldval("src", ip_destination)
                ip_pkt.setfieldval("dst", ip_source)
                ip_pkt.setfieldval("ttl", destination_ttl_value)

                # TCP

                # Regular connection
                if tcp_pkt.getfieldval("dport") == 80 or tcp_pkt.getfieldval(
                        "sport") == 80:
                    tcp_pkt.setfieldval("dport", port_source)
                    tcp_pkt.setfieldval("sport", port_destination)

                str_tcp_seg = self.modify_http_header(str_tcp_seg, '/ATutor',
                                                      target_uri, orig_ip_dst,
                                                      target_host)

                # TCP Seq, ACK
                tcp_pkt.setfieldval("ack", attacker_seq)
                tcp_pkt.setfieldval("seq", victim_seq)
                strLen = len(str_tcp_seg)
                if not (tcp_pkt.getfieldval("flags") == 16
                        and strLen == 0):  # flags=A:
                    victim_seq += max(strLen, 1)

                new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
                timestamp_next_pkt = Util.update_timestamp(
                    timestamp_next_pkt, pps) + float(time_steps.random())
                new_pkt.time = timestamp_next_pkt

            self.packets.append(new_pkt)

        exploit_raw_packets.close()