Beispiel #1
0
    def test_little_endian_16_bit(self):
        mb = MessageTypeBuilder("little_endian_16_length_test")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 16)

        num_messages_by_data_length = {256 * 8: 5, 16: 4, 512: 2}
        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x9a9d"},
                               little_endian=True)

        random.seed(0)
        for data_length, num_messages in num_messages_by_data_length.items():
            for i in range(num_messages):
                pg.generate_message(data="".join(
                    [random.choice(["0", "1"]) for _ in range(data_length)]))

        #self.save_protocol("little_endian_16_length_test", pg)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)

        length_engine = LengthEngine(ff.bitvectors)
        highscored_ranges = length_engine.find(n_gram_length=8)
        self.assertEqual(len(highscored_ranges), 3)

        ff.perform_iteration()
        self.assertEqual(len(ff.message_types), 1)
        self.assertGreater(len(ff.message_types[0]), 0)
        label = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.LENGTH)
        self.assertEqual(label.start, 24)
        self.assertEqual(label.length, 16)
Beispiel #2
0
    def test_format_finding_enocean(self):
        enocean_protocol = ProtocolAnalyzer(None)
        with open(get_path_for_data_file("enocean_bits.txt")) as f:
            for line in f:
                enocean_protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", "")))
                enocean_protocol.messages[-1].message_type = enocean_protocol.default_message_type

        preamble_start = 3
        preamble_end = 10
        sof_start = 11
        sof_end = 14

        preamble_label = ProtocolLabel(name=self.preamble_field_type.caption, field_type=self.preamble_field_type,
                                       start=preamble_start, end=preamble_end, color_index=0)
        sync_label = ProtocolLabel(name=self.sync_field_type.caption, field_type=self.sync_field_type,
                                   start=sof_start, end=sof_end, color_index=1)

        ff = FormatFinder(enocean_protocol, self.participants, field_types=self.field_types)
        ff.perform_iteration()

        self.assertEqual(len(enocean_protocol.message_types), 1)

        self.assertIn(preamble_label, enocean_protocol.default_message_type)
        self.assertIn(sync_label, enocean_protocol.default_message_type)
        self.assertTrue(
            not any(lbl.name == self.length_field_type.caption for lbl in enocean_protocol.default_message_type))
        self.assertTrue(not any("address" in lbl.name.lower() for lbl in enocean_protocol.default_message_type))
Beispiel #3
0
    def test_sequence_number_little_endian_16_bit(self):
        mb = MessageTypeBuilder("16bit_seq_test")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 16)

        num_messages = 8

        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x9a9d"},
                               little_endian=True,
                               sequence_number_increment=64)

        for i in range(num_messages):
            pg.generate_message(data="0xcafe")

        #self.save_protocol("16bit_litte_endian_seq", pg)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)
        ff.perform_iteration()

        self.assertEqual(len(ff.message_types), 1)
        self.assertEqual(
            ff.message_types[0].num_labels_with_type(
                FieldType.Function.SEQUENCE_NUMBER), 1)
        label = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SEQUENCE_NUMBER)
        self.assertEqual(label.start, 24)
        self.assertEqual(label.length, 16)
Beispiel #4
0
    def test_protocol_with_acks_and_checksum(self):
        proto_file = get_path_for_data_file("ack_frames_with_crc.proto.xml")
        protocol = ProtocolAnalyzer(signal=None, filename=proto_file)
        protocol.from_xml_file(filename=proto_file, read_bits=True)

        self.clear_message_types(protocol.messages)

        ff = FormatFinder(protocol.messages)
        ff.known_participant_addresses.clear()

        ff.run()
        self.assertEqual(
            util.convert_numbers_to_hex_string(
                ff.known_participant_addresses[0]), "1337")
        self.assertEqual(
            util.convert_numbers_to_hex_string(
                ff.known_participant_addresses[1]), "4711")

        for mt in ff.message_types:
            preamble = mt.get_first_label_with_type(
                FieldType.Function.PREAMBLE)
            self.assertEqual(preamble.start, 0)
            self.assertEqual(preamble.length, 16)
            sync = mt.get_first_label_with_type(FieldType.Function.SYNC)
            self.assertEqual(sync.start, 16)
            self.assertEqual(sync.length, 16)
            length = mt.get_first_label_with_type(FieldType.Function.LENGTH)
            self.assertEqual(length.start, 32)
            self.assertEqual(length.length, 8)
