Esempio n. 1
0
def analyze(bytecode: str,
            contract_name,
            result_printer: Printer,
            verbose=False) -> ContractReport:
    result_printer.info("***************************************************")
    result_printer.info("Analyzing contract: {0}".format(contract_name))
    result = ContractReport()
    c_printer = CPrinter()
    instructions = ByteCode.disasm(bytecode, c_printer)

    result_printer.info("Symbolically executing")
    analyzer = Analyzer(instructions, result_printer, verbose)
    # analyze construction code
    result_printer.info("Checking construction assemble code")
    cfg_r = analyze_cfg(analyzer.construct_cfg, result_printer)
    result.add(cfg_r)
    result_printer.info("Checking construction assemble code...done")
    result_printer.info("- - - - - - - - - - - - - - - - - - - - - - - - - -")
    # analyze body code
    result_printer.info("Checking runtime assemble code")
    cfg_r = analyze_cfg(analyzer.body_cfg, result_printer, verbose)
    result.add(cfg_r)
    result_printer.info("Checking runtime assemble code...done")
    result_printer.info("***************************************************")
    return result
Esempio n. 2
0
def process(args):
    c_printer = CPrinter()
    result = {}
    if args.result is not None:
        if not os.path.exists(args.result):
            c_printer.error(
                "Result output directory '{0}' does not exist".format(
                    args.result))
            sys.exit(-1)
        if not os.path.isdir(args.result):
            c_printer.error("'{0}' is not a directory".format(args.result))
            sys.exit(-1)
    if args.file:
        if args.source and args.extension is None:
            args.extension = 'sol'
        elif args.bytecode and args.extension is None:
            args.extension = 'hex'
        c_printer.info("processing files with extension '{0}'".format(
            args.extension))
        for s in args.input:
            f_r = FileReport()
            if os.path.splitext(s)[-1][1:] != args.extension:
                c_printer.warn("file '{0}' extension mismatch".format(s))
                c_printer.warn("skipping '{0}'".format(s))
                continue
            if not os.path.exists(s):
                c_printer.error("file '{0}' does not exist".format(s))
                c_printer.warn("skipping '{0}'".format(s))
            elif not os.path.isfile(s):
                c_printer.error("'{0}' is not a file".format(s))
                c_printer.warn("skipping '{0}'".format(s))
            else:
                with open(s) as file:
                    c_printer.info("start analyzing {0}".format(s))
                    try:
                        if args.source:
                            bytecodes = utils.compile_sol(s, args.t_runtime)
                        else:
                            bytecodes = ''.join(file.readlines())

                        for contract_name, bytecode in bytecodes:
                            if args.result is not None:
                                filename = os.path.splitext(s)[0] + ".txt"
                                f_printer = FPrinter(filename=os.path.join(
                                    args.result, filename))
                                c_r = analyze(bytecode, contract_name,
                                              f_printer)
                            else:
                                c_r = analyze(bytecode, contract_name,
                                              c_printer)
                            f_r.add(c_r)
                    except AttributeError as e:
                        c_printer.error(str(e))
                        c_printer.warn("fail to analyze {0}".format(s))
                    except AnalyzerException as e:
                        c_printer.warn("Unsupported feature: {}".format(e))
                        c_printer.warn("fail to analyze {0}".format(s))
                    except TimeoutException:
                        c_printer.warn("Analyze timeout")
                        c_printer.warn("fail to analyze {0}".format(s))
                    except Exception as e:
                        c_printer.error("SmSymer internal Error: {}".format(e))
                        c_printer.warn("fail to analyze {0}".format(s))
                    else:
                        c_printer.info("finish analyzing {0}".format(s))
            result[s] = f_r
    elif args.dir:
        if args.source and args.extension is None:
            args.extension = 'sol'
        elif args.bytecode and args.extension is None:
            args.extension = 'hex'
        c_printer.info("processing files with extension '{0}'".format(
            args.extension))
        for s in args.input:
            if not os.path.exists(s):
                c_printer.error("directory '{0}' does not exist")
                c_printer.warn("skipping '{0}'")
            elif not os.path.isdir(s):
                c_printer.error("'{0}' is not a directory")
                c_printer.warn("skipping '{0}'")
            else:
                f_r = process_dir(s, args)
                result.update(f_r)
    else:
        for i, s in enumerate(args.input):
            bytecode = s
            c_printer.info("start analyzing {0}".format(s))
            f_r = FileReport()
            try:
                if args.result is not None:
                    filename = str(i) + ".txt"
                    f_printer = FPrinter(
                        filename=os.path.join(args.result, filename))
                    c_r = analyze(bytecode, '', f_printer)
                else:
                    c_r = analyze(bytecode, '', c_printer)
                f_r.add(c_r)
            except AttributeError as e:
                c_printer.error(str(e))
                c_printer.warn("fail to analyze {0}".format(s))
            except AnalyzerException as e:
                c_printer.warn("Unsupported feature: {}".format(e))
                c_printer.warn("fail to analyze {0}".format(s))
            except TimeoutException:
                c_printer.warn("Analyze timeout")
                c_printer.warn("fail to analyze {0}".format(s))
            except Exception as e:
                c_printer.error("SmSymer internal Error: {}".format(e))
                c_printer.warn("fail to analyze {0}".format(s))
            else:
                c_printer.info("finish analyzing {0}".format(s))
            result[i] = f_r

    # t_result_file = "/home/troublor/Desktop/result/t_contracts"
    # t_r_printer = FPrinter(t_result_file)
    # u_result_file = "/home/troublor/Desktop/result/u_contracts"
    # u_r_printer = FPrinter(u_result_file)
    # r_result_file = "/home/troublor/Desktop/result/r_contracts"
    # r_r_printer = FPrinter(r_result_file)

    c_printer.info("***********************************")
    f_total = 0
    f_success = 0
    c_total = 0
    c_success = 0
    n_td = 0
    n_td_f = 0
    n_uc = 0
    n_r = 0
    for filename, f_r in result.items():
        f_total += 1
        if f_r.success:
            f_success += 1
        has_timestamp = False
        for c_r in f_r.c_reports:
            c_total += 1
            if c_r.success:
                c_success += 1
            for cfg_r in c_r.cfg_reports:
                if cfg_r.n_timestamp_dependency > 0:
                    n_td += 1
                    has_timestamp = True
                    # t_r_printer.print(filename)
                    break
            for cfg_r in c_r.cfg_reports:
                if cfg_r.n_unchecked_call > 0:
                    n_uc += 1
                    # u_r_printer.print(filename)
                    break
            for cfg_r in c_r.cfg_reports:
                if cfg_r.n_reentrancy > 0:
                    n_r += 1
                    # r_r_printer.print(filename)
                    break
        if has_timestamp:
            n_td_f += 1
    c_printer.info("SmSymer analyzed {0} files".format(f_total))
    c_printer.info("{0} success files, containing {1} contracts".format(
        f_success, c_total))
    c_printer.info("{0} success analyzed contracts".format(c_success))
    c_printer.info(
        "{0} contracts contains Timestamp Dependency Vulnerability".format(
            n_td))
    c_printer.info(
        "{0} contracts contains Unchecked Call Vulnerability".format(n_uc))
    c_printer.info(
        "{0} contracts contains Reentrancy Vulnerability".format(n_r))
    c_printer.info(
        "{0} files contains Timestamp Dependency Vulnerability".format(n_td_f))
