Example #1
0
def check_annotations(contracts, address, eth, dynld, max_depth=12):

    logging.debug("Executing annotations check")

    for contract in contracts:

        contr_to_const = deepcopy(contract)
        contr_to_const.disassembly = Disassembly(contr_to_const.creation_code)
        contr_to_const.code = contr_to_const.creation_code
        dynloader = DynLoader(eth) if dynld else None
        glbstate = get_constr_glbstate(contr_to_const, address)

        sym_constructor = SymExecWrapper(contr_to_const, address, dynloader,
                                         max_depth, glbstate)
        sym_contract = SymExecWrapper(contract,
                                      address,
                                      dynloader,
                                      max_depth=max_depth)

        constructor_trace = get_construction_traces(
            sym_constructor
        )  # Todo the traces here should not contain references to storages anymore
        for t in constructor_trace:
            t.pp_trace()

        traces = get_transaction_traces(sym_contract)
        print("Start")
        a = process_time()
        print("const: " + str(len(constructor_trace)) + " trans: " +
              str(len(traces)))
        trace_chains = []
        for trace in constructor_trace:
            comp_trace_lvls = trace.apply_up_to_trace_levels(traces, 1)
            if not trace_chains:
                trace_chains = comp_trace_lvls
            else:
                for index in range(len(trace_chains)):
                    trace_chains[index].extend(comp_trace_lvls[index])
            print()
        for lvl in trace_chains:
            print("Traces: " + str(len(lvl)))

        #for tt in trace_chains[-1]:
        #    tt.pp_trace()
        #    for trace_lvl in comp_trace_lvls:
        #        print(len(trace_lvl))
        #        print(sum(map(lambda t: len(t.tran_constraints), trace_lvl))/len(trace_lvl))
        #        for t in trace_lvl:
        #            print("constraints: " + str(len(t.tran_constraints)))
        #            t.pp_trace()
        print(process_time() - a)
Example #2
0
    def fire_lasers(
        self,
        strategy,
        contracts=None,
        address=None,
        modules=None,
        verbose_report=False,
        max_depth=None,
        execution_timeout=None,
    ):

        all_issues = []
        for contract in (contracts or self.contracts):
            sym = SymExecWrapper(
                contract,
                address,
                strategy,
                dynloader=DynLoader(self.eth) if self.dynld else None,
                max_depth=max_depth,
                execution_timeout=execution_timeout)

            issues = fire_lasers(sym, modules)

            if type(contract) == SolidityContract:
                for issue in issues:
                    issue.add_code_info(contract)

            all_issues += issues

        # Finally, output the results
        report = Report(verbose_report)
        for issue in all_issues:
            report.append_issue(issue)

        return report
Example #3
0
    def analyze(self, address):
        """
        Analyse a contract using mythril
        :param address: Address of contract to analyse
        :return: Findings
        """
        # The followin code is kinda straight from mythril, thanks ;)
        # Setup
        code = self.eth.eth_getCode(address)

        contract = ETHContract(code, name=address)
        sym = SymExecWrapper(contract, address, dynloader=DynLoader(self.eth))
        # Starting analysis
        logging.debug(
            "Firing lasers on contract with address: {}".format(address))
        issues = fire_lasers(sym)

        logging.debug("Found {} issues using mythril".format(len(issues)))

        # Build findings
        findings = []
        for issue in issues:
            findings += [
                Finding("Mythril analysis", issue.title, issue.description,
                        issue.contract, issue.pc, issue.type)
            ]

        return findings
Example #4
0
def test_symbolic_call_calldata_to(mocker):
    # arrange
    address = "0x10"

    state = GlobalState(None, None, None)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "the function name"

    to = Variable("calldata", VarType.SYMBOLIC)
    call = Call(node, state, None, "Type: ", to, None)

    mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None)
    statespace = SymExecWrapper(1)

    mocker.patch.object(statespace, "find_storage_write")
    statespace.find_storage_write.return_value = "Function name"

    # act
    issues = _symbolic_call(call, state, address, statespace)

    # assert
    issue = issues[0]
    assert issue.address == address
    assert issue.contract == node.contract_name
    assert issue.function == node.function_name
    assert issue.title == "Type:  to a user-supplied address"
    assert issue.type == "Informational"
    assert (
        issue.description ==
        "This contract delegates execution to a contract address obtained from calldata. "
        "Be aware that the called contract gets unrestricted access to this contract's state."
    )