Beispiel #5
0
    def test_format_finding_enocean(self):
        enocean_protocol = ProtocolAnalyzer(None)
        with open(get_path_for_data_file("enocean_bits.txt")) as f:
            for line in f:
                enocean_protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", "")))
                enocean_protocol.messages[-1].message_type = enocean_protocol.default_message_type

        ff = FormatFinder(enocean_protocol.messages)
        ff.perform_iteration()

        message_types = ff.message_types
        self.assertEqual(len(message_types), 1)

        preamble = message_types[0].get_first_label_with_type(FieldType.Function.PREAMBLE)
        self.assertEqual(preamble.start, 0)
        self.assertEqual(preamble.length, 8)

        sync = message_types[0].get_first_label_with_type(FieldType.Function.SYNC)
        self.assertEqual(sync.start, 8)
        self.assertEqual(sync.length, 4)

        checksum = message_types[0].get_first_label_with_type(FieldType.Function.CHECKSUM)
        self.assertEqual(checksum.start, 56)
        self.assertEqual(checksum.length, 4)

        self.assertIsNone(message_types[0].get_first_label_with_type(FieldType.Function.SRC_ADDRESS))
        self.assertIsNone(message_types[0].get_first_label_with_type(FieldType.Function.DST_ADDRESS))
        self.assertIsNone(message_types[0].get_first_label_with_type(FieldType.Function.LENGTH))
        self.assertIsNone(message_types[0].get_first_label_with_type(FieldType.Function.SEQUENCE_NUMBER))
Beispiel #6
0
    def test_paper_example(self):
        alice = Participant("Alice", "A")
        bob = Participant("Bob", "B")
        participants = [alice, bob]
        msg1 = Message.from_plain_hex_str("aabb1234")
        msg1.participant = alice
        msg2 = Message.from_plain_hex_str("aabb6789")
        msg2.participant = alice
        msg3 = Message.from_plain_hex_str("bbaa4711")
        msg3.participant = bob
        msg4 = Message.from_plain_hex_str("bbaa1337")
        msg4.participant = bob

        protocol = ProtocolAnalyzer(None)
        protocol.messages.extend([msg1, msg2, msg3, msg4])
        #self.save_protocol("paper_example", protocol)

        bitvectors = FormatFinder.get_bitvectors_from_messages(
            protocol.messages)
        hexvectors = FormatFinder.get_hexvectors(bitvectors)
        address_engine = AddressEngine(hexvectors,
                                       participant_indices=[
                                           participants.index(msg.participant)
                                           for msg in protocol.messages
                                       ])
    def test_multiple_sync_words(self):
        hex_messages = [
            "aaS1234",
            "aaScafe",
            "aaSdead",
            "aaSbeef",
        ]

        for i in range(1, 256):
            messages = []
            sync = "{0:02x}".format(i)
            if sync.startswith("a"):
                continue

            for msg in hex_messages:
                messages.append(
                    Message.from_plain_hex_str(msg.replace("S", sync)))

            for i in range(1, len(messages)):
                messages[i].message_type = messages[0].message_type

            ff = FormatFinder(messages)
            ff.run()

            self.assertEqual(len(ff.message_types), 1, msg=sync)

            preamble = ff.message_types[0].get_first_label_with_type(
                FieldType.Function.PREAMBLE)
            self.assertEqual(preamble.start, 0, msg=sync)
            self.assertEqual(preamble.length, 8, msg=sync)

            sync = ff.message_types[0].get_first_label_with_type(
                FieldType.Function.SYNC)
            self.assertEqual(sync.start, 8, msg=sync)
            self.assertEqual(sync.length, 8, msg=sync)
    def test_given_address_information(self):
        """
        Empty both message types and see if addresses are found, when information of participant addresses is given

        :return:
        """
        protocol = self.__prepare_example_protocol()
        self.clear_message_types(protocol.messages)

        ff = FormatFinder(protocol.messages)
        ff.perform_iteration()
        self.assertEqual(2, len(ff.message_types))

        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.PREAMBLE))
        self.assertIsNotNone(ff.message_types[1].get_first_label_with_type(
            FieldType.Function.PREAMBLE))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SYNC))
        self.assertIsNotNone(ff.message_types[1].get_first_label_with_type(
            FieldType.Function.SYNC))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.LENGTH))
        self.assertIsNotNone(ff.message_types[1].get_first_label_with_type(
            FieldType.Function.LENGTH))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.DST_ADDRESS))
        self.assertIsNotNone(ff.message_types[1].get_first_label_with_type(
            FieldType.Function.DST_ADDRESS))
        self.assertIsNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SRC_ADDRESS))
        self.assertIsNotNone(ff.message_types[1].get_first_label_with_type(
            FieldType.Function.SRC_ADDRESS))
    def test_sync_word_finding_varying_message_length(self):
        hex_messages = [
            "aaaa9a7d0f1337471100009a44ebdd13517bf9",
            "aaaa9a7d4747111337000134a4473c002b909630b11df37e34728c79c60396176aff2b5384e82f31511581d0cbb4822ad1b6734e2372ad5cf4af4c9d6b067e5f7ec359ec443c3b5ddc7a9e",
            "aaaa9a7d0f13374711000205ee081d26c86b8c",
            "aaaa9a7d474711133700037cae4cda789885f88f5fb29adc9acf954cb2850b9d94e7f3b009347c466790e89f2bcd728987d4670690861bbaa120f71f14d4ef8dc738a6d7c30e7d2143c267",
            "aaaa9a7d0f133747110004c2906142300427f3"
        ]

        messages = [
            Message.from_plain_hex_str(hex_msg) for hex_msg in hex_messages
        ]
        for i in range(1, len(messages)):
            messages[i].message_type = messages[0].message_type

        ff = FormatFinder(messages)
        ff.run()

        self.assertEqual(len(ff.message_types), 1)
        preamble = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.PREAMBLE)
        self.assertEqual(preamble.start, 0)
        self.assertEqual(preamble.length, 16)

        sync = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SYNC)
        self.assertEqual(sync.start, 16)
        self.assertEqual(sync.length, 16)
