Beispiel #1
0
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)
Beispiel #2
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
Beispiel #7
0
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,
Beispiel #8
0
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)