Example #5
0
    def dump_statespace(self, contract: EVMContract = None) -> str:
        """
        Returns serializable statespace of the contract
        :param contract: The Contract on which the analysis should be done
        :return: The serialized state space
        """
        sym = SymExecWrapper(
            contract or self.contracts[0],
            self.address,
            self.strategy,
            dynloader=DynLoader(
                self.eth,
                storage_loading=self.onchain_storage_access,
                contract_loading=self.dynld,
            ),
            max_depth=self.max_depth,
            execution_timeout=self.execution_timeout,
            create_timeout=self.create_timeout,
            enable_iprof=self.enable_iprof,
            disable_dependency_pruning=self.disable_dependency_pruning,
            run_analysis_modules=False,
            enable_coverage_strategy=self.enable_coverage_strategy,
            custom_modules_directory=self.custom_modules_directory,
        )

        return get_serializable_statespace(sym)
Example #6
0
def symbolic_execute(code, address):
    contract = ETHContract(code)
    sym = SymExecWrapper(contract=contract, address=address, strategy="dfs")

    # populate graph object
    graph = MythrilSymExecGraph()
    for n in sym.nodes.values():
        # g.add all nodes - just in case one is not connected which should not happen
        graph.add_node(n)

    for e in sym.edges:
        graph.add_edge(sym.nodes[e.node_from], sym.nodes[e.node_to], e)
    """
    print(graph.iterate_graph())
    print(sorted([x.uid for x in graph.nodes]))
    print(graph._first_added.uid)
    print(next(graph.get_basicblocks_by_address(0)))
    print(graph.get_basicblock_by_uid(0))
    print(list(n.uid for n in graph.iterate_graph(graph.get_basicblock_by_uid(0))))

    print(graph.find_all_paths(graph.get_basicblock_by_uid(0), graph.get_basicblock_by_uid(37)))
    print(graph.find_all_paths(graph.get_basicblock_by_uid(0),None))
    print("streams")
    for stream in graph.get_streams(graph.get_basicblock_by_uid(0)):
        print([s.uid for s in stream])
    
    print(list(s.get_current_instruction() for b,s in graph.get_block_and_state_by_instruction_name("PUSH",prn_cmp=lambda x,y:x.startswith(y))))

    print(graph.get_stream_by_block(block=graph.get_block_by_uid(2)))
    """
    # only work on the graph from now
    return graph
Example #7
0
    def dump_statespace(self, strategy, contract, address=None, max_depth=12):

        sym = SymExecWrapper(contract, address, strategy,
                             dynloader=DynLoader(self.eth) if self.dynld else None,
                             max_depth=max_depth)

        return get_serializable_statespace(sym)
Example #8
0
    def fire_lasers(self,
                    contracts=None,
                    address=None,
                    modules=None,
                    verbose_report=False,
                    max_depth=12):

        all_issues = []
        if self.dynld and self.eth is None:
            self.set_api_rpc_infura()
        for contract in (contracts or self.contracts):
            sym = SymExecWrapper(
                contract,
                address,
                dynloader=DynLoader(self.eth) if self.dynld else None,
                max_depth=max_depth)

            issues = fire_lasers(sym, modules)

            if type(contract) == SolidityContract:
                for issue in issues:
                    issue.add_code_info(contract)

            all_issues += issues

        # Finally, output the results
        report = Report(verbose_report)
        for issue in all_issues:
            report.append_issue(issue)

        return report
Example #9
0
    def test_generate_graph(self):
        for input_file in TESTDATA_INPUTS.iterdir():
            output_expected = TESTDATA_OUTPUTS_EXPECTED / (
                input_file.name + ".graph.html"
            )
            output_current = TESTDATA_OUTPUTS_CURRENT / (
                input_file.name + ".graph.html"
            )

            contract = EVMContract(input_file.read_text())

            sym = SymExecWrapper(
                contract,
                address=(util.get_indexed_address(0)),
                strategy="dfs",
                transaction_count=1,
                execution_timeout=5,
            )

            html = generate_graph(sym)
            output_current.write_text(html)

            lines_expected = re.findall(
                r"'label': '.*'", str(output_current.read_text())
            )
            lines_found = re.findall(r"'label': '.*'", str(output_current.read_text()))
            if not (lines_expected == lines_found):
                self.found_changed_files(input_file, output_expected, output_current)

        self.assert_and_show_changed_files()