Esempio n. 3
0
def process_dir(directory: str, args) -> Dict[str, FileReport]:
    result = {}
    c_printer = CPrinter()
    for item in os.listdir(directory):
        f_r: FileReport = FileReport()
        if os.path.isdir(item):
            if args.recursively:
                process_dir(item, args)
            else:
                c_printer.warn(
                    "not specify -R option, skipping subdirectory '{}'".format(
                        item))
        else:
            if os.path.splitext(item)[-1][1:] != args.extension:
                c_printer.warn("file '{0}' extension mismatch".format(item))
                c_printer.warn("skipping '{0}'".format(item))
                continue
            with open(os.path.join(directory, item)) as file:
                c_printer.info("start analyzing {0}".format(
                    os.path.join(directory, item)))
                try:
                    if args.source:
                        bytecodes = utils.compile_sol(
                            os.path.join(directory, item), args.t_runtime)
                    else:
                        bytecodes = ''.join(file.readlines())
                    for contract_name, bytecode in bytecodes:
                        if args.result is not None:
                            filename = os.path.join(
                                args.result,
                                os.path.split(directory)[0], item + ".txt")
                            f_printer = FPrinter(filename=filename)
                            c_r = analyze(bytecode, contract_name, f_printer)
                            f_r.add(c_r)
                        else:
                            c_r = analyze(bytecode, contract_name, c_printer)
                            f_r.add(c_r)
                except AttributeError as e:
                    c_printer.error(str(e))
                    traceback.print_exc()
                    c_printer.warn("fail to analyze {0}".format(
                        os.path.join(directory, item)))
                except AnalyzerException as e:
                    c_printer.warn("Unsupported feature: {}".format(e))
                    c_printer.warn("fail to analyze {0}".format(
                        os.path.join(directory, item)))
                except TimeoutException:
                    c_printer.warn("Analyze timeout")
                    c_printer.warn("fail to analyze {0}".format(
                        os.path.join(directory, item)))
                except Exception as e:
                    c_printer.error("SmSymer internal Error: {}".format(e))
                    traceback.print_exc()
                    c_printer.warn("fail to analyze {0}".format(
                        os.path.join(directory, item)))
                else:
                    c_printer.info("finish analyzing {0}".format(
                        os.path.join(directory, item)))
        result[os.path.join(directory, item)] = f_r
    return result
