From 851283bc5c104bc92d5146747fc7cc2f61f08719 Mon Sep 17 00:00:00 2001 From: Bernhard Mueller Date: Fri, 23 Mar 2018 14:11:01 +0700 Subject: [PATCH] Intialize disassembly in ETHCContract init method --- mythril/analysis/modules/external_calls.py | 4 +++- mythril/analysis/symbolic.py | 2 +- mythril/ether/ethcontract.py | 7 ++----- mythril/ether/soliditycontract.py | 2 +- mythril/support/loader.py | 7 ++++--- requirements.txt | 2 +- setup.py | 4 ++-- tests/ethcontract_test.py | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/mythril/analysis/modules/external_calls.py b/mythril/analysis/modules/external_calls.py index 46c4c6d7..0eb5e2e0 100644 --- a/mythril/analysis/modules/external_calls.py +++ b/mythril/analysis/modules/external_calls.py @@ -51,7 +51,7 @@ def execute(statespace): if (call.type == "CALL"): - logging.debug("[EXTERNAL_CALLS] Call to: " + str(call.to) + ", value " + str(call.value) + ", gas = " + str(call.gas)) + logging.info("[EXTERNAL_CALLS] Call to: " + str(call.to) + ", value " + str(call.value) + ", gas = " + str(call.gas)) if (call.to.type == VarType.SYMBOLIC and (call.gas.type == VarType.CONCRETE and call.gas.val > 2300) or (call.gas.type == VarType.SYMBOLIC and "2300" not in str(call.gas))): @@ -103,6 +103,8 @@ def execute(statespace): state_change_addresses = search_children(statespace, call.node, call.state_index + 1) + logging.info("Detected state changes at: " + str(state_change_addresses)) + if (len(state_change_addresses)): for address in state_change_addresses: description = "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities." diff --git a/mythril/analysis/symbolic.py b/mythril/analysis/symbolic.py index fc32d83a..02894254 100644 --- a/mythril/analysis/symbolic.py +++ b/mythril/analysis/symbolic.py @@ -13,7 +13,7 @@ class SymExecWrapper: def __init__(self, contract, address, dynloader=None, max_depth=12): - account = svm.Account(address, contract.get_disassembly(), contract_name=contract.name) + account = svm.Account(address, contract.disassembly, contract_name=contract.name) self.accounts = {address: account} diff --git a/mythril/ether/ethcontract.py b/mythril/ether/ethcontract.py index e892fe7c..bc5f5071 100644 --- a/mythril/ether/ethcontract.py +++ b/mythril/ether/ethcontract.py @@ -17,6 +17,7 @@ class ETHContract(persistent.Persistent): code = re.sub(r'(_+[A-Za-z0-9]+_+)', 'aa' * 20, code) self.code = code + self.disassembly = Disassembly(self.code) def as_dict(self): @@ -25,7 +26,7 @@ class ETHContract(persistent.Persistent): 'name': self.name, 'code': self.code, 'creation_code': self.creation_code, - 'disassembly': self.get_disassembly() + 'disassembly': self.disassembly } def get_xrefs(self): @@ -45,10 +46,6 @@ class ETHContract(persistent.Persistent): return xrefs - def get_disassembly(self): - - return Disassembly(self.code) - def get_easm(self): return Disassembly(self.code).get_easm() diff --git a/mythril/ether/soliditycontract.py b/mythril/ether/soliditycontract.py index 180f875a..d0e5c56e 100644 --- a/mythril/ether/soliditycontract.py +++ b/mythril/ether/soliditycontract.py @@ -94,7 +94,7 @@ class SolidityContract(ETHContract): def get_source_info(self, address): - index = helper.get_instruction_index(self.get_disassembly().instruction_list, address) + index = helper.get_instruction_index(self.disassembly.instruction_list, address) solidity_file = self.solidity_files[self.mappings[index].solidity_file_idx] diff --git a/mythril/support/loader.py b/mythril/support/loader.py index 6bab3a61..6559b840 100644 --- a/mythril/support/loader.py +++ b/mythril/support/loader.py @@ -1,4 +1,5 @@ from mythril.ether.ethcontract import ETHContract +from mythril.disassembler.disassembly import Disassembly import logging import re @@ -34,7 +35,7 @@ class DynLoader: def dynld(self, contract_address, dependency_address): - logging.info("Dynld at contract " + contract_address + ": " + dependency_address) + logging.info("Dynld at contract " + contract_address + ": " + dependency_address) m = re.match(r'^(0x[0-9a-fA-F]{40})$', dependency_address) @@ -44,11 +45,11 @@ class DynLoader: else: return None - logging.info("Dependency address: " + dependency_address) + logging.info("Dependency address: " + dependency_address) code = self.eth.eth_getCode(dependency_address) if (code == "0x"): return None else: - return ETHContract(self.eth.eth_getCode(dependency_address)).get_disassembly() + return Disassembly(code) diff --git a/requirements.txt b/requirements.txt index f89d260a..17bc764e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ ethereum>=2.0.4 ZODB>=5.3.0 z3-solver>=4.5 -laser-ethereum==0.5.15 +laser-ethereum==0.5.16 requests BTrees py-solc diff --git a/setup.py b/setup.py index 9fb82901..b357d99a 100755 --- a/setup.py +++ b/setup.py @@ -254,7 +254,7 @@ Credit setup( name='mythril', - version='0.14.4', + version='0.14.5', description='Security analysis tool for Ethereum smart contracts', long_description=long_description, @@ -290,7 +290,7 @@ setup( 'ethereum>=2.0.4', 'ZODB>=5.3.0', 'z3-solver>=4.5', - 'laser-ethereum==0.5.15', + 'laser-ethereum==0.5.16', 'requests', 'BTrees', 'py-solc' diff --git a/tests/ethcontract_test.py b/tests/ethcontract_test.py index 27d7f440..2ab0950f 100644 --- a/tests/ethcontract_test.py +++ b/tests/ethcontract_test.py @@ -14,7 +14,7 @@ class Getinstruction_listTestCase(ETHContractTestCase): contract = ETHContract(self.code, self.creation_code) - disassembly = contract.get_disassembly() + disassembly = contract.disassembly self.assertEqual(len(disassembly.instruction_list), 53, 'Error disassembling code using ETHContract.get_instruction_list()')