Example #10
0
def test_symbolic_call_storage_to(mocker):
    # arrange
    address = "0x10"

    active_account = Account(address)
    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "the function name"

    to = Variable("storage_1", VarType.SYMBOLIC)
    call = Call(node, state, None, "Type: ", to, None)

    mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None)
    statespace = SymExecWrapper(1)

    mocker.patch.object(statespace, 'find_storage_write')
    statespace.find_storage_write.return_value = "Function name"

    # act
    issues = _symbolic_call(call, state, address, statespace)

    # assert
    issue = issues[0]
    assert issue.address == address
    assert issue.contract == node.contract_name
    assert issue.function == node.function_name
    assert issue.title == 'Type:  to a user-supplied address'
    assert issue.type == 'Informational'
    assert issue.description == 'This contract delegates execution to a contract address in storage slot 1.' \
                                ' This storage slot can be written to by calling the function `Function name`. ' \
                                'Be aware that the called contract gets unrestricted access to this contract\'s state.'
Example #11
0
 def graph_html(
     self,
     strategy,
     contract,
     address,
     max_depth=None,
     enable_physics=False,
     phrackify=False,
     execution_timeout=None,
     create_timeout=None,
 ):
     sym = SymExecWrapper(
         contract,
         address,
         strategy,
         dynloader=DynLoader(
             self.eth,
             storage_loading=self.onchain_storage_access,
             contract_loading=self.dynld,
         ),
         max_depth=max_depth,
         execution_timeout=execution_timeout,
         create_timeout=create_timeout,
     )
     return generate_graph(sym, physics=enable_physics, phrackify=phrackify)
Example #12
0
    def fire_lasers(
        self,
        modules: Optional[List[str]] = None,
        transaction_count: Optional[int] = None,
    ) -> Report:
        """
        :param modules: The analysis modules which should be executed
        :param transaction_count: The amount of transactions to be executed
        :return: The Report class which contains the all the issues/vulnerabilities
        """
        all_issues = []  # type: List[Issue]
        SolverStatistics().enabled = True
        exceptions = []
        for contract in self.contracts:
            StartTime()  # Reinitialize start time for new contracts
            try:
                sym = SymExecWrapper(
                    contract,
                    self.address,
                    self.strategy,
                    dynloader=DynLoader(
                        self.eth,
                        storage_loading=self.onchain_storage_access,
                        contract_loading=self.dynld,
                    ),
                    max_depth=self.max_depth,
                    execution_timeout=self.execution_timeout,
                    loop_bound=self.loop_bound,
                    create_timeout=self.create_timeout,
                    transaction_count=transaction_count,
                    modules=modules,
                    compulsory_statespace=False,
                    enable_iprof=self.enable_iprof,
                    disable_dependency_pruning=self.disable_dependency_pruning,
                )

                issues = fire_lasers(sym, modules)
            except KeyboardInterrupt:
                log.critical("Keyboard Interrupt")
                issues = retrieve_callback_issues(modules)
            except Exception:
                log.critical(
                    "Exception occurred, aborting analysis. Please report this issue to the Mythril GitHub page.\n"
                    + traceback.format_exc())
                issues = retrieve_callback_issues(modules)
                exceptions.append(traceback.format_exc())
            for issue in issues:
                issue.add_code_info(contract)

            all_issues += issues
            log.info("Solver statistics: \n{}".format(str(SolverStatistics())))

        source_data = Source()
        source_data.get_source_from_contracts_list(self.contracts)
        # Finally, output the results
        report = Report(contracts=self.contracts, exceptions=exceptions)
        for issue in all_issues:
            report.append_issue(issue)

        return report
Example #13
0
    def dump_statespace(
        self,
        strategy,
        contract,
        address=None,
        max_depth=None,
        execution_timeout=None,
        create_timeout=None,
    ):

        sym = SymExecWrapper(
            contract,
            address,
            strategy,
            dynloader=DynLoader(
                self.eth,
                storage_loading=self.onchain_storage_access,
                contract_loading=self.dynld,
            ),
            max_depth=max_depth,
            execution_timeout=execution_timeout,
            create_timeout=create_timeout,
        )

        return get_serializable_statespace(sym)
Example #14
0
    def slither_graph_html(self,
                           strategy,
                           contract,
                           address,
                           max_depth=None,
                           enable_physics=False,
                           phrackify=False,
                           execution_timeout=None,
                           create_timeout=None,
                           file=None):
        priority = self.parse_slither(contract=contract, file=file[0])

        sym = SymExecWrapper(contract,
                             address,
                             strategy,
                             dynloader=DynLoader(
                                 self.eth,
                                 storage_loading=self.onchain_storage_access,
                                 contract_loading=self.dynld,
                             ),
                             max_depth=max_depth,
                             execution_timeout=execution_timeout,
                             create_timeout=create_timeout,
                             priority=priority)
        return generate_graph(sym, physics=enable_physics, phrackify=phrackify)
