def load_from_bytecode( self, code: str, bin_runtime: bool = False, address: Optional[str] = None) -> Tuple[str, EVMContract]: """ Returns the address and the contract class for the given bytecode :param code: Bytecode :param bin_runtime: Whether the code is runtime code or creation code :param address: address of contract :return: tuple(address, Contract class) """ if address is None: address = util.get_indexed_address(0) if bin_runtime: self.contracts.append( EVMContract( code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup, )) else: self.contracts.append( EVMContract( creation_code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup, )) return address, self.contracts[ -1] # return address and contract object
def load_from_bytecode(self, code, bin_runtime=False, address=None): """ :param code: :param bin_runtime: :param address: :return: """ if address is None: address = util.get_indexed_address(0) if bin_runtime: self.contracts.append( EVMContract( code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup, )) else: self.contracts.append( EVMContract( creation_code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup, )) return address, self.contracts[ -1] # return address and contract object
def runTest(self): contract = EVMContract(self.code) instruction_list = contract.get_easm() self.assertTrue( "PUSH1 0x60" in instruction_list, "Error obtaining EASM code through EVMContract.get_easm()", )
def runTest(self): contract = EVMContract(self.code) self.assertTrue( contract.matches_expression("code#PUSH1# or code#PUSH1#"), "Unexpected result in expression matching", ) self.assertFalse( contract.matches_expression("func#abcdef#"), "Unexpected result in expression matching", )
def load_from_address(self, address: str) -> Tuple[str, EVMContract]: """ Returns the contract given it's on chain address :param address: The on chain address of a contract :return: tuple(address, contract) """ if not re.match(r"0x[a-fA-F0-9]{40}", address): raise CriticalError( "Invalid contract address. Expected format is '0x...'.") try: code = self.eth.eth_getCode(address) except FileNotFoundError as e: raise CriticalError("IPC error: " + str(e)) except ConnectionError: raise CriticalError( "Could not connect to RPC server. Make sure that your node is running and that RPC parameters are set correctly." ) except Exception as e: raise CriticalError("IPC / RPC error: " + str(e)) if code == "0x" or code == "0x0": raise CriticalError( "Received an empty response from eth_getCode. Check the contract address and verify that you are on the correct chain." ) else: self.contracts.append( EVMContract(code, name=address, enable_online_lookup=self.enable_online_lookup)) return address, self.contracts[ -1] # return address and contract object
def AnalyseSherlockJson(fileAddress): startTime = time.time() # pour calculer temps exécution accounts = {} contractAddress = "" contractName = "" firstContract = True with open(fileAddress) as json_file: data = json.load(json_file) #print (data) for p in data['contract']: contract = EVMContract(code=p['contractBytecode'], name=p['contractName']) address = p['contractAddress'] account = svm.Account(address, contract.disassembly) accounts[address] = account if firstContract == True: contractAddress = p['contractAddress'] contractName = p['contractName'] firstContract = False print('contract name: ' + p['contractName']) print('contract address: ' + p['contractAddress']) #print('contract bytecote: ' + p['contractBytecode']) print('') laser = svm.LaserEVM(accounts, max_depth=maxDept, execution_timeout=executionTimeOut, create_timeout=createTimeOut, transaction_count=transactionCount) ExecutionSymbolique(laser, contractAddress, contractName, startTime)
def symbolic_execute(code, address): contract = EVMContract(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
def contract(self) -> EVMContract: try: with open(self._file_path) as contract_bin: bytecode = contract_bin.read() except IOError as e: log.error('Failed to open contract binary file: %s', e) raise IOError('Failed to open contract binary file') return EVMContract(creation_code=bytecode)
def get_contracts(self): """Iterate through all contracts.""" for account in self.reader._get_head_state().get_all_accounts(): if account.code is not None: code = _encode_hex(account.code) contract = EVMContract(code, enable_online_lookup=False) yield contract, account.address, account.balance
def runTest(self): contract = EVMContract(self.code, self.creation_code) disassembly = contract.disassembly self.assertEqual( len(disassembly.instruction_list), 53, "Error disassembling code using EVMContract.get_instruction_list()", )
def runTest(self): code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029" contract = EVMContract(code) sym = SymExecWrapper(contract, "0xd0a6E6C543bC68Db5db3A191B171A77407Ff7ccf") html = generate_graph(sym) self.assertTrue( "0 PUSH1 0x60\\n2 PUSH1 0x40\\n4 MSTORE\\n5 JUMPDEST" in html)
def analyze_truffle_project(sigs, args): """ :param sigs: :param args: """ project_root = os.getcwd() build_dir = os.path.join(project_root, "build", "contracts") files = os.listdir(build_dir) for filename in files: if re.match(r".*\.json$", filename) and filename != "Migrations.json": with open(os.path.join(build_dir, filename)) as cf: contractdata = json.load(cf) try: name = contractdata["contractName"] bytecode = contractdata["deployedBytecode"] filename = PurePath(contractdata["sourcePath"]).name except KeyError: print( "Unable to parse contract data. Please use Truffle 4 to compile your project." ) sys.exit() if len(bytecode) < 4: continue get_sigs_from_truffle(sigs, contractdata) ethcontract = EVMContract(bytecode, name=name) address = util.get_indexed_address(0) sym = SymExecWrapper( ethcontract, address, args.strategy, max_depth=args.max_depth, create_timeout=args.create_timeout, execution_timeout=args.execution_timeout, transaction_count=args.transaction_count, modules=args.modules or [], compulsory_statespace=False, ) issues = fire_lasers(sym) if not len(issues): if args.outform == "text" or args.outform == "markdown": print("# Analysis result for " + name + "\n\nNo issues found.") else: result = { "contract": name, "result": { "success": True, "error": None, "issues": [] }, } print(json.dumps(result)) else: report = Report() # augment with source code deployed_disassembly = ethcontract.disassembly constructor_disassembly = ethcontract.creation_disassembly source = contractdata["source"] deployed_source_map = contractdata["deployedSourceMap"].split( ";") source_map = contractdata["sourceMap"].split(";") deployed_mappings = get_mappings(source, deployed_source_map) constructor_mappings = get_mappings(source, source_map) for issue in issues: if issue.function == "constructor": mappings = constructor_mappings disassembly = constructor_disassembly else: mappings = deployed_mappings disassembly = deployed_disassembly index = get_instruction_index(disassembly.instruction_list, issue.address) if index: try: offset = mappings[index].offset length = mappings[index].length issue.filename = filename issue.code = source.encode("utf-8")[offset:offset + length].decode( "utf-8") issue.lineno = mappings[index].lineno except IndexError: log.debug("No code mapping at index %d", index) report.append_issue(issue) if args.outform == "json": result = { "contract": name, "result": { "success": True, "error": None, "issues": list(map(lambda x: x.as_dict, issues)), }, } print(json.dumps(result)) else: if args.outform == "text": print("# Analysis result for " + name + ":\n\n" + report.as_text()) elif args.outform == "markdown": print(report.as_markdown())