|
|
@ -13,6 +13,7 @@ from mythril.rpc.client import EthJsonRpc |
|
|
|
from mythril.ipc.client import EthIpc |
|
|
|
from mythril.ipc.client import EthIpc |
|
|
|
from ethereum import utils |
|
|
|
from ethereum import utils |
|
|
|
from laser.ethereum import laserfree |
|
|
|
from laser.ethereum import laserfree |
|
|
|
|
|
|
|
from pathlib import Path |
|
|
|
import logging |
|
|
|
import logging |
|
|
|
import sys |
|
|
|
import sys |
|
|
|
import argparse |
|
|
|
import argparse |
|
|
@ -33,21 +34,22 @@ def exitWithError(message): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description='Bug hunting on the Ethereum blockchain') |
|
|
|
parser = argparse.ArgumentParser(description='Bug hunting on the Ethereum blockchain') |
|
|
|
|
|
|
|
parser.add_argument("solidity_file", nargs='*') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commands = parser.add_argument_group('commands') |
|
|
|
commands = parser.add_argument_group('commands') |
|
|
|
commands.add_argument('-d', '--disassemble', action='store_true', help='disassemble') |
|
|
|
commands.add_argument('-d', '--disassemble', action='store_true', help='disassemble') |
|
|
|
commands.add_argument('-g', '--graph', help='generate a control flow graph', metavar='OUTPUT_FILE') |
|
|
|
commands.add_argument('-g', '--graph', help='generate a control flow graph', metavar='OUTPUT_FILE') |
|
|
|
commands.add_argument('-x', '--fire-lasers', action='store_true', help='detect vulnerabilities') |
|
|
|
commands.add_argument('-x', '--fire-lasers', action='store_true', help='detect vulnerabilities') |
|
|
|
commands.add_argument('-t', '--trace', action='store_true', help='trace, use with -c or -a and --data (optional)') |
|
|
|
commands.add_argument('-t', '--trace', action='store_true', help='trace contract, use with --data (optional)') |
|
|
|
commands.add_argument('-s', '--search', help='search the contract database') |
|
|
|
commands.add_argument('-s', '--search', help='search the contract database', metavar='EXPRESSION') |
|
|
|
commands.add_argument('--xrefs', action='store_true', help='get xrefs from a contract, use with -c or -a') |
|
|
|
commands.add_argument('--xrefs', action='store_true', help='get xrefs from a contract') |
|
|
|
commands.add_argument('--hash', help='calculate function signature hash', metavar='SIGNATURE') |
|
|
|
commands.add_argument('--hash', help='calculate function signature hash', metavar='SIGNATURE') |
|
|
|
commands.add_argument('--init-db', action='store_true', help='initialize the contract database') |
|
|
|
commands.add_argument('--init-db', action='store_true', help='initialize the contract database') |
|
|
|
|
|
|
|
|
|
|
|
inputs = parser.add_argument_group('input arguments') |
|
|
|
inputs = parser.add_argument_group('input arguments') |
|
|
|
inputs.add_argument('-c', '--code', help='hex-encoded bytecode string ("6060604052...")', metavar='BYTECODE') |
|
|
|
inputs.add_argument('-c', '--code', help='hex-encoded bytecode string ("6060604052...")', metavar='BYTECODE') |
|
|
|
inputs.add_argument('-i', '--infiles', help='comma-separated list of solidity files', metavar='INPUT_FILES') |
|
|
|
inputs.add_argument('-a', '--address', help='pull contract from the blockchain', metavar='CONTRACT_ADDRESS') |
|
|
|
inputs.add_argument('-a', '--address', help='pull contract from the mainnet', metavar='CONTRACT_ADDRESS') |
|
|
|
|
|
|
|
inputs.add_argument('--data', help='message call input data for tracing') |
|
|
|
inputs.add_argument('--data', help='message call input data for tracing') |
|
|
|
|
|
|
|
|
|
|
|
options = parser.add_argument_group('options') |
|
|
|
options = parser.add_argument_group('options') |
|
|
@ -105,7 +107,7 @@ if args.search or args.init_db: |
|
|
|
|
|
|
|
|
|
|
|
# Establish RPC/IPC connection if necessary |
|
|
|
# Establish RPC/IPC connection if necessary |
|
|
|
|
|
|
|
|
|
|
|
if (args.address or args.infiles): |
|
|
|
if (args.address or len(args.solidity_file)): |
|
|
|
if args.ipc: |
|
|
|
if args.ipc: |
|
|
|
try: |
|
|
|
try: |
|
|
|
eth = EthIpc() |
|
|
|
eth = EthIpc() |
|
|
@ -127,13 +129,12 @@ if (args.code): |
|
|
|
contracts.append(ETHContract(args.code, address = util.get_random_address())) |
|
|
|
contracts.append(ETHContract(args.code, address = util.get_random_address())) |
|
|
|
elif (args.address): |
|
|
|
elif (args.address): |
|
|
|
contracts.append(ETHContract(eth.eth_getCode(args.address), address = args.address)) |
|
|
|
contracts.append(ETHContract(eth.eth_getCode(args.address), address = args.address)) |
|
|
|
elif (args.infiles): |
|
|
|
elif (len(args.solidity_file)): |
|
|
|
files = args.infiles.split(",") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
counter = 0 |
|
|
|
counter = 0 |
|
|
|
|
|
|
|
|
|
|
|
for file in files: |
|
|
|
for file in args.solidity_file: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
file = file.replace("~", str(Path.home())) # Expand user path |
|
|
|
name, bytecode = compile_solidity(solc_binary, file) |
|
|
|
name, bytecode = compile_solidity(solc_binary, file) |
|
|
|
|
|
|
|
|
|
|
|
# Max. 16 contracts supported |
|
|
|
# Max. 16 contracts supported |
|
|
|