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)
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)
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))
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)
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))
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)
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)
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_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")
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
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()
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
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))
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))
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)
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)
def get_format_finder_from_protocol_file(self, filename: str, clear_participant_addresses=True, return_messages=False): proto_file = get_path_for_data_file(filename) 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) if clear_participant_addresses: ff.known_participant_addresses.clear() if return_messages: return ff, protocol.messages else: return ff
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))
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)
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())
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)
def test_simple_protocol(self): """ Test a simple protocol with preamble, sync and length field (8 bit) and some random data :return: """ mb = MessageTypeBuilder("simple_length_test") mb.add_label(FieldType.Function.PREAMBLE, 8) mb.add_label(FieldType.Function.SYNC, 16) mb.add_label(FieldType.Function.LENGTH, 8) num_messages_by_data_length = {8: 5, 16: 10, 32: 15} pg = ProtocolGenerator([mb.message_type], syncs_by_mt={mb.message_type: "0x9a9d"}) 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("simple_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), 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, 8)
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()
def test_format_finding_rwe_zeroed_crc(self): ff = FormatFinder(self.zero_crc_protocol, self.participants) ff.perform_iteration()
def auto_assign_labels(self): format_finder = FormatFinder(self) # OPEN: Perform multiple iterations with varying priorities later format_finder.perform_iteration()