Exemple #1
0
    def __send_unencrypted_ack(self):
        chlo = ACKPacket()
        conf.L3socket = L3RawSocket

        chlo.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))
        chlo.setfieldval(
            "Packet Number",
            PacketNumberInstance.get_instance().get_next_packet_number())

        # print("First Ack Packet Number {}".format(int(str(PacketNumberInstance.get_instance().highest_received_packet_number), 16)))
        chlo.setfieldval(
            'Largest Acked',
            int(
                str(PacketNumberInstance.get_instance().
                    highest_received_packet_number), 16))
        chlo.setfieldval(
            'First Ack Block Length',
            int(
                str(PacketNumberInstance.get_instance().
                    highest_received_packet_number), 16))

        associated_data = extract_from_packet(chlo, end=15)
        body = extract_from_packet(chlo, start=27)

        message_authentication_hash = FNV128A().generate_hash(
            associated_data, body, True)
        chlo.setfieldval('Message Authentication Hash',
                         string_to_ascii(message_authentication_hash))

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121, sport=61250) / chlo
        send(p)
Exemple #2
0
    def handle_received_encrypted_packet(self, packet):
        a = AEADPacketDynamic(packet[0][1][1].payload.load)
        a.parse()
        # print(">>>>>>>> Received packet with MAH: {}".format(a.get_field(AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)))

        # Start key derixvation
        SessionInstance.get_instance().div_nonce = a.get_field(
            AEADFieldNames.DIVERSIFICATION_NONCE)
        SessionInstance.get_instance(
        ).message_authentication_hash = a.get_field(
            AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)
        packet_number = a.get_field(AEADFieldNames.PACKET_NUMBER)
        SessionInstance.get_instance().packet_number = packet_number
        # print("Packet Number {}".format(packet_number))
        SessionInstance.get_instance(
        ).largest_observed_packet_number = packet_number
        SessionInstance.get_instance().associated_data = a.get_associated_data(
        )
        # print("Associated Data {}".format(SessionInstance.get_instance().associated_data))
        ciphertext = split_at_nth_char(
            a.get_field(AEADFieldNames.ENCRYPTED_FRAMES))

        # print("Received peer public value {}".format(SessionInstance.get_instance().peer_public_value))
        dhke.generate_keys(SessionInstance.get_instance().peer_public_value,
                           SessionInstance.get_instance().shlo_received)
        # SessionInstance.get_instance().packet_number = packet_number

        # Process the streams
        processor = FramesProcessor(ciphertext)
        processor.process()
Exemple #3
0
    def reset(self, reset_server, reset_run=True):
        # also reset the server
        if reset_server:
            # remove the previous session
            CacheInstance.get_instance().remove_session_model()
            filename = str(time.time())
            open('resets/{}'.format(filename), 'a')
            time.sleep(8)

        if reset_run:
            # For the three times a command we do not want to remove the run events, only when there is a complete reset
            # which occurs after an iteration or after an explicit RESET command.
            self.run_events = []

        self.run = ""
        self.previous_result = ""
        PacketNumberInstance.get_instance().reset()
        conn_id = random.getrandbits(64)
        SessionInstance.get_instance().shlo_received = False
        SessionInstance.get_instance().scfg = ""
        SessionInstance.get_instance().zero_rtt = False
        self.logger.info("Changing CID from {}".format(
            SessionInstance.get_instance().connection_id))
        SessionInstance.get_instance().connection_id_as_number = conn_id
        SessionInstance.get_instance().connection_id = str(
            format(conn_id, 'x').zfill(16))  # Pad to 16 chars
        self.logger.info("To {}".format(
            SessionInstance.get_instance().connection_id))
Exemple #4
0
    def send_chlo(self, only_reset):
        # print("Only reset? {}".format(only_reset))
        self.reset(only_reset)

        if only_reset:
            self.learner.respond("RESET")
            return

        # print(SessionInstance.get_instance().connection_id)

        # print("Sending CHLO")
        chlo = QUICHeader()
        conf.L3socket = L3RawSocket

        chlo.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))
        chlo.setfieldval(
            "Packet Number",
            PacketNumberInstance.get_instance().get_next_packet_number())

        associated_data = extract_from_packet(chlo, end=15)
        body = extract_from_packet(chlo, start=27)

        message_authentication_hash = FNV128A().generate_hash(
            associated_data, body)
        chlo.setfieldval('Message Authentication Hash',
                         string_to_ascii(message_authentication_hash))

        # Store chlo for the key derivation
        SessionInstance.get_instance(
        ).chlo = extract_from_packet_as_bytestring(chlo)
        self.sniffer.add_observer(self)

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121, sport=61250) / chlo
        send(p)
        self.wait_for_signal_or_expiration()
        self.processed = False
        self.sniffer.remove_observer(self)