Beispiel #10
0
    def test_find_generated_crc16(self):
        mb = MessageTypeBuilder("data")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.DATA, 32)
        mb.add_checksum_label(16, GenericCRC.from_standard_checksum("CRC16 CCITT"))

        mb2 = MessageTypeBuilder("data2")
        mb2.add_label(FieldType.Function.PREAMBLE, 8)
        mb2.add_label(FieldType.Function.SYNC, 16)
        mb2.add_label(FieldType.Function.LENGTH, 8)
        mb2.add_label(FieldType.Function.DATA, 16)

        mb2.add_checksum_label(16, GenericCRC.from_standard_checksum("CRC16 CCITT"))

        pg = ProtocolGenerator([mb.message_type, mb2.message_type], syncs_by_mt={mb.message_type: "0x1234", mb2.message_type: "0x1234"})

        num_messages = 5

        for i in range(num_messages):
            pg.generate_message(data="{0:032b}".format(i), message_type=mb.message_type)
            pg.generate_message(data="{0:016b}".format(i), message_type=mb2.message_type)

        #self.save_protocol("crc16_test", pg)
        self.clear_message_types(pg.protocol.messages)

        ff = FormatFinder(pg.protocol.messages)
        ff.run()

        self.assertEqual(len(ff.message_types), 2)
        for mt in ff.message_types:
            checksum_label = mt.get_first_label_with_type(FieldType.Function.CHECKSUM)
            self.assertEqual(checksum_label.length, 16)
            self.assertEqual(checksum_label.checksum.caption, "CRC16 CCITT")
Beispiel #11
0
    def run_format_finder_for_protocol(protocol: ProtocolAnalyzer):
        ff = FormatFinder(protocol.messages)
        ff.known_participant_addresses.clear()
        ff.run()

        for msg_type, indices in ff.existing_message_types.items():
            for i in indices:
                protocol.messages[i].message_type = msg_type
Beispiel #12
0
    def auto_assign_labels(self):
        from urh.awre.FormatFinder import FormatFinder
        format_finder = FormatFinder(self.messages)
        format_finder.run(max_iterations=10)

        self.message_types[:] = format_finder.message_types
        for msg_type, indices in format_finder.existing_message_types.items():
            for i in indices:
                self.messages[i].message_type = msg_type
Beispiel #13
0
    def auto_assign_labels(self):
        if len(self.used_symbols) > 0:
            logger.info("Format Finder not compatible with symbols yet.")
            return

        format_finder = FormatFinder(self)

        # OPEN: Perform multiple iterations with varying priorities later
        format_finder.perform_iteration()
