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/disassembler/disassembly.py

92 lines
2.6 KiB

from mythril.ether import asm,evm,util
from mythril.rpc.client import EthJsonRpc
from ethereum import utils
import binascii
import sys
import os
import json
class Block:
def __init__(self, code_index, start_addr, funcname):
self.code_index = code_index
self.funcname = funcname
self.xrefs = []
def update_length(self, num_instructions):
self.length = num_instructions
class Disassembly:
def __init__(self, code):
self.instruction_list = asm.disassemble(util.safe_decode(code))
self.blocks = []
self.func_to_addr = {}
self.addr_to_func = []
# Parse jump table & resolve function names
script_dir = os.path.dirname(os.path.realpath(__file__))
signature_file = os.path.join(script_dir, 'signatures.json')
with open(signature_file) as f:
signatures = json.load(f)
jmptable_indices = asm.find_opcode_sequence(["PUSH4", "EQ"], self.instruction_list)
for i in jmptable_indices:
func_hash = self.instruction_list[i]['argument']
try:
func_name = signatures[func_hash]
except KeyError:
func_name = "UNK_" + func_hash
try:
offset = self.instruction_list[i+2]['argument']
jump_target = self.instruction_list[i]['address'] + int(offset, 16)
self.func_to_addr[func_name] = jump_target
self.addr_to_func[jump_target] = func_name
except:
continue
# Parse instructions into basic blocks
current_block = Block(0, 0, "prologue")
index = 0
blocklen = 0
for instruction in self.instruction_list:
blocklen += 1
if (instruction['opcode'] == "JUMPDEST"):
try:
func_name = self.addr_to_func[instruction['address']]
except IndexError:
func_name = "UNKNOWN_JUMPDEST"
current_block.update_length(blocklen)
self.blocks.append(current_block)
current_block = Block(index, instruction['address'], func_name)
blocklen = 0
index += 1
def get_easm(self):
easm = ""
for block in self.blocks:
easm += str(self.instruction_list[block.code_index]['address']) + " --- " + block.funcname + "---\n"
easm += asm.instruction_list_to_easm(self.instruction_list[block.code_index + 1:block.code_index + block.length])
return easm