def match_functions(bv, flirt_path, action, keep_manually_renamed, prefix): callback = partial(analysis_callback, bv, action=action, keep_manually_renamed=keep_manually_renamed, prefix=prefix) ilog('opening "{}"'.format(flirt_path)) with open(flirt_path, 'rb') as f: flirt = nampa.parse_flirt_file(f) ilog('signature name: "{}"'.format(flirt.header.library_name)) ilog('processing...') for funk in bv.functions: f_start = funk.start f_end = get_function_end(funk) buff = bytes( bv.read(f_start, f_end - f_start + FUNCTION_TAIL_LENGTH)) nampa.match_function(flirt, buff, f_start, callback) # ff = [f.start for f in bv.functions] + [bv.end] # for f_start, f_end in zip(ff[:-1], ff[1:]): # buff = bytes(bv.read(f_start, f_end - f_start)) # nampa.match_function(flirt, buff, f_start, callback) ilog('done :B')
def _match_all_against_one_signature(self, sig: FlirtSignature): # match each function self._suggestions = {} with open(sig.sig_path, "rb") as sigfile: flirt = nampa.parse_flirt_file(sigfile) for func in self.project.kb.functions.values(): func: 'Function' if func.is_simprocedure or func.is_plt: continue if not func.is_default_name: # it already has a name. skip continue start = func.addr if self._is_arm: start = start & 0xffff_fffe max_block_addr = max(func.block_addrs_set) end_block = func.get_block(max_block_addr) end = max_block_addr + end_block.size if self._is_arm: end = end & 0xffff_fffe # load all bytes func_bytes = self.project.loader.memory.load( start, end - start + 0x100) _callback = partial(self._on_func_matched, func) nampa.match_function(flirt, func_bytes, start, _callback)
def load_signatures(path: str) -> None: """ Recursively load all FLIRT signatures under a specific path. :param path: Location of FLIRT signatures. """ FLIRT_SIGNATURES_BY_ARCH.clear() LIBRARY_TO_SIGNATURES.clear() STRING_TO_LIBRARIES.clear() for root, _, filenames in os.walk(path): for filename in filenames: if filename.endswith(".sig"): # parse it sig_path = os.path.join(root, filename) with open(sig_path, "rb") as f: flirt = nampa.parse_flirt_file(f) # is there a meta data file? meta_path = os.path.join(root, filename[:-4] + ".meta") if os.path.isfile(meta_path): # yes! with open(meta_path, "r") as f: meta = json.load(f) arch = meta.get("arch", None) platform = meta.get("platform", None) os_name = meta.get("os", None) os_version = meta.get("os_version", None) compiler = meta.get("compiler", None) compiler_version = meta.get("compiler_version", None) unique_strings = meta.get("unique_strings", None) else: # nope... we need to extract information from the signature file # TODO: Convert them to angr-specific strings arch = flirt.header.arch platform = flirt.header.os_types os_name = None os_version = None unique_strings = None compiler = None compiler_version = None signature = FlirtSignature( arch, platform, flirt.header.library_name.decode("utf-8"), sig_path, unique_strings=unique_strings, compiler=compiler, compiler_version=compiler_version, os_name=os_name, os_version=os_version, ) FLIRT_SIGNATURES_BY_ARCH[arch].append(signature) # fill in LIBRARY_TO_SIGNATURES and STRING_TO_LIBRARIES for sigs in FLIRT_SIGNATURES_BY_ARCH.values(): for sig in sigs: LIBRARY_TO_SIGNATURES[sig.sig_name].append(sig) if sig.unique_strings: for us in sig.unique_strings: STRING_TO_LIBRARIES[us].add(sig.sig_name)
def main(fpath): sig = nampa.parse_flirt_file(open(fpath, 'rb')) for child in sig.root.children: recurse(child, level=0)