Ejemplo n.º 1
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
Ejemplo n.º 2
0
    def __init__(self, contracts=None, exceptions=None):
        """

        :param contracts:
        :param exceptions:
        """
        self.issues = {}
        self.solc_version = ""
        self.meta = {}
        self.source = Source()
        self.source.get_source_from_contracts_list(contracts)
        self.exceptions = exceptions or []
Ejemplo n.º 3
0
    def __init__(self, verbose=False, contracts=None, exceptions=None):
        """

        :param verbose:
        """
        self.issues = {}
        self.verbose = verbose
        self.solc_version = ""
        self.meta = {}
        self.source = Source()
        self.source.get_source_from_contracts_list(contracts)
        self.exceptions = exceptions or []
Ejemplo n.º 4
0
    def __init__(self, verbose=False, source=None):
        """

        :param verbose:
        """
        self.issues = {}
        self.verbose = verbose
        self.solc_version = ""
        self.meta = {}
        self.source = source or Source()
Ejemplo n.º 5
0
    def fire_lasers(
        self,
        strategy,
        contracts=None,
        address=None,
        modules=None,
        verbose_report=False,
        max_depth=None,
        execution_timeout=None,
        create_timeout=None,
        transaction_count=None,
        enable_iprof=False,
    ):
        """

        :param strategy:
        :param contracts:
        :param address:
        :param modules:
        :param verbose_report:
        :param max_depth:
        :param execution_timeout:
        :param create_timeout:
        :param transaction_count:
        :return:
        """
        all_issues = []
        for contract in contracts or self.contracts:
            try:
                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,
                    modules=modules,
                    compulsory_statespace=False,
                    enable_iprof=enable_iprof,
                )
                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)

            for issue in issues:
                issue.add_code_info(contract)

            all_issues += issues

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

        return report
Ejemplo n.º 6
0
class Report:
    """A report containing the content of multiple issues."""

    environment = Environment(loader=PackageLoader("mythril.analysis"),
                              trim_blocks=True)

    def __init__(self, contracts=None, exceptions=None):
        """

        :param contracts:
        :param exceptions:
        """
        self.issues = {}
        self.solc_version = ""
        self.meta = {}
        self.source = Source()
        self.source.get_source_from_contracts_list(contracts)
        self.exceptions = exceptions or []

    def sorted_issues(self):
        """

        :return:
        """
        issue_list = [issue.as_dict for key, issue in self.issues.items()]
        return sorted(issue_list, key=operator.itemgetter("address", "title"))

    def append_issue(self, issue):
        """

        :param issue:
        """
        m = hashlib.md5()
        m.update((issue.contract + str(issue.address) +
                  issue.title).encode("utf-8"))
        issue.resolve_function_names()
        self.issues[m.digest()] = issue

    def as_text(self):
        """

        :return:
        """
        name = self._file_name()
        template = Report.environment.get_template("report_as_text.jinja2")

        return template.render(filename=name, issues=self.sorted_issues())

    def as_json(self):
        """

        :return:
        """
        result = {
            "success": True,
            "error": None,
            "issues": self.sorted_issues()
        }
        return json.dumps(result, sort_keys=True)

    def _get_exception_data(self) -> dict:
        if not self.exceptions:
            return {}
        logs = []  # type: List[Dict]
        for exception in self.exceptions:
            logs += [{"level": "error", "hidden": "true", "msg": exception}]
        return {"logs": logs}

    def as_swc_standard_format(self):
        """Format defined for integration and correlation.

        :return:
        """
        _issues = []

        for key, issue in self.issues.items():

            idx = self.source.get_source_index(issue.bytecode_hash)
            try:
                title = SWC_TO_TITLE[issue.swc_id]
            except KeyError:
                title = "Unspecified Security Issue"
            extra = {"discoveryTime": int(issue.discovery_time * 10**9)}
            if issue.transaction_sequence_jsonv2:
                extra["testCases"] = [issue.transaction_sequence_jsonv2]

            _issues.append({
                "swcID":
                "SWC-" + issue.swc_id,
                "swcTitle":
                title,
                "description": {
                    "head": issue.description_head,
                    "tail": issue.description_tail,
                },
                "severity":
                issue.severity,
                "locations": [{
                    "sourceMap": "%d:1:%d" % (issue.address, idx)
                }],
                "extra":
                extra,
            })
        meta_data = self._get_exception_data()
        result = [{
            "issues": _issues,
            "sourceType": self.source.source_type,
            "sourceFormat": self.source.source_format,
            "sourceList": self.source.source_list,
            "meta": meta_data,
        }]

        return json.dumps(result, sort_keys=True)

    def as_markdown(self):
        """

        :return:
        """
        filename = self._file_name()
        template = Report.environment.get_template("report_as_markdown.jinja2")
        return template.render(filename=filename, issues=self.sorted_issues())

    def _file_name(self):
        """

        :return:
        """
        if len(self.issues.values()) > 0:
            return list(self.issues.values())[0].filename