Exemple #5
0
    def close_connection(self):
        """
        We do this the unfriendly way, since GoAway does not work. friendly way by means of a Go Away
        :return:
        """
        frame_data = "02"  # frame type
        frame_data += "00000000"  # error code, no error
        # frame_data += "00000000"    # latest responded stream Id
        frame_data += "0000"  # No reason therefore length of 0

        # encrypt it
        packet_number = PacketNumberInstance.get_instance(
        ).get_next_packet_number()
        ciphertext = CryptoManager.encrypt(bytes.fromhex(frame_data),
                                           packet_number,
                                           SessionInstance.get_instance(),
                                           self.logger)

        a = AEADRequestPacket()
        a.setfieldval("Public Flags", 0x18)
        a.setfieldval('Packet Number', packet_number)
        a.setfieldval("Message Authentication Hash",
                      string_to_ascii(ciphertext[0:24]))
        a.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))

        self.logger.info("Closing connection {}".format(
            SessionInstance.get_instance().connection_id))

        self.logger.info("With ciphertext {}".format(ciphertext))
        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121,
            sport=61250) / a / Raw(load=string_to_ascii(ciphertext[24:]))
        # ans, _ = sr(p, count=3)
        send(p)
        self.wait_for_signal_or_expiration()
        self.processed = False
        self.sniffer.remove_observer(self)
        time.sleep(1)
Exemple #6
0
    def send_ping(self):
        print("Sending ping message...")
        ping = PingPacket()
        ping.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))

        packet_number = PacketNumberInstance.get_instance(
        ).get_next_packet_number()
        ciphertext = CryptoManager.encrypt(bytes.fromhex("07"), packet_number,
                                           SessionInstance.get_instance())

        ping.setfieldval('Packet Number', packet_number)
        ping.setfieldval("Message Authentication Hash",
                         string_to_ascii(ciphertext[:24]))

        conf.L3socket = L3RawSocket
        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121,
            sport=61250) / ping / Raw(load=string_to_ascii(ciphertext[24:]))
        # Maybe we cannot assume that is just a version negotiation packet?
        send(p)
Exemple #7
0
    def make_get_request(self):
        get_request = "800300002501250000000500000000FF418FF1E3C2E5F23A6BA0AB9EC9AE38110782848750839BD9AB7A85ED6988B4C7"
        packet_number = PacketNumberInstance.get_instance(
        ).get_next_packet_number()
        ciphertext = CryptoManager.encrypt(bytes.fromhex(get_request),
                                           packet_number, self.__instance)

        # Send it to the server
        a = AEADRequestPacket()
        a.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))
        a.setfieldval("Public Flags", 0x18)
        a.setfieldval('Packet Number', packet_number)
        a.setfieldval("Message Authentication Hash",
                      string_to_ascii(ciphertext[0:24]))

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121,
            sport=61250) / a / Raw(load=string_to_ascii(ciphertext[24:]))
        # self.__sniffer.add_observer(self)
        send(p)
Exemple #8
0
    def send_second_ack(self):
        chlo = SecondACKPacket()
        conf.L3socket = L3RawSocket

        chlo.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))
        chlo.setfieldval(
            "Packet Number",
            PacketNumberInstance.get_instance().get_next_packet_number())

        associated_data = extract_from_packet(chlo, end=15)
        body = extract_from_packet(chlo, start=27)

        message_authentication_hash = FNV128A().generate_hash(
            associated_data, body)
        chlo.setfieldval('Message Authentication Hash',
                         string_to_ascii(message_authentication_hash))

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121, sport=61250) / chlo
        send(p)
    def parse(self):
        """
        :return:
        """
        tags = []
        self.parse_type()
        tag = self.read_byte(4)
        if tag == "53484c4f":
            tag_number = self.read_byte(2)
            tag_number = struct.unpack("<h", bytes.fromhex(tag_number))[
                0]  # Number of tags that need to be processed
            self.read_byte(2)

            offset = 0
            for i in range(0, tag_number):
                tag = bytes.fromhex(self.read_byte(4))
                length = struct.unpack("<i",
                                       bytes.fromhex(self.read_byte(4)))[0]

                length = length - offset
                offset += length

                tags.append({'tag': tag, 'length': length})

            for tag in tags:
                tag['value'] = self.read_byte(tag['length'])
                if "PUBS".encode('utf-8') in tag['tag']:
                    SessionInstance.get_instance(
                    ).peer_public_value = bytes.fromhex(tag['value'])
                elif "SNO".encode('utf-8') in tag['tag']:
                    SessionInstance.get_instance().server_nonce = tag['value']
            print(tags)
            SessionInstance.get_instance(
            ).last_received_shlo = SessionInstance.get_instance(
            ).message_authentication_hash

            return True
        return False
Exemple #10
0
 def send_message(endpoint, msg: bytes, expect_answer=False):
     if endpoint == ConnectionEndpoint.CRYPTO_ORACLE or True:
         print("Sending message ...")
         crypto_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         crypto_socket.connect(
             (SessionInstance.get_instance().destination_ip, 3030))
         crypto_socket.send(msg)
         if expect_answer:
             # Arbitrary big sized buffer
             print("Waiting for response...")
             data = crypto_socket.recv(555555)
             decoded_data = data.decode('utf-8')
             return json.loads(decoded_data)
         crypto_socket.close()
     else:
         raise NotImplementedError("Currently only Crypto Oracle")
