mirror of https://github.com/ConsenSys/mythril
blockchainethereumsmart-contractssoliditysecurityprogram-analysissecurity-analysissymbolic-execution
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
3.1 KiB
91 lines
3.1 KiB
from mythril.ether import util
|
|
from mythril.rpc.client import EthJsonRpc
|
|
from mythril.ether.contractstorage import get_persistent_storage
|
|
from mythril.disassembler.disassembly import Disassembly
|
|
from ethereum.abi import encode_abi
|
|
import re
|
|
import os
|
|
|
|
|
|
# Discover contract functions that write the sender address, or an address passed as an argument, to storage.
|
|
# Needs testrpc running on port 8546
|
|
|
|
# testrpc --port 8546 --gasLimit 0xFFFFFF --account 0x0b6f3fd29ca0e570faf9d0bb8945858b9c337cd2a2ff89d65013eec412a4a811,500000000000000000000 --account 0x2194ac1cd3b9ca6cccc1a90aa2c6f944994b80bb50c82b973adce7f288734d5c,500000000000000000000
|
|
|
|
|
|
addr_knupper= "0xe2beffc4bc7ebb9eae43d59d2b555749d9ce7c54"
|
|
addr_schnupper = "0xadc2f8617191ff60a36c3c136170cc69c03e64cd"
|
|
|
|
contract_storage = get_persistent_storage(os.path.join(os.path.expanduser('~'), ".mythril"))
|
|
testrpc = EthJsonRpc("localhost", 8546)
|
|
|
|
testargs1 = [
|
|
([], []),
|
|
(['address'], [addr_schnupper]),
|
|
(['address', 'uint256'], [addr_schnupper, 1 ]),
|
|
(['address', 'uint256', 'uint256'], [addr_schnupper, 1, 1]),
|
|
(['address[]'], [[addr_schnupper]]),
|
|
(['address[]', 'uint256'], [[addr_schnupper], 1 ]),
|
|
(['address[]', 'uint256', 'uint256'], [[addr_schnupper], 1, 1]),
|
|
]
|
|
|
|
|
|
def testCase(contract_addr, function_selector, arg_types, args):
|
|
|
|
if re.match(r'^UNK_0x', function_selector):
|
|
args = encode_abi(['address'], [addr_schnupper])
|
|
data= function_selector[4:] + args.hex()
|
|
else:
|
|
data = util.encode_calldata(function_selector, arg_types, args)
|
|
|
|
tx = testrpc.eth_sendTransaction(to_address=contract_addr, from_address=addr_schnupper, gas=5000000, value=0, data=data)
|
|
|
|
trace = testrpc.traceTransaction(tx)
|
|
|
|
if trace:
|
|
for t in trace['structLogs']:
|
|
if t['op'] == 'SSTORE':
|
|
if addr_schnupper[2:] in t['stack'][-2]:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def testDynamic(contract_hash, contract, addresses, balances):
|
|
|
|
ret = testrpc.eth_sendTransaction(from_address=addr_knupper, gas=5000000, value=0, data=contract.creation_code)
|
|
receipt = testrpc.eth_getTransactionReceipt(ret)
|
|
contract_addr = receipt['contractAddress']
|
|
|
|
try:
|
|
disas = Disassembly(contract.code)
|
|
except:
|
|
return
|
|
|
|
found = False
|
|
|
|
for function_selector in disas.func_to_addr:
|
|
|
|
try:
|
|
for t in testargs1:
|
|
if(testCase(contract_addr, function_selector, t[0], t[1])):
|
|
print("Possible write!")
|
|
print("Contract hash: " + contract_hash)
|
|
print("Selector: " + function_selector)
|
|
print("Input data: " + str(t[1]))
|
|
|
|
for i in range(0, len(addresses)):
|
|
print("Address: " + addresses[i] + ", balance: " + str(balances[i]))
|
|
|
|
found = True
|
|
break
|
|
|
|
if found:
|
|
break
|
|
except:
|
|
break
|
|
|
|
|
|
print("Searching " +str(len(list(contract_storage.contracts))) + " contracts...")
|
|
|
|
contract_storage.search("code#PUSH#", testDynamic) # Returns all contracts
|
|
|