Beispiel #14
0
    def test_homematic(self):
        proto_file = get_path_for_data_file("homematic.proto.xml")
        protocol = ProtocolAnalyzer(signal=None, filename=proto_file)
        protocol.message_types = []
        protocol.from_xml_file(filename=proto_file, read_bits=True)
        # prevent interfering with preassinged labels
        protocol.message_types = [MessageType("Default")]

        participants = sorted({msg.participant for msg in protocol.messages})

        self.clear_message_types(protocol.messages)
        ff = FormatFinder(protocol.messages, participants=participants)
        ff.known_participant_addresses.clear()
        ff.perform_iteration()

        self.assertGreater(len(ff.message_types), 0)

        for i, message_type in enumerate(ff.message_types):
            preamble = message_type.get_first_label_with_type(FieldType.Function.PREAMBLE)
            self.assertEqual(preamble.start, 0)
            self.assertEqual(preamble.length, 32)

            sync = message_type.get_first_label_with_type(FieldType.Function.SYNC)
            self.assertEqual(sync.start, 32)
            self.assertEqual(sync.length, 32)

            length = message_type.get_first_label_with_type(FieldType.Function.LENGTH)
            self.assertEqual(length.start, 64)
            self.assertEqual(length.length, 8)

            seq = message_type.get_first_label_with_type(FieldType.Function.SEQUENCE_NUMBER)
            self.assertEqual(seq.start, 72)
            self.assertEqual(seq.length, 8)

            src = message_type.get_first_label_with_type(FieldType.Function.SRC_ADDRESS)
            self.assertEqual(src.start, 96)
            self.assertEqual(src.length, 24)

            dst = message_type.get_first_label_with_type(FieldType.Function.DST_ADDRESS)
            self.assertEqual(dst.start, 120)
            self.assertEqual(dst.length, 24)

            checksum = message_type.get_first_label_with_type(FieldType.Function.CHECKSUM)
            self.assertEqual(checksum.length, 16)
            self.assertIn("CC1101", checksum.checksum.caption)

            for msg_index in ff.existing_message_types[message_type]:
                msg_len = len(protocol.messages[msg_index])
                self.assertEqual(checksum.start, msg_len-16)
                self.assertEqual(checksum.end, msg_len)
    def test_fully_labeled(self):
        """
        For fully labeled protocol, nothing should be done

        :return:
        """
        protocol = self.__prepare_example_protocol()
        message_types = sorted(copy.deepcopy(protocol.message_types),
                               key=lambda x: x.name)
        ff = FormatFinder(protocol.messages)
        ff.perform_iteration()
        self.assertEqual(len(message_types), len(ff.message_types))

        for mt1, mt2 in zip(message_types, ff.message_types):
            self.assertTrue(self.__message_types_have_same_labels(mt1, mt2))
Beispiel #16
0
    def test_create_message_types_2(self):
        rng1 = CommonRange(0, 8, "1" * 8, score=1, field_type="Length")
        rng1.message_indices = {0, 2, 4, 6, 8, 12}
        rng2 = CommonRange(8, 8, "1" * 8, score=1, field_type="Address")
        rng2.message_indices = {1, 2, 3, 4, 5, 12}
        rng3 = CommonRange(16, 8, "1" * 8, score=1, field_type="Seq")
        rng3.message_indices = {1, 3, 5, 7, 12}

        message_types = FormatFinder.create_common_range_containers(
            {rng1, rng2, rng3})
        expected1 = CommonRangeContainer([rng1], message_indices={0, 6, 8})
        expected2 = CommonRangeContainer([rng1, rng2], message_indices={2, 4})
        expected3 = CommonRangeContainer([rng1, rng2, rng3],
                                         message_indices={12})
        expected4 = CommonRangeContainer([rng2, rng3],
                                         message_indices={1, 3, 5})
        expected5 = CommonRangeContainer([rng3], message_indices={7})

        self.assertEqual(len(message_types), 5)

        self.assertIn(expected1, message_types)
        self.assertIn(expected2, message_types)
        self.assertIn(expected3, message_types)
        self.assertIn(expected4, message_types)
        self.assertIn(expected5, message_types)
Beispiel #17
0
    def test_retransform_message_indices(self):
        sync_ends = np.array([12, 12, 12, 14, 14])

        rng = CommonRange(0,
                          8,
                          "1" * 8,
                          score=1,
                          field_type="length",
                          message_indices={0, 1, 2, 3, 4})
        retransformed_ranges = FormatFinder.retransform_message_indices(
            [rng], [0, 1, 2, 3, 4], sync_ends)

        # two different sync ends
        self.assertEqual(len(retransformed_ranges), 2)

        expected1 = CommonRange(12,
                                8,
                                "1" * 8,
                                score=1,
                                field_type="length",
                                message_indices={0, 1, 2})
        expected2 = CommonRange(14,
                                8,
                                "1" * 8,
                                score=1,
                                field_type="length",
                                message_indices={3, 4})

        self.assertIn(expected1, retransformed_ranges)
        self.assertIn(expected2, retransformed_ranges)