Exemple #11
0
    def send_full_chlo(self):
        chlo = FullCHLOPacket()

        chlo.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))
        chlo.setfieldval('SCID_Value',
                         SessionInstance.get_instance().server_config_id)
        chlo.setfieldval('STK_Value',
                         SessionInstance.get_instance().source_address_token)

        # Lets just create the public key for DHKE
        dhke.set_up_my_keys()

        chlo.setfieldval(
            "Packet Number",
            PacketNumberInstance.get_instance().get_next_packet_number())
        chlo.setfieldval(
            'PUBS_Value',
            string_to_ascii(
                SessionInstance.get_instance().public_values_bytes))

        associated_data = extract_from_packet(chlo, end=15)
        body = extract_from_packet(chlo, start=27)

        message_authentication_hash = FNV128A().generate_hash(
            associated_data, body)
        chlo.setfieldval('Message Authentication Hash',
                         string_to_ascii(message_authentication_hash))

        conf.L3socket = L3RawSocket
        SessionInstance.get_instance(
        ).chlo = extract_from_packet_as_bytestring(
            chlo, start=31
        )  # CHLO from the CHLO tag, which starts at offset 26 (22 header + frame type + stream id + offset)

        # print("Send full CHLO")

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121, sport=61250) / chlo
        # Maybe we cannot assume that is just a version negotiation packet?
        # ans, _ = sr(p)
        self.sniffer.add_observer(self)
        send(p)
        self.wait_for_signal_or_expiration()

        self.processed = False
        self.sniffer.remove_observer(self)
Exemple #12
0
    def packet_update(self, packet):
        # print("Received update from the Sniffer thread")
        a = AEADPacketDynamic(packet[0][1][1].payload.load)
        a.parse()
        print(">>>>>>>> Received packet with MAH: {}".format(
            a.get_field(AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)))

        # Start key derixvation
        SessionInstance.get_instance().div_nonce = a.get_field(
            AEADFieldNames.DIVERSIFICATION_NONCE)
        SessionInstance.get_instance(
        ).message_authentication_hash = a.get_field(
            AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)
        packet_number = a.get_field(AEADFieldNames.PACKET_NUMBER)
        SessionInstance.get_instance().packet_number = packet_number
        SessionInstance.get_instance(
        ).largest_observed_packet_number = packet_number

        # print(">>>><<<!!!! Updating highest received packet number to {}".format(int(packet_number, 16)))
        # PacketNumberInstance.get_instance().update_highest_received_packet_number(int(packet_number, 16))

        dhke.generate_keys(SessionInstance.get_instance().peer_public_value,
                           SessionInstance.get_instance().shlo_received)

        SessionInstance.get_instance().associated_data = a.get_associated_data(
        )
        SessionInstance.get_instance().packet_number = packet_number
        # Process the streams
        processor = FramesProcessor(
            split_at_nth_char(a.get_field(AEADFieldNames.ENCRYPTED_FRAMES)))
        processor.process(self)

        # print("GETTER received packets {}".format(self.__received_packets))
        if self.__received_packets < 3:
            self.__received_packets += 1
        else:
            self.__sniffer.remove_observer(self)
            self.send_ack()
Exemple #13
0
 def process(self):
     """
     Assumption, the stream frame is last. FIXME
     :return:
     """
     # Add stream Id == 1 check
     # Set the stream Id. It starts after the header (byte 27), after the byte frame type (28).
     try:
         was_shlo = SHLOPacketProcessor(self.packet_body).parse()
         SessionInstance.get_instance().shlo_received = was_shlo
         if was_shlo:
             self.status = "shlo"
         else:
             self.status = "unknown"
     except NotSHLOButHtmlException as err:
         # If we catch the exception, then it is not a SHLO (Stream ID != 1)
         self.status = "http"
     except NotHtmlNorSHLOException as err:
         # We don't know what it is.
         self.status = "unknown"
     except NotSHLOButCloseException as err:
         self.status = "close"
