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 redo(self): len_pattern = len(self.amble_pattern) amble_sequence = self.amble_pattern * self.min_occurences len_sequence = len(amble_sequence) labels = [] for group in self.groups: count = 0 for k, block in enumerate(group.blocks): bit_str = block.decoded_bits_str len_bit_str = len(bit_str) indx = bit_str.find(amble_sequence) labels.append([]) while indx != -1: start = indx end = indx + len_sequence for i in range(start + len_sequence, len_bit_str, len_pattern): if bit_str[i:i + len_pattern] != self.amble_pattern: end = i break start = start if start > 1 else 0 # Erstes Bit mitnehmen, wenn Preamble beim zweiten Bit beginnt if count == 0: name = "Preamble" else: name = "Amble #{0:d}".format(count) lbl = ProtocolLabel(name, start, end - 1, k, 0, -1, True) lbl.reference_bits = bit_str[start:end] lbl.apply_decoding = False labels[k].append(lbl) indx = bit_str.find(amble_sequence, end - 1) count += 1 group.add_label(lbl)
def add_protocol_label(self, start: int, end: int, refblock: int, type_index: int, restrictive: bool, name=None, color_ind=None) -> \ ProtocolLabel: if refblock >= self.num_blocks: refblock = 0 name = "Label {0:d}".format(len(self.labels) + 1) if not name else name used_colors = [p.color_index for p in self.labels] avail_colors = [i for i, _ in enumerate(constants.LABEL_COLORS) if i not in used_colors] if color_ind is None: if len(avail_colors) > 0: color_ind = avail_colors[random.randint(0, len(avail_colors)-1)] else: color_ind = random.randint(0, len(constants.LABEL_COLORS) - 1) proto_label = ProtocolLabel(name, start, end, refblock, type_index, color_ind, restrictive) try: proto_label.reference_bits = self.decoded_bits_str[refblock][proto_label.start:proto_label.end] except IndexError: return None proto_label.signals.apply_decoding_changed.connect(self.handle_plabel_apply_decoding_changed) proto_label.find_block_numbers(self.decoded_bits_str) self.labels.append(proto_label) self.labels.sort() return proto_label
def read_compare_frame_groups(self): if self.project_file is None: return tree = ET.parse(self.project_file) root = tree.getroot() proto_tree_model = self.maincontroller.compare_frame_controller.proto_tree_model tree_root = proto_tree_model.rootItem pfi = proto_tree_model.protocol_tree_items proto_frame_items = [item for item in pfi[0]] """:type: list of ProtocolTreeItem """ for group_tag in root.iter("group"): name = group_tag.attrib["name"] id = group_tag.attrib["id"] if id == "0": tree_root.child(0).setData(name) else: tree_root.addGroup(name=name) group = tree_root.child(int(id)) for proto_tag in group_tag.iter("cf_protocol"): filename = os.path.join(self.project_path, proto_tag.attrib["filename"]) show = proto_tag.attrib["show"] try: proto_frame_item = next((p for p in proto_frame_items if p.protocol.filename == filename)) except StopIteration: proto_frame_item = None if proto_frame_item is not None: group.appendChild(proto_frame_item) proto_frame_item.show_in_compare_frame = Qt.Checked if show == "1" else Qt.Unchecked group = proto_tree_model.groups[int(id)] for label_tag in group_tag.iter("label"): name = label_tag.attrib["name"] start = int(label_tag.attrib["start"]) end = int(label_tag.attrib["end"]) refblock = int(label_tag.attrib["refblock"]) color_index = int(label_tag.attrib["color_index"]) restrictive = int(label_tag.attrib["restrictive"]) == 1 proto_label = ProtocolLabel(name, start, end, refblock, 0, color_index, restrictive) proto_label.reference_bits = label_tag.attrib["refbits"] proto_label.display_type_index = int(label_tag.attrib["display_type_index"]) proto_label.apply_decoding = int(label_tag.attrib["apply_decoding"]) == 1 group.add_label(proto_label) self.maincontroller.compare_frame_controller.expand_group_node(int(id)) self.maincontroller.compare_frame_controller.refresh()
def change_field_type_of_label(self, label: ProtocolLabel, field_type: FieldType): if not isinstance(label, ProtocolLabel) and hasattr(label, "field_type"): # In case of SimulatorProtocolLabel label.field_type = field_type return is_crc_type = field_type is not None and field_type.function == FieldType.Function.CHECKSUM if is_crc_type != isinstance(label, ChecksumLabel): self[self.index(label)] = self.__create_label(label.name, label.start, label.end - 1, label.color_index, label.auto_created, field_type) else: label.field_type = field_type
def change_field_type_of_label(self, label: ProtocolLabel, field_type: FieldType): if not isinstance(label, ProtocolLabel) and hasattr(label, "field_type"): # In case of SimulatorProtocolLabel label.field_type = field_type return is_crc_type = field_type is not None and field_type.function == FieldType.Function.CHECKSUM if is_crc_type != isinstance(label, ChecksumLabel): self[self.index(label)] = self.__create_label(label.name, label.start, label.end - 1, label.color_index, label.auto_created, field_type) else: label.field_type = field_type
def test_message_break_plugin(self): bp = MessageBreakPlugin() n = 1 action = bp.get_action(self.cframe.ui.tblViewProtocol, self.cframe.protocol_undo_stack, (n, n, 4, 4), self.cframe.proto_analyzer, 0) self.assertEqual(self.cframe.protocol_model.row_count, 3) original_msg = self.cframe.proto_analyzer.messages[n] original_msg.message_type = MessageType( "Test", [ProtocolLabel("Test Label", 2, 42, 0)]) msg_type = original_msg.message_type old_msg_len = len(original_msg) action.trigger() # Now we have two messages: One before and including selection and one behind selection msg_1 = self.cframe.proto_analyzer.messages[n] msg_2 = self.cframe.proto_analyzer.messages[n + 1] self.assertEqual(len(msg_1), 4) self.assertEqual(len(msg_2), old_msg_len - 4) self.assertEqual(msg_type, msg_1.message_type) self.assertEqual(msg_type, msg_2.message_type) self.assertEqual(self.cframe.protocol_model.row_count, 4) self.cframe.protocol_undo_stack.undo() self.assertEqual(self.cframe.protocol_model.row_count, 3)
def from_xml(tag: ET.Element): field_types_by_caption = { ft.caption: ft for ft in FieldType.load_from_xml() } name = tag.get("name", "blank") id = tag.get("id", None) assigned_by_ruleset = bool(int(tag.get("assigned_by_ruleset", 0))) assigned_by_logic_analyzer = bool( int(tag.get("assigned_by_logic_analyzer", 0))) labels = [] for lbl_tag in tag.findall("label"): labels.append( ProtocolLabel.from_xml( lbl_tag, field_types_by_caption=field_types_by_caption)) for lbl_tag in tag.findall("checksum_label"): labels.append( ChecksumLabel.from_xml( lbl_tag, field_types_by_caption=field_types_by_caption)) result = MessageType(name=name, iterable=labels, id=id, ruleset=Ruleset.from_xml(tag.find("ruleset"))) result.assigned_by_ruleset = assigned_by_ruleset result.assigned_by_logic_analyzer = assigned_by_logic_analyzer return result
def __create_label(self, name: str, start: int, end: int, color_index: int, auto_created: bool, field_type: FieldType): if field_type is not None: if field_type.function == FieldType.Function.CHECKSUM: # If we have sync or preamble labels start behind last one: pre_sync_label_ends = [ lbl.end for lbl in self if lbl.is_preamble or lbl.is_sync ] if len(pre_sync_label_ends) > 0: range_start = max(pre_sync_label_ends) else: range_start = 0 if range_start >= start: range_start = 0 return ChecksumLabel(name=name, start=start, end=end, color_index=color_index, field_type=field_type, auto_created=auto_created, data_range_start=range_start) return ProtocolLabel(name=name, start=start, end=end, color_index=color_index, field_type=field_type, auto_created=auto_created)
def add_label(self, start: int, end: int, name: str = None, color_index: int = None, type: FieldType = None, parent_item: SimulatorMessage = None): assert isinstance(parent_item, SimulatorMessage) name = "" if not name else name used_colors = [p.color_index for p in parent_item.message_type] avail_colors = [ i for i, _ in enumerate(constants.LABEL_COLORS) if i not in used_colors ] if color_index is None: if len(avail_colors) > 0: color_index = avail_colors[0] else: color_index = random.randint(0, len(constants.LABEL_COLORS) - 1) label = ProtocolLabel(name, start, end, color_index, type) sim_label = SimulatorProtocolLabel(label) self.add_items([sim_label], -1, parent_item) return sim_label
def add_protocol_label(self, start: int, end: int, name=None, color_ind=None, auto_created=False, type: FieldType = None) -> ProtocolLabel: name = "" if not name else name used_colors = [p.color_index for p in self] avail_colors = [ i for i, _ in enumerate(constants.LABEL_COLORS) if i not in used_colors ] if color_ind is None: if len(avail_colors) > 0: color_ind = avail_colors[0] else: color_ind = random.randint(0, len(constants.LABEL_COLORS) - 1) proto_label = ProtocolLabel(name=name, start=start, end=end, color_index=color_ind, auto_created=auto_created, type=type) if proto_label not in self: self.append(proto_label) self.sort() return proto_label # Return label to set editor focus after adding
def add_label(self, lbl: ProtocolLabel, allow_overlapping=True): if allow_overlapping or not any(lbl.overlaps_with(l) for l in self): added = self.add_protocol_label(lbl.start, lbl.end - 1, name=lbl.name, color_ind=lbl.color_index) added.display_format_index = lbl.display_format_index added.display_bit_order_index = lbl.display_bit_order_index
def change_field_type_of_label(self, label: ProtocolLabel, field_type: FieldType): is_crc_type = field_type is not None and field_type.function == FieldType.Function.CHECKSUM if is_crc_type != isinstance(label, ChecksumLabel): self[self.index(label)] = self.__create_label( label.name, label.start, label.end - 1, label.color_index, label.auto_created, field_type) else: label.field_type = field_type
def test_assign_labels(self): preamble_start = 0 preamble_end = 31 sync_start = 32 sync_end = 63 t = time.time() self.protocol.auto_assign_labels() print("Time for auto assigning labels: ", str(time.time()-t)) # 0.020628690719604492 preamble_label = ProtocolLabel(name="Preamble", start=preamble_start, end=preamble_end, val_type_index=0, color_index=0) sync_label = ProtocolLabel(name="Sync", start=sync_start, end=sync_end, val_type_index=0, color_index=1) self.assertEqual(1, len([lbl for lbl in self.protocol.default_labelset if lbl.name == "Preamble"])) self.assertEqual(1, len([lbl for lbl in self.protocol.default_labelset if lbl.name == "Sync"])) for block in self.protocol.blocks: self.assertIn(preamble_label, block.labelset) self.assertIn(sync_label, block.labelset)
def to_label(self, field_type: FieldType) -> ProtocolLabel: result = ProtocolLabel(name=self.name, start=self.start, end=self.end - 1, color_index=self.color_index, field_type=field_type, auto_created=self.auto_created, fuzz_created=self.fuzz_created) result.apply_decoding = self.apply_decoding result.show = self.show result.fuzz_me = self.fuzz_me result.fuzz_values = self.fuzz_values result.display_format_index = self.display_format_index return result
def test_assign_labels_trash_protocol(self): preamble_start = 0 preamble_end = 31 sync_start = 32 sync_end = 63 decoded_trash_protocol = ProtocolAnalyzer(None) with open("./data/decoded_with_trash.txt") as f: for line in f: decoded_trash_protocol.blocks.append(ProtocolBlock.from_plain_bits_str(line.replace("\n", ""), {})) decoded_trash_protocol.blocks[-1].labelset = decoded_trash_protocol.default_labelset decoded_trash_protocol.auto_assign_labels() preamble_label = ProtocolLabel(name="Preamble", start=preamble_start, end=preamble_end, val_type_index=0, color_index=0) sync_label = ProtocolLabel(name="Sync", start=sync_start, end=sync_end, val_type_index=0, color_index=1) self.assertEqual(1, len([lbl for lbl in decoded_trash_protocol.default_labelset if lbl.name == "Preamble"])) self.assertEqual(1, len([lbl for lbl in decoded_trash_protocol.default_labelset if lbl.name == "Sync"])) for block in decoded_trash_protocol.blocks: self.assertIn(preamble_label, block.labelset) self.assertIn(sync_label, block.labelset)
def add_label(self, lbl: ProtocolLabel, allow_overlapping=True): if allow_overlapping or not any(lbl.overlaps_with(l) for l in self): added = self.add_protocol_label(lbl.start, lbl.end - 1, name=lbl.name, color_ind=lbl.color_index, type=lbl.field_type) added.display_format_index = lbl.display_format_index added.display_bit_order_index = lbl.display_bit_order_index if isinstance(lbl, ChecksumLabel) and isinstance( added, ChecksumLabel): added.data_ranges = copy.copy(lbl.data_ranges) added.category = copy.copy(lbl.category) added.checksum = copy.copy(lbl.checksum)
def from_xml(tag: ET.Element): field_types_by_caption = {ft.caption: ft for ft in FieldType.load_from_xml()} name = tag.get("name", "blank") id = tag.get("id", None) assigned_by_ruleset = bool(int(tag.get("assigned_by_ruleset", 0))) assigned_by_logic_analyzer = bool(int(tag.get("assigned_by_logic_analyzer", 0))) labels = [] for lbl_tag in tag.findall("label"): labels.append(ProtocolLabel.from_xml(lbl_tag, field_types_by_caption=field_types_by_caption)) for lbl_tag in tag.findall("checksum_label"): labels.append(ChecksumLabel.from_xml(lbl_tag, field_types_by_caption=field_types_by_caption)) result = MessageType(name=name, iterable=labels, id=id, ruleset=Ruleset.from_xml(tag.find("ruleset"))) result.assigned_by_ruleset = assigned_by_ruleset result.assigned_by_logic_analyzer = assigned_by_logic_analyzer return result
def add_label(self, label_type: FieldType.Function, length: int, name: str = None): try: start = self.message_type[-1].end color_index = self.message_type[-1].color_index + 1 except IndexError: start, color_index = 0, 0 if name is None: name = label_type.value lbl = ProtocolLabel(name, start, start + length - 1, color_index, field_type=FieldType(label_type.name, label_type)) self.message_type.append(lbl)
def from_xml(cls, tag: ET.Element, field_types_by_caption=None): """ :param tag: :type field_types_by_caption: dict[str, FieldType] :return: """ label_tag = tag.find("label") if label_tag is not None: label = ProtocolLabel.from_xml(label_tag, field_types_by_caption) else: label = ChecksumLabel.from_xml(tag.find("checksum_label"), field_types_by_caption) result = SimulatorProtocolLabel(label) result.value_type_index = Formatter.str2val(tag.get("value_type_index", "0"), int) result.external_program = tag.get("external_program", "") result.formula = tag.get("formula", "") result.random_min = Formatter.str2val(tag.get("random_min", "0"), int) result.random_max = Formatter.str2val(tag.get("random_max", str(label.fuzz_maximum-1)), int) return result
def from_xml(cls, tag: ET.Element, field_types_by_caption=None): """ :param tag: :type field_types_by_caption: dict[str, FieldType] :return: """ label_tag = tag.find("label") if label_tag is not None: label = ProtocolLabel.from_xml(label_tag, field_types_by_caption) else: label = ChecksumLabel.from_xml(tag.find("checksum_label"), field_types_by_caption) result = SimulatorProtocolLabel(label) result.value_type_index = Formatter.str2val( tag.get("value_type_index", "0"), int) result.external_program = tag.get("external_program", "") result.formula = tag.get("formula", "") result.random_min = Formatter.str2val(tag.get("random_min", "0"), int) result.random_max = Formatter.str2val( tag.get("random_max", str(label.fuzz_maximum - 1)), int) return result
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_find_unlabeled_range(self): lbl11 = ProtocolLabel(name="Label 1.1", start=2, end=10, color_index=0) lbl12 = ProtocolLabel(name="Label 1.2", start=15, end=20, color_index=0) lbl13 = ProtocolLabel(name="Label 1.3", start=40, end=60, color_index=0) mt1 = MessageType(name="MT1", iterable=[lbl11, lbl12, lbl13]) self.assertEqual([(0, 2), (11, 15), (21, 40), (61, None)], mt1.unlabeled_ranges) self.assertEqual([(0, 2), (11, 15), (21, 40), (61, None)], mt1.unlabeled_ranges_with_other_mt(mt1)) lbl21 = ProtocolLabel(name="Label 2.1", start=1, end=11, color_index=0) lbl22 = ProtocolLabel(name="Label 2.2", start=14, end=18, color_index=0) lbl23 = ProtocolLabel(name="Label 2.3", start=50, end=70, color_index=0) mt2 = MessageType(name="MT2", iterable=[lbl21, lbl22, lbl23]) self.assertEqual(mt1.unlabeled_ranges_with_other_mt(mt2), mt2.unlabeled_ranges_with_other_mt(mt1)) self.assertEqual(mt1.unlabeled_ranges_with_other_mt(mt2), [(0, 1), (11, 14), (21, 40), (71, None)])
def read_protocol(filename: str): if not os.path.isfile(filename): raise FileNotFoundError("{0} could not be found".format(filename)) with open(filename, mode="r") as f: viewtype = 0 reading_proto = False reading_labels = False reading_symbols = False label_name = None label_start = label_end = label_ref_block = -1 label_restrictive = None label_blocks = None apply_decoding = None symbols = dict() cur_group = -1 groups = [] for line in f: line = line.strip() line = line.strip("\n") if line.startswith("#") or len(line) == 0: continue elif line.startswith("VIEWTYPE"): _, viewtype_str = line.split("=") viewtype_str = viewtype_str.strip() if viewtype_str not in VIEW_TYPES: raise SyntaxError( "Unknown Viewtype {0} in file {1}".format( viewtype_str, filename)) else: viewtype = VIEW_TYPES.index(viewtype_str) elif line.startswith("GROUPNAME"): _, name = line.split("=") cur_group += 1 groups.append({}) groups[cur_group]["name"] = name.strip() groups[cur_group]["blocks"] = [] groups[cur_group]["labels"] = [] elif line.startswith("ENCODING"): _, encoding_str = line.split("=") encoding_str = encoding_str.strip() decoding = int(encoding_str) groups[cur_group]["decoding_index"] = decoding elif line.startswith("SYMBOLS:"): reading_symbols = True reading_labels = False reading_proto = False elif line.startswith("PROTOCOL:"): reading_proto = True reading_symbols = False reading_labels = False elif line.startswith("PROTOCOL-LABELS:"): reading_proto = False reading_symbols = False reading_labels = True elif reading_symbols and line.startswith("-"): try: _, symbol_name, nbits, pulsetype, nsamples = line.split( " ") symbols[symbol_name] = Symbol(symbol_name, int(nbits), int(pulsetype), int(nsamples)) except ValueError: continue elif reading_proto and len(line) > 0: groups[cur_group]["blocks"].append( ProtocolBlock.from_plain_bits_str(line, symbols)) elif reading_labels and line.startswith("Name"): label_name = line.replace("Name: ", "") elif reading_labels and line.startswith("Bits"): label_start, label_end = map( int, line.replace("Bits: ", "").split("-")) label_start -= 1 label_end -= 1 elif reading_labels and line.startswith("Restrictive"): if line.replace("Restrictive: ", "") == "True": label_restrictive = True else: label_restrictive = False elif reading_labels and line.startswith("Reference Block"): label_ref_block = int(line.replace("Reference Block: ", "")) - 1 elif reading_labels and line.startswith("Applies for Blocks: "): label_blocks = list( map(int, line.replace("Applies for Blocks: ", "").split(","))) elif reading_labels and line.startswith("Apply Decoding: "): apply_decoding = False if line.replace("Apply Decoding: ", "") == "False" else True if label_name is not None and label_start >= 0 and label_end >= 0 and label_restrictive is not None\ and label_ref_block >= 0 and label_blocks is not None and apply_decoding is not None: color_index = len(groups[cur_group]["labels"]) proto_label = ProtocolLabel(label_name, label_start, label_end, label_ref_block, 0, color_index, label_restrictive) proto_label.block_numbers = label_blocks[:] proto_label.apply_decoding = apply_decoding groups[cur_group]["labels"].append(proto_label) label_name = None label_start = label_end = label_ref_block = -1 label_restrictive = None label_blocks = None if len(groups) == 0: raise SyntaxError("Did not find a PROTOCOL in file " + filename) return viewtype, groups, set(symbols.values())
def add_label(self, lbl: ProtocolLabel, allow_overlapping=True): if allow_overlapping or not any(lbl.overlaps_with(l) for l in self): added = self.add_protocol_label(lbl.start, lbl.end - 1, name=lbl.name, color_ind=lbl.color_index) added.display_format_index = lbl.display_format_index added.display_bit_order_index = lbl.display_bit_order_index
def refresh_label(self, lbl: ProtocolLabel): if lbl not in self.labels: print("Label {0} is not in Group {1}".format(lbl.name, self.name), file=sys.stderr) return lbl.find_block_numbers(self.decoded_bits_str)
def add_label(self, lbl: ProtocolLabel, allow_overlapping=True): if allow_overlapping or not any(lbl.overlaps_with(l) for l in self): self.add_protocol_label(lbl.start, lbl.end - 1, name=lbl.name, color_ind=lbl.color_index)