Beispiel #18
0
    def test_one_participant(self):
        """
        Test a simple protocol with
        preamble, sync and length field (8 bit) and some random data

        :return:
        """
        mb = MessageTypeBuilder("simple_address_test")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.SRC_ADDRESS, 16)

        num_messages_by_data_length = {8: 5, 16: 10, 32: 15}
        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x9a9d"},
                               participants=[self.alice])
        for data_length, num_messages in num_messages_by_data_length.items():
            for i in range(num_messages):
                pg.generate_message(data=pg.decimal_to_bits(
                    22 * i, data_length),
                                    source=self.alice)

        #self.save_protocol("address_one_participant", pg)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)

        address_engine = AddressEngine(ff.hexvectors, ff.participant_indices)
        address_dict = address_engine.find_addresses()

        self.assertEqual(len(address_dict), 0)
Beispiel #19
0
    def test_medium_protocol(self):
        """
        Protocol with two message types. Length field only present in one of them

        :return:
        """
        mb1 = MessageTypeBuilder("data")
        mb1.add_label(FieldType.Function.PREAMBLE, 8)
        mb1.add_label(FieldType.Function.SYNC, 8)
        mb1.add_label(FieldType.Function.LENGTH, 8)
        mb1.add_label(FieldType.Function.SEQUENCE_NUMBER, 8)

        mb2 = MessageTypeBuilder("ack")
        mb2.add_label(FieldType.Function.PREAMBLE, 8)
        mb2.add_label(FieldType.Function.SYNC, 8)

        pg = ProtocolGenerator([mb1.message_type, mb2.message_type],
                               syncs_by_mt={
                                   mb1.message_type: "11110011",
                                   mb2.message_type: "11110011"
                               })
        num_messages_by_data_length = {8: 5, 16: 10, 32: 5}
        for data_length, num_messages in num_messages_by_data_length.items():
            for i in range(num_messages):
                pg.generate_message(data=pg.decimal_to_bits(
                    10 * i, data_length),
                                    message_type=mb1.message_type)
                pg.generate_message(message_type=mb2.message_type, data="0xaf")

        #self.save_protocol("medium_length", pg)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)

        ff.perform_iteration()
        self.assertEqual(len(ff.message_types), 2)
        length_mt = next(mt for mt in ff.message_types
                         if mt.get_first_label_with_type(
                             FieldType.Function.LENGTH) is not None)
        length_label = length_mt.get_first_label_with_type(
            FieldType.Function.LENGTH)

        for i, sync_end in enumerate(ff.sync_ends):
            self.assertEqual(sync_end, 16, msg=str(i))

        self.assertEqual(16, length_label.start)
        self.assertEqual(8, length_label.length)
    def test_without_preamble(self):
        alice = Participant("Alice", address_hex="24")
        broadcast = Participant("Broadcast", address_hex="ff")

        mb = MessageTypeBuilder("data")
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.SRC_ADDRESS, 8)
        mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 8)

        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x8e88"},
                               preambles_by_mt={mb.message_type: "10" * 8},
                               participants=[alice, broadcast])

        for i in range(20):
            data_bits = 16 if i % 2 == 0 else 32
            source = pg.participants[i % 2]
            destination = pg.participants[(i + 1) % 2]
            pg.generate_message(data="1010" * (data_bits // 4),
                                source=source,
                                destination=destination)

        #self.save_protocol("without_preamble", pg)
        self.clear_message_types(pg.messages)
        ff = FormatFinder(pg.messages)
        ff.known_participant_addresses.clear()

        ff.run()
        self.assertEqual(len(ff.message_types), 1)

        mt = ff.message_types[0]
        sync = mt.get_first_label_with_type(FieldType.Function.SYNC)
        self.assertEqual(sync.start, 0)
        self.assertEqual(sync.length, 16)

        length = mt.get_first_label_with_type(FieldType.Function.LENGTH)
        self.assertEqual(length.start, 16)
        self.assertEqual(length.length, 8)

        dst = mt.get_first_label_with_type(FieldType.Function.SRC_ADDRESS)
        self.assertEqual(dst.start, 24)
        self.assertEqual(dst.length, 8)

        seq = mt.get_first_label_with_type(FieldType.Function.SEQUENCE_NUMBER)
        self.assertEqual(seq.start, 32)
        self.assertEqual(seq.length, 8)
    def test_one_message_type_empty(self):
        """
        Empty the "ACK" message type, the labels should be find by FormatFinder

        :return:
        """
        protocol = self.__prepare_example_protocol()
        n_message_types = len(protocol.message_types)
        ack_mt = next(mt for mt in protocol.message_types if mt.name == "ack")
        ack_mt.clear()
        self.assertEqual(len(ack_mt), 0)

        ff = FormatFinder(protocol.messages)
        ff.perform_iteration()
        self.assertEqual(n_message_types, len(ff.message_types))

        self.assertEqual(len(ack_mt), 4, msg=str(ack_mt))
Beispiel #22
0
    def test_easy_protocol(self):
        """
        preamble, sync, sequence number, length field (8 bit) and some random data

        :return:
        """
        mb = MessageTypeBuilder("easy_length_test")
        mb.add_label(FieldType.Function.PREAMBLE, 16)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 8)

        num_messages_by_data_length = {32: 10, 64: 15, 16: 5, 24: 7}
        pg = ProtocolGenerator([mb.message_type],
                               preambles_by_mt={mb.message_type: "10" * 8},
                               syncs_by_mt={mb.message_type: "0xcafe"})
        for data_length, num_messages in num_messages_by_data_length.items():
            for i in range(num_messages):
                if i % 4 == 0:
                    data = "1" * data_length
                elif i % 4 == 1:
                    data = "0" * data_length
                elif i % 4 == 2:
                    data = "10" * (data_length // 2)
                else:
                    data = "01" * (data_length // 2)

                pg.generate_message(data=data)

        #self.save_protocol("easy_length", pg)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)

        length_engine = LengthEngine(ff.bitvectors)
        highscored_ranges = length_engine.find(n_gram_length=8)
        self.assertEqual(len(highscored_ranges), 4)

        ff.perform_iteration()
        self.assertEqual(len(ff.message_types), 1)
        self.assertGreater(len(ff.message_types[0]), 0)
        label = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.LENGTH)
        self.assertIsInstance(label, ProtocolLabel)
        self.assertEqual(label.start, 32)
        self.assertEqual(label.length, 8)
Beispiel #23
0
    def test_no_sequence_number(self):
        """
        Ensure no sequence number is labeled, when it cannot be found

        :return:
        """
        alice = Participant("Alice", address_hex="dead")
        bob = Participant("Bob", address_hex="beef")

        mb = MessageTypeBuilder("protocol_with_one_message_type")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.SRC_ADDRESS, 16)
        mb.add_label(FieldType.Function.DST_ADDRESS, 16)

        num_messages = 3

        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x1337"},
                               participants=[alice, bob])

        for i in range(num_messages):
            if i % 2 == 0:
                source, destination = alice, bob
            else:
                source, destination = bob, alice
            pg.generate_message(data="",
                                source=source,
                                destination=destination)

        #self.save_protocol("protocol_1", pg)

        # Delete message type information -> no prior knowledge
        self.clear_message_types(pg.protocol.messages)

        ff = FormatFinder(pg.protocol.messages)
        ff.known_participant_addresses.clear()
        ff.perform_iteration()

        self.assertEqual(len(ff.message_types), 1)

        self.assertEqual(
            ff.message_types[0].num_labels_with_type(
                FieldType.Function.SEQUENCE_NUMBER), 0)