Example #15
0
 def graph_html(self,
                strategy,
                contract,
                address,
                max_depth=None,
                enable_physics=False,
                phrackify=False,
                execution_timeout=None,
                create_timeout=None,
                transaction_count=2,
                enable_iprof=False):
     """
     :param strategy:
     :param contract:
     :param address:
     :param max_depth:
     :param enable_physics:
     :param phrackify:
     :param execution_timeout:
     :param create_timeout:
     :return:
     """
     sym = SymExecWrapper(contract,
                          address,
                          strategy,
                          dynloader=DynLoader(
                              self.eth,
                              storage_loading=self.onchain_storage_access,
                              contract_loading=self.dynld,
                          ),
                          max_depth=max_depth,
                          execution_timeout=execution_timeout,
                          create_timeout=create_timeout,
                          transaction_count=transaction_count)
     return generate_graph(sym, physics=enable_physics, phrackify=phrackify)
Example #16
0
    def graph_html(
        self,
        contract: EVMContract = None,
        enable_physics: bool = False,
        phrackify: bool = False,
        transaction_count: Optional[int] = None,
    ) -> str:
        """

        :param contract: The Contract on which the analysis should be done
        :param enable_physics: If true then enables the graph physics simulation
        :param phrackify: If true generates Phrack-style call graph
        :param transaction_count: The amount of transactions to be executed
        :return: The generated graph in html format
        """
        sym = SymExecWrapper(
            contract or self.contracts[0],
            self.address,
            self.strategy,
            dynloader=DynLoader(
                self.eth,
                storage_loading=self.onchain_storage_access,
                contract_loading=self.dynld,
            ),
            max_depth=self.max_depth,
            execution_timeout=self.execution_timeout,
            transaction_count=transaction_count,
            create_timeout=self.create_timeout,
            enable_iprof=self.enable_iprof,
            disable_dependency_pruning=self.disable_dependency_pruning,
            run_analysis_modules=False,
        )
        return generate_graph(sym, physics=enable_physics, phrackify=phrackify)
Example #17
0
    def runTest(self):

        code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029"

        contract = ETHContract(code)
        sym = SymExecWrapper(contract, "0xd0a6E6C543bC68Db5db3A191B171A77407Ff7ccf")

        html = generate_graph(sym)

        self.assertTrue("0 PUSH1 0x60\\n2 PUSH1 0x40\\n4 MSTORE\\n5 JUMPDEST" in html)
def test_sym_exec():
    contract = SolidityContract(
        str(tests.TESTDATA_INPUTS_CONTRACTS / 'calls.sol'))

    sym = SymExecWrapper(contract,
                         address=(util.get_indexed_address(0)),
                         strategy="dfs")
    issues = fire_lasers(sym)

    assert len(issues) != 0
Example #19
0
    def dump_statespaces(self, contracts=None, address=None, max_depth=12):
        statespaces = []

        for contract in (contracts or self.contracts):
            sym = SymExecWrapper(contract, address,
                                 dynloader=DynLoader(self.eth) if self.dynld else None,
                                 max_depth=max_depth)
            statespaces.append((contract, get_serializable_statespace(sym)))

        return statespaces
Example #20
0
def _generate_report(input_file):
    contract = ETHContract(input_file.read_text())
    sym = SymExecWrapper(contract, address=(util.get_indexed_address(0)))
    issues = fire_lasers(sym)

    report = Report()
    for issue in issues:
        issue.filename = "test-filename.sol"
        report.append_issue(issue)
    return report, input_file
Example #21
0
def _generate_report(input_file):
    contract = SolidityContract(str(input_file), name=None, solc_args=None)
    sym = SymExecWrapper(contract, address=(util.get_indexed_address(0)))
    issues = fire_lasers(sym)

    report = Report()
    for issue in issues:
        issue.add_code_info(contract)
        report.append_issue(issue)

    return report
Example #22
0
 def graph_html(self,
                contract,
                address,
                max_depth=12,
                enable_physics=False,
                phrackify=False):
     sym = SymExecWrapper(
         contract,
         address,
         dynloader=DynLoader(self.eth) if self.dynld else None,
         max_depth=max_depth)
     return generate_graph(sym, physics=enable_physics, phrackify=phrackify)
def test_sym_exec():
    contract = SolidityContract(
        str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"),
        solc_binary=Mythril._init_solc_binary("0.5.0"),
    )

    sym = SymExecWrapper(contract,
                         address=(util.get_indexed_address(0)),
                         strategy="dfs")
    issues = fire_lasers(sym)

    assert len(issues) != 0
