Esempio n. 1
0
    def _run_mythril(self, contract_address=None):
        eth_json_rpc = EthJsonRpc(url=self.web3_rpc)

        disassembler = MythrilDisassembler(eth=eth_json_rpc,
                                           solc_version=None,
                                           enable_online_lookup=True)

        disassembler.load_from_address(contract_address)

        analyzer = MythrilAnalyzer(
            strategy="bfs",
            use_onchain_data=self.onchain_storage,
            disassembler=disassembler,
            address=contract_address,
            execution_timeout=self.timeout,
            solver_timeout=self.timeout,
            loop_bound=self.loop_bound,
            max_depth=64,
            create_timeout=10,
        )

        self.logger.info("Analyzing %s", contract_address)
        self.logger.debug("Running Mythril")

        return analyzer.fire_lasers(modules=self.modules,
                                    transaction_count=self.tx_count)
Esempio n. 2
0
def get_code(disassembler: MythrilDisassembler, args: argparse.Namespace):
    address = None
    if args.code:
        # Load from bytecode
        code = args.code[2:] if args.code.startswith("0x") else args.code
        address, _ = disassembler.load_from_bytecode(code, args.bin_runtime)
    elif args.codefile:
        bytecode = "".join([l.strip() for l in args.codefile if len(l.strip()) > 0])
        bytecode = bytecode[2:] if bytecode.startswith("0x") else bytecode
        address, _ = disassembler.load_from_bytecode(bytecode, args.bin_runtime)
    elif args.address:
        # Get bytecode from a contract address
        address, _ = disassembler.load_from_address(args.address)
    elif args.solidity_file:
        # Compile Solidity source file(s)
        if args.graph and len(args.solidity_file) > 1:
            exit_with_error(
                args.outform,
                "Cannot generate call graphs from multiple input files. Please do it one at a time.",
            )
        address, _ = disassembler.load_from_solidity(
            args.solidity_file
        )  # list of files
    else:
        exit_with_error(
            args.outform,
            "No input bytecode. Please provide EVM code via -c BYTECODE, -a ADDRESS, or -i SOLIDITY_FILES",
        )
    return address
Esempio n. 3
0
def load_code(disassembler: MythrilDisassembler, args: Namespace):
    """
    Loads code into disassembly and returns address
    :param disassembler:
    :param args:
    :return: Address
    """

    address = None
    if args.__dict__.get("code", False):
        # Load from bytecode
        code = args.code[2:] if args.code.startswith("0x") else args.code
        address, _ = disassembler.load_from_bytecode(code, args.bin_runtime)
    elif args.__dict__.get("codefile", False):
        bytecode = "".join(
            [l.strip() for l in args.codefile if len(l.strip()) > 0])
        bytecode = bytecode[2:] if bytecode.startswith("0x") else bytecode
        address, _ = disassembler.load_from_bytecode(bytecode,
                                                     args.bin_runtime)
    elif args.__dict__.get("address", False):
        # Get bytecode from a contract address
        address, _ = disassembler.load_from_address(args.address)
    elif args.__dict__.get("solidity_file", False):
        # Compile Solidity source file(s)
        if args.command in ANALYZE_LIST and args.graph and len(
                args.solidity_file) > 1:
            exit_with_error(
                args.outform,
                "Cannot generate call graphs from multiple input files. Please do it one at a time.",
            )
        address, _ = disassembler.load_from_solidity(
            args.solidity_file)  # list of files
    else:
        exit_with_error(
            args.__dict__.get("outform", "text"),
            "No input bytecode. Please provide EVM code via -c BYTECODE, -a ADDRESS, -f BYTECODE_FILE or <SOLIDITY_FILE>",
        )
    return address
Esempio n. 4
0
def exploits_from_mythril(
    rpcHTTP="http://localhost:8545",
    rpcWS=None,
    rpcIPC=None,
    timeout=300,
    contract="",
    account_pk="",
    strategy="bfs",
    modules=["ether_thief", "suicide"],
    transaction_count=3,
    execution_timeout=120,
    max_depth=32,
    loop_bound=3,
    disable_dependency_pruning=False,
    onchain_storage_access=True,
    enable_online_lookup=False,
):
    if re.match(r"^https", rpcHTTP):
        host, port = rpcHTTP[8:].split(":")
        rpc_tls = True
    else:
        host, port = rpcHTTP[7:].split(":")
        rpc_tls = False

    try:
        # Disassembler
        disassembler = MythrilDisassembler(
            eth=EthJsonRpc(host=host, port=port, tls=rpc_tls),
            solc_version=None,
            solc_args=None,
            enable_online_lookup=enable_online_lookup,
        )
        disassembler.load_from_address(contract)
        # Analyzer
        analyzer = MythrilAnalyzer(
            strategy=strategy,
            disassembler=disassembler,
            address=contract,
            execution_timeout=execution_timeout,
            max_depth=max_depth,
            loop_bound=loop_bound,
            disable_dependency_pruning=disable_dependency_pruning,
            onchain_storage_access=onchain_storage_access,
        )
        # Generate report
        report = analyzer.fire_lasers(
            modules=modules, transaction_count=transaction_count
        )
    except CriticalError as e:
        print(e)
        return []

    if rpcIPC is not None:
        print("Connecting to IPC: {rpc}.".format(rpc=rpcIPC))
        w3 = Web3(Web3.IPCProvider(rpcIPC, timeout=timeout))
    elif rpcWS is not None:
        print("Connecting to WebSocket: {rpc}.".format(rpc=rpcWS))
        w3 = Web3(Web3.WebsocketProvider(rpcWS, websocket_kwargs={"timeout": timeout}))
    else:
        print("Connecting to HTTP: {rpc}.".format(rpc=rpcHTTP))
        w3 = Web3(Web3.HTTPProvider(rpcHTTP, request_kwargs={"timeout": timeout}))

    exploits = []

    for ri in report.issues:
        txs = []
        issue = report.issues[ri]

        for si in issue.transaction_sequence["steps"]:
            txs.append(Tx(data=si["input"], value=si["value"], name=si["name"]))

        exploits.append(
            Exploit(
                txs=txs,
                w3=w3,
                contract=contract,
                account=private_key_to_account(account_pk),
                account_pk=account_pk,
                title=issue.title,
                description=issue.description,
                swc_id=issue.swc_id,
            )
        )

    return exploits