Beispiel #24
0
    def test_format_finding_rwe(self):
        preamble_start, preamble_end = 0, 31
        sync_start, sync_end = 32, 63
        length_start, length_end = 64, 71
        ack_address_start, ack_address_end = 72, 95
        dst_address_start, dst_address_end = 88, 111
        src_address_start, src_address_end = 112, 135

        preamble_label = ProtocolLabel(name=self.preamble_field_type.caption, field_type=self.preamble_field_type,
                                       start=preamble_start, end=preamble_end, color_index=0)
        sync_label = ProtocolLabel(name=self.sync_field_type.caption, field_type=self.sync_field_type,
                                   start=sync_start, end=sync_end, color_index=1)
        length_label = ProtocolLabel(name=self.length_field_type.caption, field_type=self.length_field_type,
                                     start=length_start, end=length_end, color_index=2)
        ack_address_label = ProtocolLabel(name=self.dst_address_field_type.caption,
                                          field_type=self.dst_address_field_type,
                                          start=ack_address_start, end=ack_address_end, color_index=3)
        dst_address_label = ProtocolLabel(name=self.dst_address_field_type.caption,
                                          field_type=self.dst_address_field_type,
                                          start=dst_address_start, end=dst_address_end, color_index=4)
        src_address_label = ProtocolLabel(name=self.src_address_field_type.caption,
                                          field_type=self.src_address_field_type,
                                          start=src_address_start, end=src_address_end, color_index=5)

        ff = FormatFinder(protocol=self.protocol, participants=self.participants, field_types=self.field_types)
        ff.perform_iteration()

        self.assertIn(preamble_label, self.protocol.default_message_type)
        self.assertIn(sync_label, self.protocol.default_message_type)
        self.assertIn(length_label, self.protocol.default_message_type)
        self.assertIn(dst_address_label, self.protocol.default_message_type)
        self.assertIn(src_address_label, self.protocol.default_message_type)

        self.assertEqual(len(self.protocol.message_types), 2)
        self.assertEqual(self.protocol.message_types[1].name, "ack")
        self.assertIn(ack_address_label, self.protocol.message_types[1])

        ack_messages = (1, 3, 5, 7, 9, 11, 13, 15, 17, 20)
        for i, msg in enumerate(self.protocol.messages):
            if i in ack_messages:
                self.assertEqual(msg.message_type.name, "ack", msg=i)
            else:
                self.assertEqual(msg.message_type.name.lower(), "default", msg=i)
    def test_type_part_already_labeled(self):
        protocol = self.__prepare_simple_example_protocol()
        self.clear_message_types(protocol.messages)
        ff = FormatFinder(protocol.messages)

        # overlaps type
        ff.message_types[0].add_protocol_label_start_length(32, 8)
        ff.perform_iteration()
        self.assertEqual(1, len(ff.message_types))

        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.PREAMBLE))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SYNC))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.LENGTH))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.DST_ADDRESS))
        self.assertIsNotNone(ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SRC_ADDRESS))
