def activate(self, ctx): f = search_strlit_form_t() f, args = f.Compile() ok = f.Execute() if ok: current_ea = ida_kernwin.get_screen_ea() patterns = ida_bytes.compiled_binpat_vec_t() encoding = ida_nalt.get_default_encoding_idx( ida_nalt.BPU_2B if f.Encoding.value else ida_nalt.BPU_1B) # string literals must be quoted. That's how parse_binpat_str # recognizes them (we want to be careful though: the user # might type in something like 'L"hello"', which should # decode to the IDB-specific wide-char set of bytes) text = f.Text.value if text.find('"') < 0: text = '"%s"' % text err = ida_bytes.parse_binpat_str( patterns, current_ea, text, 10, # radix (not that it matters though, since we're all about string literals) encoding) if not err: ea = ida_bytes.bin_search( current_ea, ida_ida.inf_get_max_ea(), patterns, ida_bytes.BIN_SEARCH_FORWARD | ida_bytes.BIN_SEARCH_NOBREAK | ida_bytes.BIN_SEARCH_NOSHOW) ok = ea != ida_idaapi.BADADDR if ok: ida_kernwin.jumpto(ea) else: print("Failed parsing binary pattern: \"%s\"" % err) return ok
def bin_search(bin_str: str) -> List[int]: if not isinstance(bin_str, str): raise ValueError('bin_str must be a string') if bin_str in cached_patterns: return cached_patterns[bin_str] bin_list = bin_str.split() image = bytearray() mask = bytearray() # Create the mask and convert '?' to 'CC'. for i in range(len(bin_list)): byte = bin_list[i] if byte == '?': image.append(int('CC', 16)) mask.append(0) else: image.append(int(byte, 16)) mask.append(1) image = bytes(image) mask = bytes(mask) start = ida_nalt.get_imagebase() end = ida_idaapi.BADADDR addrs: List[int] = [] ea = ida_bytes.bin_search(start, end, image, mask, 0, ida_bytes.BIN_SEARCH_FORWARD) while ea != ida_idaapi.BADADDR: addrs.append(ea) ea = ida_bytes.bin_search(ea + len(image), end, image, mask, 0, ida_bytes.BIN_SEARCH_FORWARD) cached_patterns[bin_str] = addrs return cached_patterns[bin_str]
def masked_search(start_addr: int, end_addr: int, bytes_data: bytes, masks_data: bytes) -> Tuple[int, Optional[bytes]]: def prepare_first_search(bd: bytes, md: bytes) -> bytes: bd_str = binascii.hexlify(bd, ' ').split(b' ') md_str = binascii.hexlify(md, ' ').split(b' ') for ii, md_token in enumerate(md_str): if md_token != b'ff': bd_str[ii] = b'?' bd_str = b' '.join(bd_str) return bd_str len_bytes = len(bytes_data) bytes_data_prep = prepare_first_search(bytes_data, masks_data) if idaapi.IDA_SDK_VERSION >= 760: patterns = ida_bytes.compiled_binpat_vec_t() idaapi.parse_binpat_str(patterns, start_addr, bytes_data_prep.decode(), 16) ea = ida_bytes.bin_search(start_addr, end_addr, patterns, ida_bytes.BIN_SEARCH_FORWARD | ida_bytes.BIN_SEARCH_NOBREAK | ida_bytes.BIN_SEARCH_NOSHOW) else: ea = ida_search.find_binary(start_addr, end_addr, bytes_data_prep.decode(), 16, idaapi.SEARCH_DOWN) if ea == idaapi.BADADDR: return idaapi.BADADDR, None found_bytes = idaapi.get_bytes(ea, len_bytes) equal = True for i in range(len_bytes): m = masks_data[i] if found_bytes[i] & m != bytes_data[i] & m: equal = False break if equal: return ea, found_bytes return idaapi.BADADDR, None