Exemple #14
0
    def send_full_chlo_to_existing_connection(self):
        """
        Is it sent encrypted?
        :return:
        """
        try:
            previous_session = SessionModel.get(SessionModel.id == 1)
            self.logger.info(previous_session)
            self.logger.info("Server config Id {}".format(
                previous_session.server_config_id))
            self.logger.info(SessionInstance.get_instance().app_keys)
            SessionInstance.get_instance(
            ).last_received_rej = "-1"  # I want to force the sniffer to generate a new set of keys.
            SessionInstance.get_instance().zero_rtt = True

            # The order is important!
            tags = [
                {
                    'name':
                    'PAD',
                    'value':
                    '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
                },
                {
                    'name': 'SNI',
                    'value': '7777772e6578616d706c652e6f7267'
                },
                {
                    'name': 'STK',
                    'value': previous_session.source_address_token
                },
                {
                    'name': 'SNO',
                    'value': previous_session.server_nonce
                },
                {
                    'name': 'VER',
                    'value': '00000000'
                },
                {
                    'name': 'CCS',
                    'value': '01e8816092921ae87eed8086a2158291'
                },
                {
                    'name':
                    'NONC',
                    'value':
                    '5ac349e90091b5556f1a3c52eb57f92c12640e876e26ab2601c02b2a32f54830'
                },
                {
                    'name': 'AEAD',
                    'value': '41455347'  # AESGCM12
                },
                {
                    'name': 'SCID',
                    'value': previous_session.server_config_id
                },
                {
                    'name': 'PDMD',
                    'value': '58353039'
                },
                {
                    'name': 'ICSL',
                    'value': '1e000000'
                },
                {
                    'name':
                    'PUBS',
                    'value':
                    '96D49F2CE98F31F053DCB6DFE729669385E5FD99D5AA36615E1A9AD57C1B090C'
                },
                {
                    'name': 'MIDS',
                    'value': '64000000'
                },
                {
                    'name': 'KEXS',
                    'value': '43323535'  # C25519
                },
                {
                    'name': 'XLCT',
                    'value': '8d884a6c79a0e6de'
                },
                {
                    'name': 'CFCW',
                    'value': '00c00000'
                },
                {
                    'name': 'SFCW',
                    'value': '00800000'
                },
            ]

            d = DynamicCHLOPacket(tags)
            body = d.build_body()
            PacketNumberInstance.get_instance().reset()

            conn_id = random.getrandbits(64)
            SessionInstance.get_instance(
            ).server_nonce = previous_session.server_nonce
            SessionInstance.get_instance().connection_id_as_number = conn_id
            SessionInstance.get_instance().connection_id = str(
                format(conn_id, 'x').zfill(8))
            SessionInstance.get_instance().peer_public_value = bytes.fromhex(
                previous_session.public_value)
            self.logger.info("Using connection Id {}".format(
                SessionInstance.get_instance().connection_id))
            SessionInstance.get_instance().shlo_received = False
            # SessionInstance.get_instance().zero_rtt = True  # This one should only be set if the Zero RTT CHLO does not result in a REJ.
            #
            a = FullCHLOPacketNoPadding()
            a.setfieldval(
                'Packet Number',
                PacketNumberInstance.get_instance().get_next_packet_number())
            a.setfieldval(
                'CID',
                string_to_ascii(SessionInstance.get_instance().connection_id))

            # # Lets just create the public key for DHKE
            dhke.set_up_my_keys()

            associated_data = extract_from_packet(a, end=15)
            body_mah = [body[i:i + 2] for i in range(0, len(body), 2)]
            message_authentication_hash = FNV128A().generate_hash(
                associated_data, body_mah)

            conf.L3socket = L3RawSocket
            SessionInstance.get_instance(
            ).chlo = extract_from_packet_as_bytestring(
                a, start=27
            )  # CHLO from the CHLO tag, which starts at offset 26 (22 header + frame type + stream id + offset)
            SessionInstance.get_instance().chlo += body[4:]

            # dhke.generate_keys(bytes.fromhex(previous_session.public_value), False)
            # ciphertext = CryptoManager.encrypt(bytes.fromhex(SessionInstance.get_instance().chlo), 1)
            #
            a.setfieldval('Message Authentication Hash',
                          string_to_ascii(message_authentication_hash))
            #
            # print("Send full CHLO from existing connection")
            #
            p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
                dport=6121, sport=61250) / a / Raw(load=string_to_ascii(body))
            # # Maybe we cannot assume that is just a version negotiation packet?
            self.sniffer.add_observer(self)
            send(p)
            self.wait_for_signal_or_expiration()

            self.processed = False
            self.sniffer.remove_observer(self)
        except Exception:
            self.send_chlo(False)
