Security analysis tool for EVM bytecode. Supports smart contracts built for Ethereum, Hedera, Quorum, Vechain, Roostock, Tron and other EVM-compatible blockchains.
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.
mythril/examples/discover_writes.py

92 lines
3.1 KiB

7 years ago
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.
7 years ago
# Needs testrpc running on port 8546
7 years ago
# testrpc --port 8546 --gasLimit 0xFFFFFF --account 0x0b6f3fd29ca0e570faf9d0bb8945858b9c337cd2a2ff89d65013eec412a4a811,500000000000000000000 --account 0x2194ac1cd3b9ca6cccc1a90aa2c6f944994b80bb50c82b973adce7f288734d5c,500000000000000000000
7 years ago
7 years ago
addr_knupper= "0xe2beffc4bc7ebb9eae43d59d2b555749d9ce7c54"
addr_schnupper = "0xadc2f8617191ff60a36c3c136170cc69c03e64cd"
7 years ago
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):
7 years ago
7 years ago
if re.match(r'^UNK_0x', function_selector):
7 years ago
args = encode_abi(['address'], [addr_schnupper])
7 years ago
data= function_selector[4:] + args.hex()
7 years ago
else:
data = util.encode_calldata(function_selector, arg_types, args)
7 years ago
tx = testrpc.eth_sendTransaction(to_address=contract_addr, from_address=addr_schnupper, gas=5000000, value=0, data=data)
7 years ago
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):
7 years ago
ret = testrpc.eth_sendTransaction(from_address=addr_knupper, gas=5000000, value=0, data=contract.creation_code)
7 years ago
receipt = testrpc.eth_getTransactionReceipt(ret)
contract_addr = receipt['contractAddress']
try:
7 years ago
disas = Disassembly(contract.code)
7 years ago
except:
7 years ago
return
7 years ago
found = False
7 years ago
for function_selector in disas.func_to_addr:
7 years ago
7 years ago
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]))
7 years ago
7 years ago
for i in range(0, len(addresses)):
print("Address: " + addresses[i] + ", balance: " + str(balances[i]))
7 years ago
7 years ago
found = True
7 years ago
break
7 years ago
if found:
break
except:
break
7 years ago
print("Searching " +str(len(list(contract_storage.contracts))) + " contracts...")
contract_storage.search("code#PUSH#", testDynamic) # Returns all contracts