def report_calls(args: argparse.Namespace) -> NoReturn: # arguments xname: str = args.xname try: (path, xfile) = UC.get_path_filename(xname) UF.check_analysis_results(path, xfile) except UF.CHBError as e: print(str(e.wrap())) exit(1) xinfo = XI.XInfo() xinfo.load(path, xfile) app = UC.get_app(path, xfile, xinfo) calls = app.call_instructions() calllist: List[Tuple[str, str]] = [] for faddr in sorted(calls): print("\nFunction " + faddr) for baddr in calls[faddr]: print(" Block " + baddr) for instr in calls[faddr][baddr]: calllist.append((instr.annotation, faddr)) print(" " + str(instr)) print("\nCalls aggregated") print("------------------") for (c, faddr) in sorted(calllist): print(faddr.ljust(12) + c) exit(0)
def relational_analysis_cmd(args: argparse.Namespace) -> NoReturn: # arguments xname1: str = args.xname1 xname2: str = args.xname2 xfunctions1: List[str] = args.functions1 xfunctions2: List[str] = args.functions2 showfunctions: bool = args.functions showinstructions: bool = args.instructions usermappingfile: Optional[str] = args.usermapping callees: List[str] = args.callees usermapping: Dict[str, str] = {} if usermappingfile is not None: if os.path.isfile(usermappingfile): with open(usermappingfile, "r") as fp: userdata = json.load(fp) usermapping = userdata["function-mapping"] else: UC.print_error("Usermapping file " + usermappingfile + " not found") exit(1) try: (path1, xfile1) = UC.get_path_filename(xname1) UF.check_analysis_results(path1, xfile1) except UF.CHBError as e: print(str(e.wrap())) exit(1) xinfo1 = XI.XInfo() xinfo1.load(path1, xfile1) try: (path2, xfile2) = UC.get_path_filename(xname2) UF.check_analysis_results(path2, xfile2) except UF.CHBError as e: print(str(e.wrap())) exit(1) xinfo2 = XI.XInfo() xinfo2.load(path2, xfile2) app1 = UC.get_app(path1, xfile1, xinfo1) app2 = UC.get_app(path2, xfile2, xinfo2) relanalysis = RelationalAnalysis(app1, app2, faddrs1=xfunctions1, faddrs2=xfunctions2, usermapping=usermapping, callees=callees) print(relanalysis.report(showfunctions, showinstructions)) exit(0)
def get_path(xname, checkresults=False): try: name = os.path.abspath(xname) path = os.path.dirname(name) filename = os.path.basename(name) if checkresults: UF.check_analysis_results(path, filename) except UF.CHBError as e: print(str(e.wrap())) exit(1) return (path, filename)
def collect_data(atfi, records, includes, excludes, args): xcount = 0 fncount = 0 for atxi in records: r = records[atxi] if satisfies_spec(r, includes, excludes): name = UF.mk_atsc(atfi, atxi) if is_representative(r): try: (path, filename) = UF.get_path_filename('x86-pe', name) UF.check_analysis_results(path, filename) except UF.CHBError as e: print('**** problem with ' + name + ': ' + str(e)) continue fnmapfilename = UF.get_fn_map_filename(path, filename) fnfeaturefilename = UF.get_fn_features_filename(path, filename) if not os.path.isfile(fnfeaturefilename): continue with open(fnfeaturefilename, 'r') as fp: fnfeatures = json.load(fp) if not os.path.isfile(fnmapfilename): continue xcount += 1 fndata[name] = {} app = AP.AppAccess(path, filename) if len(args.printfunctions) > 0: apps[k] = app metrics = app.get_result_metrics() fncount += metrics.get_function_count() with open(fnmapfilename, 'r') as fp: fnmap = json.load(fp) fnstats[name] = (metrics.get_function_count(), len(fnmap['functions'])) for fn in fnmap['functions']: if not fn in fnfeatures: continue fnmd5 = fnfeatures[fn]['md5'] fnrec = fndata[name][fn] = {} fnmetrics = metrics.get_function_metrics(fn) if fnmetrics is None: print(name + ': Function ' + fn + ' not found') continue try: fnrec['md5'] = fnmd5 fnrec['reffn'] = fnmap['functions'][fn]['reffn'] fnrec['score'] = fnmap['functions'][fn]['score'] fnrec['esp'] = fnmetrics.get_espp() fnrec['blocks'] = fnmetrics.get_blocks() fnrec['instrs'] = fnmetrics.get_instrs() fnrec['unrc'] = fnmetrics.get_unresolved_calls() if fnmetrics.has_name(): fnrec['name'] = fnmetrics.get_name() except: print('Problem in ' + name + ', ' + fn) raise return (xcount, fncount)
def load_mips_lib_file(libxname: str) -> Tuple["MIPSAccess", "MIPSAssembly"]: try: (libpath, libxfile) = UC.get_path_filename(libxname) UF.check_analysis_results(libpath, libxfile) except UF.CHBError as e: print(str(e.wrap())) exit(1) libxinfo = XI.XInfo() libxinfo.load(libpath, libxfile) libapp = cast("MIPSAccess", UC.get_app(libpath, libxfile, libxinfo)) libasm = cast("MIPSAssembly", UC.get_asm(libapp)) return (libapp, libasm)
def check_test_case(filename: str) -> int: testdatafile = filename + ".json" try: with open(testdatafile, "r") as fp: testdata = json.load(fp) except Exception as e: print(str(e)) return (-1) try: (path, xfile) = UC.get_path_filename(filename) UF.check_analysis_results(path, xfile) except UF.CHBError as e: print(str(e.wrap())) exit(1) xinfo = XI.XInfo() xinfo.load(path, xfile) app = UC.get_app(path, xfile, xinfo) for faddr in testdata["functions"]: if app.has_function(faddr): f = app.function(faddr) fstats = app.result_metrics.get_function_metrics(faddr) result = check_test_function(f, fstats, testdata["functions"][faddr]) if result != 0: break else: print("Function " + faddr + " not found in results") result = (-1) break else: result = 0 return result
import chb.app.AppAccess as AP def parse(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('filename', help='name of executable') args = parser.parse_args() return args if __name__ == '__main__': args = parse() try: (path, filename) = UF.get_path_filename('mips-elf', args.filename) UF.check_analysis_results(path, filename) except UF.CHBError as e: print(str(e.wrap())) exit(1) app = AP.AppAccess(path, filename, mips=True) result = [] for fn in app.functionsdata.functions: fndata = app.functionsdata.functions[fn] if fndata.is_by_preamble(): result.append(fndata.faddr) dresult = {} dresult['function-entry-points'] = result fefilename = os.path.join(path,
def report_memops(args: argparse.Namespace) -> NoReturn: # arguments xname: str = args.xname try: (path, xfile) = UC.get_path_filename(xname) UF.check_analysis_results(path, xfile) except UF.CHBError as e: print(str(e.wrap())) exit(1) xinfo = XI.XInfo() xinfo.load(path, xfile) app = UC.get_app(path, xfile, xinfo) memloads = app.load_instructions() memstores = app.store_instructions() loadstats: Dict[str, Tuple[int, int]] = {} storestats: Dict[str, Tuple[int, int]] = {} def add_load_unknown(faddr: str) -> None: loadstats.setdefault(faddr, (0, 0)) v = loadstats[faddr] loadstats[faddr] = (v[0] + 1, v[1]) def add_load_known(faddr: str) -> None: loadstats.setdefault(faddr, (0, 0)) v = loadstats[faddr] loadstats[faddr] = (v[0] + 1, v[1] + 1) loadxrefs: Dict[str, List[str]] = {} def add_load_xref(gv: str, faddr: str) -> None: loadxrefs.setdefault(gv, []) loadxrefs[gv].append(faddr) print("Load instructions") print("-----------------") for faddr in sorted(memloads): print("\nFunction " + faddr) for baddr in memloads[faddr]: print(" Block: " + baddr) for instr in memloads[faddr][baddr]: print(" " + str(instr)) for rhs in instr.rhs: add_load_xref(str(rhs), faddr) if str(rhs) == "?": add_load_unknown(faddr) else: add_load_known(faddr) def add_store_unknown(faddr: str) -> None: storestats.setdefault(faddr, (0, 0)) v = storestats[faddr] storestats[faddr] = (v[0] + 1, v[1]) def add_store_known(faddr: str) -> None: storestats.setdefault(faddr, (0, 0)) v = storestats[faddr] storestats[faddr] = (v[0] + 1, v[1] + 1) storexrefs: Dict[str, List[str]] = {} def add_store_xref(gv: str, faddr: str) -> None: storexrefs.setdefault(gv, []) storexrefs[gv].append(faddr) print("\n\nStore instructions") print("----------------------") for faddr in sorted(memstores): print("\nFunction " + faddr) for baddr in memstores[faddr]: print(" Block: " + baddr) for instr in memstores[faddr][baddr]: print(" " + str(instr)) for lhs in instr.lhs: add_store_xref(str(lhs), faddr) if str(lhs) in ["?", "??operand??"]: add_store_unknown(faddr) else: add_store_known(faddr) print("\nLoad xreferences") print("------------------") for gv in sorted(loadxrefs): if gv.startswith("gv_"): print(gv.ljust(24) + "[" + ", ".join(loadxrefs[gv]) + "]") print("\nStore xreferences") print("-------------------") for gv in sorted(storexrefs): if gv.startswith("gv"): print(gv.ljust(24) + "[" + ", ".join(storexrefs[gv]) + "]") print("\nLoad statistics") print("-----------------") loadtotal: int = 0 loadknown: int = 0 for faddr in sorted(loadstats): ftotal = loadstats[faddr][0] fknown = loadstats[faddr][1] loadtotal += ftotal loadknown += fknown print(faddr + ": " + str(fknown).rjust(4) + " / " + str(ftotal).ljust(4)) perc = (loadknown / loadtotal) * 100 fperc = "{:.2f}".format(perc) print("\nTotal: " + str(loadknown) + " / " + str(loadtotal) + " (" + fperc + "%)") print("\nStore statistics") print("------------------") storetotal = 0 storeknown = 0 for faddr in sorted(storestats): ftotal = storestats[faddr][0] fknown = storestats[faddr][1] storetotal += ftotal storeknown += fknown print(faddr + ": " + str(fknown).rjust(4) + " / " + str(ftotal).ljust(4)) perc = (storeknown / storetotal) * 100 fperc = "{:.2f}".format(perc) print("\nTotal: " + str(storeknown) + " / " + str(storetotal) + " (" + fperc + "%)") exit(0)
def simulate_function_cmd(args: argparse.Namespace) -> NoReturn: # arguments xname: str = args.xname faddr: str = args.faddr stepcount: int = args.steps libs: List[str] = args.libs support: Optional[str] = args.support stub_imports: List[str] = args.stub_imports mainargs: List[str] = args.mainargs optargaddrstr: Optional[str] = args.optargaddr optargstatestr: Optional[str] = args.optargstate patched_globals: List[str] = args.patched_globals envptr_addr: Optional[str] = args.envptr_addr mainargs = [a.strip() for a in mainargs] try: (path, xfile) = UC.get_path_filename(xname) UF.check_analysis_results(path, xfile) except UF.CHBError as e: print(str(e.wrap())) exit(1) libnames = unpack_named_strings(libs) libapps: Dict[str, Tuple["MIPSAccess", "MIPSAssembly"]] = {} for (name, libxname) in libnames.items(): libapps[name] = load_mips_lib_file(libxname) xinfo = XI.XInfo() xinfo.load(path, xfile) print(str(xinfo)) app = UC.get_app(path, xfile, xinfo) asm = UC.get_asm(app) if xinfo.is_mips: app = cast("MIPSAccess", app) asm = cast("MIPSAssembly", asm) simulate_mips_function( xname, app, asm, faddr, stepcount=stepcount, libs=libapps, support=support, stub_imports=stub_imports, mainargs=[x.lstrip() for x in mainargs], optargaddrstr=optargaddrstr, optargstatestr=optargstatestr, patched_globals=unpack_named_strings(patched_globals), envptr_addr=envptr_addr) elif xinfo.is_arm: app = cast("ARMAccess", app) asm = cast("ARMAssembly", asm) simulate_arm_function(xname, app, asm, faddr) else: UC.print_error( "Simulation not yet implemented for " + app.__class__.__name__) exit(1)