Exemple #15
0
    def inform_observer(self, packet):
        parsed_packet = AEADPacketDynamic(packet[0][1][1].payload.load)
        parsed_packet.parse()
        if parsed_packet.get_field(
                AEADFieldNames.CID) == SessionInstance.get_instance(
                ).connection_id:
            self.__logger.info("Received packet with MAH {}".format(
                parsed_packet.get_field(
                    AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)))
            print(">>>>>>>> Received packet with MAH: {}".format(
                parsed_packet.get_field(
                    AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)))
            self.__packet_instance.highest_received_packet_number = parsed_packet.get_field(
                AEADFieldNames.PACKET_NUMBER)

            # Catch the Public Reset packet, flags == 0x0e && TAG == PRST (50525354)
            # print("Parsed packet Public Flags {}".format(parsed_packet.get_field(AEADFieldNames.PUBLIC_FLAGS)))
            if parsed_packet.get_field(AEADFieldNames.PUBLIC_FLAGS) == "0e":
                # check if the tag is equal to the PRST
                tag = parsed_packet.packet_body[9:13]
                if tag == b'PRST':
                    self.__logger.info("Parsed as PRST")
                    # Public Reset Packet
                    for observer in self.__observers:
                        observer.update("", "PRST")
                    return

            if SessionInstance.get_instance(
            ).shlo_received or parsed_packet.has_field(
                    AEADFieldNames.DIVERSIFICATION_NONCE):
                threading.Thread(target=self.__send_encrypted_ack,
                                 args=()).start()
                result = self.__handle_encrypted_packet(parsed_packet)
                self.__logger.info("Parsed as encrypted packet")
                for observer in self.__observers:
                    # print("Result {}".format(result))
                    observer.update("", result)
            else:
                # Add a check if it is really a REJ or just garbage
                try:
                    threading.Thread(target=self.__send_unencrypted_ack,
                                     args=()).start()
                    rej_packet = RejectionPacket(packet[0][1][1].payload.load)
                    rej_tag = rej_packet.getfieldval('Tag_1')
                    if rej_tag == b'REJ\x00':
                        # print("REJ Received")
                        SessionInstance.get_instance(
                        ).last_received_rej = parsed_packet.get_field(
                            AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)
                        self.__logger.info("Parsed as REJ packet")
                        # if not SessionInstance.get_instance().currently_sending_zero_rtt:
                        self.__handle_rej_packet(rej_packet)
                        for observer in self.__observers:
                            observer.update("", "REJ")
                    else:
                        self.__logger.info("Parsed as Garbage")
                        threading.Thread(target=self.__send_unencrypted_ack,
                                         args=()).start()
                        # print("Garbage received, ack has been sent.")
                except Exception:
                    self.__logger.info("Parsed as closed. Not a REJ packet.")
                    # Considered as garbage.
                    # Maybe its not a REJ packet
                    # for observer in self.__observers:
                    #     observer.update("", "closed")
        else:
            self.__logger.info("Discarding old connection id message received")
Exemple #16
0
    def send_ack_for_encrypted_message(self):
        ack = AckNotificationPacket()
        conf.L3socket = L3RawSocket

        ack.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))

        next_packet_number_int = PacketNumberInstance.get_instance(
        ).get_next_packet_number()
        next_packet_number_byte = int(next_packet_number_int).to_bytes(
            8, byteorder='little')
        next_packet_number_nonce = int(next_packet_number_int).to_bytes(
            2, byteorder='big')
        # print("Sending encrypted ack for packet number {}".format(next_packet_number_int))

        ack.setfieldval("Packet Number", next_packet_number_int)
        highest_received_packet_number = format(
            int(
                PacketNumberInstance.get_instance().
                get_highest_received_packet_number(), 16), 'x')

        ack_body = "40"
        ack_body += str(highest_received_packet_number).zfill(2)
        ack_body += "0062"
        ack_body += str(highest_received_packet_number).zfill(2)
        ack_body += "00"
        # not sure yet if we can remove this?

        keys = SessionInstance.get_instance().keys

        request = {
            'mode':
            'encryption',
            'input':
            ack_body,
            'key':
            keys['key1'].hex(),  # For encryption, we use my key
            'additionalData':
            "18" + SessionInstance.get_instance().connection_id +
            next_packet_number_byte.hex()
            [:4],  # Fixed public flags 18 || fixed connection Id || packet number
            'nonce':
            keys['iv1'].hex() + next_packet_number_nonce.hex().ljust(16, '0')
        }

        # print("Ack request for encryption {}".format(request))

        ciphertext = CryptoConnectionManager.send_message(
            ConnectionEndpoint.CRYPTO_ORACLE,
            json.dumps(request).encode('utf-8'), True)
        ciphertext = ciphertext['data']
        # print("Ciphertext in ack {}".format(ciphertext))

        ack.setfieldval("Message Authentication Hash",
                        string_to_ascii(ciphertext[:24]))
        SessionInstance.get_instance().nr_ack_send += 1

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121,
            sport=61250) / ack / Raw(load=string_to_ascii(ciphertext[24:]))
        send(p)