Beispiel #26
0
    def test_create_message_types_1(self):
        rng1 = CommonRange(0, 8, "1" * 8, score=1, field_type="Length")
        rng1.message_indices = {0, 1, 2}
        rng2 = CommonRange(8, 8, "1" * 8, score=1, field_type="Address")
        rng2.message_indices = {0, 1, 2}

        message_types = FormatFinder.create_common_range_containers(
            {rng1, rng2})
        self.assertEqual(len(message_types), 1)

        expected = CommonRangeContainer([rng1, rng2],
                                        message_indices={0, 1, 2})
        self.assertEqual(message_types[0], expected)
Beispiel #27
0
    def test_simple_protocol(self):
        """
        Test a simple protocol with
        preamble, sync and increasing sequence number (8 bit) and some constant data

        :return:
        """
        mb = MessageTypeBuilder("simple_seq_test")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 8)

        num_messages = 20

        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x9a9d"})

        for i in range(num_messages):
            pg.generate_message(data="0xcafe")

        #self.save_protocol("simple_sequence_number", pg)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)

        seq_engine = SequenceNumberEngine(ff.bitvectors, n_gram_length=8)
        highscored_ranges = seq_engine.find()
        self.assertEqual(len(highscored_ranges), 1)

        ff.perform_iteration()
        self.assertEqual(len(ff.message_types), 1)
        self.assertGreater(len(ff.message_types[0]), 0)
        self.assertEqual(
            ff.message_types[0].num_labels_with_type(
                FieldType.Function.SEQUENCE_NUMBER), 1)
        label = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SEQUENCE_NUMBER)
        self.assertEqual(label.start, 24)
        self.assertEqual(label.length, 8)