Esempio n. 4
0
def process_dir(directory: str, args):
    c_printer = CPrinter()
    for item in os.listdir(directory):
        if os.path.isdir(item):
            if args.recursively:
                process_dir(item, args)
            else:
                c_printer.warn(
                    "not specify -R option, skipping subdirectory '{}'".format(
                        item))
        else:
            if os.path.splitext(item)[-1][1:] != args.extension:
                c_printer.warn("file '{0}' extension mismatch".format(item))
                c_printer.warn("skipping '{0}'".format(item))
                continue
            with open(os.path.join(directory, item)) as file:
                c_printer.info("start disassembling {0}".format(
                    os.path.join(directory, item)))
                try:
                    if args.source:
                        _, bytecode = utils.compile_sol(
                            os.path.join(directory, item))[0]
                    else:
                        bytecode = ''.join(file.readlines())
                    if args.result is not None:
                        filename = os.path.join(args.result,
                                                os.path.split(directory)[0],
                                                item + ".asm")
                        f_printer = FPrinter(filename=filename)
                        f_printer.print(disasm(bytecode))
                    else:
                        c_printer.print(disasm(bytecode))
                except AttributeError as e:
                    c_printer.error(str(e))
                    c_printer.info("fail to disassemble {0}".format(
                        os.path.join(directory, item)))
                else:
                    c_printer.info("finish disassembling {0}".format(
                        os.path.join(directory, item)))
Esempio n. 5
0
def disasm(bytecode: str) -> List[str]:
    c_printer = CPrinter()
    instructions = ByteCode.disasm(bytecode, c_printer)
    return list(map(lambda ins: str(ins), instructions))