Exemple #17
0
    def wait_for_signal_or_expiration(self):
        # wait for a specific time otherwise
        start = time.time()
        expired = False
        print(self.run_results)
        while not self.processed and not expired:
            if time.time() - start >= self.TIMEOUT:
                expired = True
        if expired:
            # print("General expired")
            if len(self.run_results) == 3 or True:
                # Get the majority element
                c = Counter(self.run_results)
                value, count = c.most_common()[0]
                self.learner.respond(value)
                self.logger.info("General expired")
                self.run += str(self.current_event)
                # self.ndc.add_run(self.run, value)
                self.run_results = []
                self.previous_result = value
                # self.reset(True, False)    # Reset the server
            else:
                self.run_results.append("EXP")
                self.logger.info(
                    "Received first time {} launching again".format("EXP"))
                time.sleep(2)
                self.logger.info("Run events {}".format(self.run_events))
                # if not isinstance(self.current_event, SendGETRequestEvent):
                self.send(self.current_event, True)
        else:
            # print("General response {}".format(self.result))
            self.logger.info("Currently at run results {}".format(
                self.run_results))
            self.logger.info("Current running event {}".format(
                self.current_event))
            self.logger.info("Previous result {}".format(self.previous_result))
            if isinstance(self.current_event, CloseConnectionEvent):
                if self.previous_result == "EXP":
                    self.learner.respond("closed")
                    self.run_results = []
                    return
            if isinstance(self.current_event, SendGETRequestEvent):
                # Does not need multiple times, as only the first time we get an HTTP response
                if self.previous_result == "EXP":
                    self.learner.respond("EXP")
                    self.run_results = []
                    return
                elif self.result == "REJ":
                    self.learner.respond("EXP")
                    self.run_results = []
                    self.result = ""
                    return
                elif self.previous_result == "shlo":
                    self.learner.respond("http")
                    self.previous_result = "http"
                    self.result = ""
                    self.run_results = []
                    return
                else:
                    self.learner.respond(self.result)
                    self.previous_result = self.result
                    self.result = ""
                    self.run_results = []
                    return
            if isinstance(self.current_event, SendInitialCHLOEvent):
                # Does not really need to send multiple times
                if self.previous_result == "":
                    self.learner.respond("REJ")
                    self.previous_result = "REJ"
                    self.result = ""
                    self.run_results = []
                    return
            if isinstance(self.current_event, SendFullCHLOEvent):
                # If it is a full CHLO and we receive a SHLO. Do not send it again
                if self.result == "http":
                    self.learner.respond("EXP")
                    self.result = ""
                    self.run_results = []
                    return

                elif self.previous_result == "EXP":
                    self.learner.respond("EXP")
                    self.previous_result = "EXP"
                    self.run_results = []
                    return

                elif self.previous_result == "shlo":
                    self.learner.respond("EXP")
                    self.previous_result = "EXP"
                    self.run_results = []
                    return

                elif self.previous_result == "" or self.previous_result == "PRST":
                    self.learner.respond("PRST")
                    self.result = ""
                    self.run_results = []
                    return

                if self.result == "shlo":
                    self.learner.respond("shlo")
                    self.run_results = []
                    self.previous_result = "shlo"
                    return

            if isinstance(self.current_event, ZeroRTTCHLOEvent):
                # We can only send this once, otherwise the second time it will automatically send it as a full message
                SessionInstance.get_instance(
                ).currently_sending_zero_rtt = False
                if self.result == "REJ" or self.result == "shlo":
                    self.learner.respond(self.result)
                    self.previous_result = self.result
                    self.run_results = []
                    return

            if len(self.run_results) == 2 and isinstance(
                    self.current_event, ZeroRTTCHLOEvent):
                # We actually need it, otherwise a subsequent Full CHLO will not result in a SHLO.
                SessionInstance.get_instance(
                ).currently_sending_zero_rtt = False
            if len(self.run_results) == 3 or True:
                # Get the majority element
                if self.run_results.count("EXP") < 3:
                    self.run_results = [
                        x for x in self.run_results if 'EXP' != x
                    ]
                c = Counter(self.run_results)
                value, count = c.most_common()[0]
                if isinstance(self.current_event, SendGETRequestEvent):
                    # If there is atleast one HTTP response, then it is a HTTP response.
                    # Because the server didn't respond to three subsequent GET requests.
                    if "http" in self.run_results:
                        value = "http"
                    if "REJ" in self.run_results:
                        if self.run_results.count("REJ") == len(
                                self.run_results):
                            value = "EXP"
                        else:
                            # remove all the REJs
                            value = list(
                                filter(lambda a: a != 'REJ',
                                       self.run_results))[0]
                    if self.previous_result == "shlo" and "http" not in self.run_results:
                        value = "http"

                if isinstance(self.current_event, ZeroRTTCHLOEvent):
                    SessionInstance.get_instance(
                    ).currently_sending_zero_rtt = False
                    if value == "REJ":
                        SessionInstance.get_instance().zero_rtt = False
                    elif value == "shlo":
                        SessionInstance.get_instance().zero_rtt = True

                    if self.previous_result == "REJ" and value != "shlo":
                        value = "shlo"
                    elif self.previous_result == "shlo":
                        value = "shlo"
                    elif value == "EXP":
                        value = "REJ"

                self.learner.respond(value)
                self.logger.info("Responding to learner {}".format(value))
                # self.run += str(self.current_event)
                # self.ndc.add_run(self.run, value)
                self.previous_result = value
                self.run_results = []
                # self.reset(True, False)
            else:
                self.run_results.append(self.result)
                self.logger.info(
                    "Received first time {} launching again".format(
                        self.result))
                time.sleep(2)
                self.logger.info("Run events {}".format(self.run_events))
                # if not isinstance(self.current_event, SendGETRequestEvent):
                self.send(self.current_event, True)

        self.logger.info("=========== Request Finished ===========")
        self.result = ""
