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)
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
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
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