Esempio n. 6
0
def process(args):
    c_printer = CPrinter()
    if args.result is not None:
        if not os.path.exists(args.result):
            c_printer.error(
                "Result output directory '{0}' does not exist".format(
                    args.result))
            sys.exit(-1)
        if not os.path.isdir(args.result):
            c_printer.error("'{0}' is not a directory".format(args.result))
            sys.exit(-1)
    if args.file:
        if args.source and args.extension is None:
            args.extension = 'sol'
        elif args.bytecode and args.extension is None:
            args.extension = 'hex'
        c_printer.info("processing files with extension '{0}'".format(
            args.extension))
        for s in args.input:
            if os.path.splitext(s)[-1][1:] != args.extension:
                c_printer.warn("file '{0}' extension mismatch".format(s))
                c_printer.warn("skipping '{0}'".format(s))
                continue
            if not os.path.exists(s):
                c_printer.error("file '{0}' does not exist".format(s))
                c_printer.warn("skipping '{0}'".format(s))
            elif not os.path.isfile(s):
                c_printer.error("'{0}' is not a file".format(s))
                c_printer.warn("skipping '{0}'".format(s))
            else:
                with open(s) as file:
                    c_printer.info("start disassembling {0}".format(s))
                    try:
                        if args.source:
                            _, bytecode = utils.compile_sol(s)[0]
                        else:
                            bytecode = ''.join(file.readlines())
                        if args.result is not None:
                            filename = os.path.splitext(s)[0] + ".asm"
                            f_printer = FPrinter(
                                filename=os.path.join(args.result, filename))
                            f_printer.print(disasm(bytecode))
                        else:
                            c_printer.print(disasm(bytecode))
                    except AttributeError as e:
                        c_printer.error(str(e))
                        c_printer.info("fail to disassemble {0}".format(s))
                    else:
                        c_printer.info("finish disassembling {0}".format(s))
    elif args.dir:
        if args.source and args.extension is None:
            args.extension = 'sol'
        elif args.bytecode and args.extension is None:
            args.extension = 'hex'
        c_printer.info("processing files with extension '{0}'".format(
            args.extension))
        for s in args.input:
            if not os.path.exists(s):
                c_printer.error("directory '{0}' does not exist")
                c_printer.warn("skipping '{0}'")
            elif not os.path.isdir(s):
                c_printer.error("'{0}' is not a directory")
                c_printer.warn("skipping '{0}'")
            else:
                process_dir(s, args)
    else:
        for i, s in enumerate(args.input):
            bytecode = s
            c_printer.info("start disassembling {0}".format(s))
            try:
                if args.result is not None:
                    filename = str(i) + ".asm"
                    f_printer = FPrinter(
                        filename=os.path.join(args.result, filename))
                    f_printer.print(disasm(bytecode))
                else:
                    c_printer.print(disasm(bytecode))
            except AttributeError as e:
                c_printer.error(str(e))
                c_printer.info("fail to disassemble {0}".format(s))
            else:
                c_printer.info("finish disassembling {0}".format(s))
Esempio n. 7
0
def process(args):
    c_printer = CPrinter()
    if args.file:
        s = args.input
        if not os.path.exists(s):
            c_printer.error("file '{0}' does not exist".format(s))
        elif not os.path.isfile(s):
            c_printer.error("'{0}' is not a file".format(s))
        else:
            with open(s) as file:
                c_printer.info("start debugging {0}".format(s))
                try:
                    bytecode = ''.join(file.readlines())
                    instructions = ByteCode.disasm(bytecode, c_printer)
                    debugger = Debugger(instructions, c_printer)
                    debugger.start()
                except AttributeError as e:
                    c_printer.error(str(e))
                    c_printer.info("fail to debug {0}".format(s))
                else:
                    c_printer.info("finish debugging {0}".format(s))
    else:
        bytecode = args.input
        c_printer.info("start debugging")
        try:
            instructions = ByteCode.disasm(bytecode, c_printer)
            debugger = Debugger(instructions, c_printer)
            debugger.start()
        except AttributeError as e:
            c_printer.error(str(e))
            c_printer.info("fail to debug")
        else:
            c_printer.info("finish debugging")