Exemple #18
0
    def __handle_rej_packet(self, a):
        self.__logger.info("Storing REJ information from packet {}".format(
            a.getfieldval('Message Authentication Hash')))
        for key, value in a.fields.items():
            if "Server_Config_ID" in key:
                SessionInstance.get_instance().server_config_id = value
                self.__logger.info("STORING: ServerConfigId {}".format(value))
            if "Source_Address_Token" in key:
                SessionInstance.get_instance().source_address_token = value
                self.__logger.info("STORING: SATKOK {}".format(value))

            if "Server_Nonce" in key:
                SessionInstance.get_instance().server_nonce = value.hex()
                self.__logger.info("STORING: SNONCE {}".format(value))
            if "Public_Value" in key:
                # Has length 35, remove the first 4 bytes which only indicate the length of 32 bytes.
                SessionInstance.get_instance(
                ).peer_public_value = bytes.fromhex(value[3:].hex())
                self.__logger.info("Public value used for DHKE {}".format(
                    value[3:].hex()))

        # Store it locally, such that in a next CHLO we can directly use it.
        CacheInstance.get_instance().add_session_model(
            SessionModel(
                source_address_token=SessionInstance.get_instance(
                ).source_address_token.hex(),
                server_nonce=SessionInstance.get_instance().server_nonce,
                server_config_id=SessionInstance.get_instance(
                ).server_config_id.hex(),
                public_value=SessionInstance.get_instance(
                ).peer_public_value.hex(),
                connection_id=SessionInstance.get_instance().connection_id))

        if SessionInstance.get_instance().scfg == "":
            SessionInstance.get_instance(
            ).scfg = extract_from_packet_as_bytestring(a,
                                                       start=452,
                                                       end=452 + 135)
Exemple #19
0
    def send_encrypted_request(self):
        """
        Make an AEAD GET Request to example.org
        :return:
        """
        self.logger.info("Making GET Request")

        # Generate forward secure keys if it hasn't already been done.
        current_app_key = SessionInstance.get_instance().app_keys
        if current_app_key['type'] != "FORWARD" or current_app_key[
                'mah'] != SessionInstance.get_instance().last_received_shlo:
            if len(SessionInstance.get_instance().peer_public_value) == 0:
                pass
            else:
                key = dhke.generate_keys(
                    SessionInstance.get_instance().peer_public_value, True,
                    self.logger)
                SessionInstance.get_instance().app_keys['type'] = "FORWARD"
                SessionInstance.get_instance().app_keys[
                    'mah'] = SessionInstance.get_instance().last_received_shlo
                SessionInstance.get_instance().app_keys['key'] = key

        get_request = "800300002501250000000500000000FF418FF1E3C2E5F23A6BA0AB9EC9AE38110782848750839BD9AB7A85ED6988B4C7"

        packet_number = PacketNumberInstance.get_instance(
        ).get_next_packet_number()
        ciphertext = CryptoManager.encrypt(bytes.fromhex(get_request),
                                           packet_number,
                                           SessionInstance.get_instance(),
                                           self.logger)

        # Send it to the server
        a = AEADRequestPacket()
        a.setfieldval(
            'CID',
            string_to_ascii(SessionInstance.get_instance().connection_id))
        a.setfieldval("Public Flags", 0x18)
        a.setfieldval('Packet Number', packet_number)
        a.setfieldval("Message Authentication Hash",
                      string_to_ascii(ciphertext[0:24]))

        p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP(
            dport=6121,
            sport=61250) / a / Raw(load=string_to_ascii(ciphertext[24:]))
        self.sniffer.add_observer(self)
        send(p)
        self.wait_for_signal_or_expiration()
        self.processed = False
        self.sniffer.remove_observer(self)