Beispiel #28
0
    def test_16bit_seq_nr_with_zeros_in_first_part(self):
        mb = MessageTypeBuilder("16bit_seq_first_byte_zero_test")
        mb.add_label(FieldType.Function.PREAMBLE, 8)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 16)

        num_messages = 10

        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x9a9d"},
                               sequence_number_increment=1)

        for i in range(num_messages):
            pg.generate_message(data="0xcafe" + "abc" * i)

        #self.save_protocol("16bit_seq_first_byte_zero_test", pg)

        bitvectors = FormatFinder.get_bitvectors_from_messages(
            pg.protocol.messages, sync_ends=[24] * num_messages)
        seq_engine = SequenceNumberEngine(bitvectors, n_gram_length=8)
        highscored_ranges = seq_engine.find()
        self.assertEqual(len(highscored_ranges), 1)

        self.clear_message_types(pg.protocol.messages)
        ff = FormatFinder(pg.protocol.messages)
        ff.perform_iteration()
        self.assertEqual(len(ff.message_types), 1)
        self.assertGreater(len(ff.message_types[0]), 0)
        self.assertEqual(
            ff.message_types[0].num_labels_with_type(
                FieldType.Function.SEQUENCE_NUMBER), 1)
        label = ff.message_types[0].get_first_label_with_type(
            FieldType.Function.SEQUENCE_NUMBER)

        # Not consider constants as part of SEQ Nr!
        self.assertEqual(label.start, 40)
        self.assertEqual(label.length, 8)
Beispiel #29
0
    def test_handle_easy_overlapping_conflict(self):
        # Easy conflict: First Label has higher score
        rng1 = CommonRange(8, 8, "1" * 8, score=1, field_type="Length")
        rng1.message_indices = {0, 1, 2}
        rng2 = CommonRange(8, 8, "1" * 8, score=0.8, field_type="Address")
        rng2.message_indices = {0, 1, 2}

        container = CommonRangeContainer([rng1, rng2],
                                         message_indices={0, 1, 2})
        result = FormatFinder.handle_overlapping_conflict([container])
        self.assertEqual(len(result), 1)
        self.assertEqual(len(result[0]), 1)
        self.assertIn(rng1, result[0])
        self.assertEqual(result[0].message_indices, {0, 1, 2})
Beispiel #30
0
    def test_handle_medium_overlapping_conflict(self):
        rng1 = CommonRange(8, 8, "1" * 8, score=1, field_type="Length")
        rng2 = CommonRange(4, 10, "1" * 8, score=0.8, field_type="Address")
        rng3 = CommonRange(15, 20, "1" * 8, score=1, field_type="Seq")
        rng4 = CommonRange(60, 80, "1" * 8, score=0.8, field_type="Type")
        rng5 = CommonRange(70, 90, "1" * 8, score=0.9, field_type="Data")

        container = CommonRangeContainer([rng1, rng2, rng3, rng4, rng5])
        result = FormatFinder.handle_overlapping_conflict([container])
        self.assertEqual(len(result), 1)
        self.assertEqual(len(result[0]), 3)
        self.assertIn(rng1, result[0])
        self.assertIn(rng3, result[0])
        self.assertIn(rng5, result[0])
Beispiel #31
0
    def test_build_component_order(self):
        expected_default = [Preamble(fieldtypes=[]), Length(fieldtypes=[], length_cluster=None),
                            Address(fieldtypes=[], xor_matrix=None), SequenceNumber(fieldtypes=[]), Type(), Flags()]

        format_finder = FormatFinder(self.protocol)

        for expected, actual in zip(expected_default, format_finder.build_component_order()):
            assert type(expected) == type(actual)

        expected_swapped = [Preamble(fieldtypes=[]), Address(fieldtypes=[], xor_matrix=None),
                            Length(fieldtypes=[], length_cluster=None), SequenceNumber(fieldtypes=[]), Type(), Flags()]
        format_finder.length_component.priority = 2
        format_finder.address_component.priority = 1

        for expected, actual in zip(expected_swapped, format_finder.build_component_order()):
            assert type(expected) == type(actual)

        # Test duplicate Priority
        format_finder.sequence_number_component.priority = 4
        with self.assertRaises(ValueError) as context:
            format_finder.build_component_order()
            self.assertTrue('Duplicate priority' in context.exception)
        format_finder.sequence_number_component.priority = 3
        self.assertTrue(format_finder.build_component_order())
Beispiel #32
0
    def test_format_finding_without_participants(self):
        for msg in self.zero_crc_protocol.messages:
            msg.participant = None

        ff = FormatFinder(self.zero_crc_protocol, [])
        ff.perform_iteration()
Beispiel #33
0
 def test_format_finding_rwe_zeroed_crc(self):
     ff = FormatFinder(self.zero_crc_protocol, self.participants)
     ff.perform_iteration()
Beispiel #34
0
    def auto_assign_labels(self):
        format_finder = FormatFinder(self)

        # OPEN: Perform multiple iterations with varying priorities later
        format_finder.perform_iteration()