Example #24
0
def _generate_report(input_file):
    contract = ETHContract(input_file.read_text(), enable_online_lookup=False)
    sym = SymExecWrapper(
        contract,
        address=(util.get_indexed_address(0)),
        strategy="dfs",
        execution_timeout=30,
    )
    issues = fire_lasers(sym)

    report = Report()
    for issue in issues:
        issue.filename = "test-filename.sol"
        report.append_issue(issue)
    return report, input_file
Example #25
0
def _generate_report(input_file):
    contract = EVMContract(input_file.read_text(), enable_online_lookup=False)
    sym = SymExecWrapper(
        contract,
        address=0xAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFE,
        strategy="dfs",
        execution_timeout=30,
        transaction_count=1,
    )
    issues = fire_lasers(sym)

    report = Report(contracts=[contract])
    for issue in issues:
        issue.filename = "test-filename.sol"
        report.append_issue(issue)
    return report, input_file
Example #26
0
 def graph_html(self,
                strategy,
                contract,
                address,
                max_depth=None,
                enable_physics=False,
                phrackify=False,
                execution_timeout=None,
                create_timeout=None):
     sym = SymExecWrapper(
         contract,
         address,
         strategy,
         dynloader=DynLoader(self.eth) if self.dynld else None,
         max_depth=max_depth,
         execution_timeout=execution_timeout,
         create_timeout=create_timeout)
     return generate_graph(sym, physics=enable_physics, phrackify=phrackify)
Example #27
0
    def dump_statespace(self,
                        strategy,
                        contract,
                        address=None,
                        max_depth=None,
                        execution_timeout=None,
                        create_timeout=None):

        sym = SymExecWrapper(
            contract,
            address,
            strategy,
            dynloader=DynLoader(self.eth) if self.dynld else None,
            max_depth=max_depth,
            execution_timeout=execution_timeout,
            create_timeout=create_timeout)

        return get_serializable_statespace(sym)
Example #28
0
    def fire_lasers(
        self,
        strategy,
        contracts=None,
        address=None,
        modules=None,
        verbose_report=False,
        max_depth=None,
        execution_timeout=None,
        create_timeout=None,
        max_transaction_count=None,
    ):

        all_issues = []
        for contract in contracts or self.contracts:
            sym = SymExecWrapper(
                contract,
                address,
                strategy,
                dynloader=DynLoader(
                    self.eth,
                    storage_loading=self.onchain_storage_access,
                    contract_loading=self.dynld,
                ),
                max_depth=max_depth,
                execution_timeout=execution_timeout,
                create_timeout=create_timeout,
                max_transaction_count=max_transaction_count,
            )

            issues = fire_lasers(sym, modules)

            if type(contract) == SolidityContract:
                for issue in issues:
                    issue.add_code_info(contract)

            all_issues += issues

        # Finally, output the results
        report = Report(verbose_report)
        for issue in all_issues:
            report.append_issue(issue)

        return report
Example #29
0
    def test_generate_graph(self):
        for input_file in TESTDATA_INPUTS.iterdir():
            output_expected = TESTDATA_OUTPUTS_EXPECTED / (input_file.name +
                                                           ".graph.html")
            output_current = TESTDATA_OUTPUTS_CURRENT / (input_file.name +
                                                         ".graph.html")

            contract = SolidityContract(str(input_file),
                                        name=None,
                                        solc_args=None)
            sym = SymExecWrapper(contract,
                                 address=(util.get_indexed_address(0)))

            html = generate_graph(sym)
            output_current.write_text(html)

            if not (output_expected.read_text() == output_current.read_text()):
                self.found_changed_files(input_file, output_expected,
                                         output_current)

        self.assert_and_show_changed_files()
Example #30
0
    def dump_statespace(
        self,
        strategy,
        contract,
        address=None,
        max_depth=None,
        execution_timeout=None,
        create_timeout=None,
        enable_iprof=False,
    ):
        """

        :param strategy:
        :param contract:
        :param address:
        :param max_depth:
        :param execution_timeout:
        :param create_timeout:
        :return:
        """
        sym = SymExecWrapper(
            contract,
            address,
            strategy,
            dynloader=DynLoader(
                self.eth,
                storage_loading=self.onchain_storage_access,
                contract_loading=self.dynld,
            ),
            max_depth=max_depth,
            execution_timeout=execution_timeout,
            create_timeout=create_timeout,
            enable_iprof=enable_iprof,
        )

        return get_serializable_statespace(sym)