Exemple #20
0
    def process(self, is_encrypted=True, logger=None):

        self.processedFramesInstance = ProcessedFramesInstance.get_instance()
        self.processedFramesInstance.reset_processed_bytes()

        if is_encrypted:
            # Response is encrypted so we need to decrypt it
            associated_data = SessionInstance.get_instance().associated_data
            packet_number = int(SessionInstance.get_instance().packet_number, 16).to_bytes(8, byteorder='little')
            nonce = SessionInstance.get_instance().keys['iv2'][0:4] + packet_number

            # The ciphertext starts from the Message Authentication Hash and continues until the end of this stream
            # Containing everything it meets along the way.
            message_authentication_hash = SessionInstance.get_instance().message_authentication_hash
            ciphertext = "".join(self.packet_body)
            complete_ciphertext = message_authentication_hash
            complete_ciphertext += self.processedFramesInstance.get_processed_bytes().hex()
            complete_ciphertext += ciphertext

            # print("ProcessedFrames thus far {}".format(self.processedFramesInstance.get_processed_bytes()))

            request_data = {
                'mode': 'decryption',
                'input': complete_ciphertext,
                'additionalData': associated_data,
                'nonce': nonce.hex(),
                'key': SessionInstance.get_instance().keys['key2'].hex()  # other key, used for decryption,.
            }

            logger.info("Requesting decryption for {}".format(request_data))

            try:
                response = CryptoConnectionManager.send_message(ConnectionEndpoint.CRYPTO_ORACLE,
                                                                      json.dumps(request_data).encode('utf-8'), True)
                # print("Response after decryption {}".format(response['data']))
                logger.info("Decrypted {}".format(response['data']))
                self.packet_body = split_at_nth_char(response['data'])
            except JSONDecodeError as err:
                self.packet_body = []

        processors = [
                    {
                        'processor': StreamProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': BlockedProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': CongestionFeedbackProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': ConnectionCloseProcessor(),
                        'result': 'closed',
                        'processes': 0
                    },
                    {
                        'processor': GoAwayProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': PaddingProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': PingProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': RSTStreamProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': StopWaitingProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': WindowUpdateProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': AckProcessor(),
                        'result': '',
                        'processes': 0
                    },
                    {
                        'processor': UnknownProcessor(),
                        'result': '',
                        'processes': -999999
                    }
                ]

        processed_by = []
        # while len(self.packet_body) > 0:
        #     # As long as we need to process the packet body
        #     for processor in processors:
        #         processor['processor'].receive(self.packet_body)
        #         if processor['processor'].my_frame():
        #             processor['processor'].process()
        #             logger.info("Processing started by {}".format(processor['processor']))
        #             self.packet_body = processor['processor'].result()
        #             print("Processed by {} with result {}".format(processor['processor'], self.packet_body))
        #             processor['processes'] += 1
        #
        #             if isinstance(processor['processor'], StreamProcessor):
        #                 print("Stream processor has status {}".format(processor['processor'].status))
        #                 processor['result'] = processor['processor'].status
        #                 logger.info("Result of stream processor {}".format(processor['result']))
        #
        #             if not processor['result'] == "":
        #                 processed_by.append(processor['result'])
        #             break
        packet_as_string = "".join(self.packet_body)
        # regexes for the SHLO part
        indexes = find_all_indexes_of_substring_in_string(packet_as_string, "a001")
        indexes += find_all_indexes_of_substring_in_string(packet_as_string, "a401")
        # regex for the HTTP part
        indexes += find_all_indexes_of_substring_in_string(packet_as_string, "c0053c")
        for index in indexes:
            processor = StreamProcessor()
            processor.receive(split_at_nth_char(packet_as_string[index:], 2))
            processor.process()
            processed_by.append(processor.status)

        # print("Finished processing ? {} ".format(processed_by))

        # logger.info("After processing {}".format(processed_by))
        if len(processed_by) > 0:
            # print("Process result {}".format(processed_by[0]))
            if processed_by.count('unknown') == len(processed_by):
                return 'unknown'
            else:
                logger.info("Complete processed by in FP {}".format(processed_by))
                p = list(filter(lambda a: a != 'unknown', processed_by))[0]
                logger.info("Returning in FramesProcessor {}".format(p))
                return p
Exemple #21
0
    def __handle_encrypted_packet(self, a):
        SessionInstance.get_instance().div_nonce = a.get_field(
            AEADFieldNames.DIVERSIFICATION_NONCE)
        SessionInstance.get_instance(
        ).message_authentication_hash = a.get_field(
            AEADFieldNames.MESSAGE_AUTHENTICATION_HASH)
        packet_number = a.get_field(AEADFieldNames.PACKET_NUMBER)
        SessionInstance.get_instance().packet_number = packet_number
        # print("Packet Number {}".format(packet_number))
        SessionInstance.get_instance(
        ).largest_observed_packet_number = packet_number
        PacketNumberInstance.get_instance(
        ).highest_received_packet_number = packet_number
        SessionInstance.get_instance().associated_data = a.get_associated_data(
        )
        # print("Associated Data {}".format(SessionInstance.get_instance().associated_data))
        ciphertext = split_at_nth_char(
            a.get_field(AEADFieldNames.ENCRYPTED_FRAMES))

        print("Received peer public value {}".format(
            SessionInstance.get_instance().peer_public_value))

        # Only generate a new set of initial keys when we receive a new REJ
        current_app_key = SessionInstance.get_instance().app_keys
        self.__logger.info(
            "Currently stored app key {}".format(current_app_key))
        self.__logger.info("Last received REJ")
        if current_app_key['type'] != "REJ" \
                or current_app_key['mah'] != SessionInstance.get_instance().last_received_rej\
                or SessionInstance.get_instance().zero_rtt:
            # If the generated key does not comply with the previously received REJ, then create a new set of keys
            # Or if it is the first set of keys. Otherwise we just use the previous set of keys.
            key = dhke.generate_keys(
                SessionInstance.get_instance().peer_public_value,
                SessionInstance.get_instance().shlo_received, self.__logger)
            SessionInstance.get_instance().app_keys['type'] = "REJ"
            SessionInstance.get_instance().app_keys[
                'mah'] = SessionInstance.get_instance().last_received_rej
            SessionInstance.get_instance().app_keys['key'] = key
        # SessionInstance.get_instance().packet_number = packet_number

        # Process the streams
        processor = FramesProcessor(ciphertext)
        return processor.process(logger=self.__logger)