Skip to content

Commit 5aa8818

Browse files
committed
fix simplify
1 parent 69c41bc commit 5aa8818

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

ethereum_dasm/evmdasm.py

+24-7
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class Contract(object):
5858
Main Input Class
5959
"""
6060

61-
def __init__(self, bytecode=None, address=None, static_analysis=True, dynamic_analysis=True, network="mainnet"):
61+
def __init__(self, bytecode=None, address=None, static_analysis=True, dynamic_analysis=True, network="mainnet", simplify_show_unreachable=False, simplify_show_asm=False):
6262
if not bytecode and not address:
6363
raise Exception("missing bytecode or contract address")
6464

@@ -70,6 +70,8 @@ def __init__(self, bytecode=None, address=None, static_analysis=True, dynamic_an
7070
self.bytecode, self.auxdata = Contract.get_auxdata(bytecode)
7171
self._evmcode = EvmCode(contract=self,
7272
static_analysis=static_analysis, dynamic_analysis=dynamic_analysis) # do not reference this directly, always use self.disassembly()
73+
74+
self._simplify_show_unreachable, self._simplify_show_asm = simplify_show_unreachable, simplify_show_asm
7375

7476
@property
7577
def disassembly(self):
@@ -79,7 +81,10 @@ def disassembly(self):
7981

8082
@property
8183
def simplified(self):
82-
return evmsimplify.simplify(self.disassembly)
84+
return evmsimplify.simplify(self.disassembly,
85+
show_pseudocode=True,
86+
show_asm=self._simplify_show_asm,
87+
show_unreachable=self._simplify_show_unreachable)
8388

8489
@property
8590
def methods(self):
@@ -530,7 +535,8 @@ def analyze_dynamic(self):
530535
for addr, instr in self.jumptable.items(): # all JUMP/I s
531536
# get symbolic stack
532537
for node, state in self.symbolic_state_at.get(addr,[]): # todo investigate keyerror
533-
dst = z3.simplify(state.mstate.stack[-1]).as_long() if z3.is_expr(state.mstate.stack[-1]) else state.mstate.stack[-1]
538+
dst = get_z3_value(state.mstate.stack[-1])
539+
#dst = z3.simplify().as_long() if z3.is_expr(state.mstate.stack[-1]) else get_z3_value(state.mstate.stack[-1])
534540
if instr.jumpto and instr.jumpto != dst: # todo: needs to be a set
535541
logger.warning("Symbolic JUMP destination different: %s != %s" % (instr.jumpto, dst))
536542
instr.jumpto = dst
@@ -588,6 +594,10 @@ def main():
588594
help="disable static analysis")
589595
parser.add_option("-s", "--simplify", dest="simplify", default=False, action="store_true",
590596
help="simplify disassembly to human readable code")
597+
parser.add_option("-x", "--simplify-show-asm", dest="simplify_show_asm", default=False, action="store_true",
598+
help="simplify: show or hide asm annotations in simplified code")
599+
parser.add_option("-y", "--simplify-show-unreachable", dest="simplify_show_unreachable", default=False, action="store_true",
600+
help="simplify: show or hide annotations for unreachable instructions in simplified code")
591601
parser.add_option("-n", "--network", dest="network", default="mainnet",
592602
help="network for address lookup (default: mainnet, ropsten, rinkeby, kovan")
593603

@@ -609,25 +619,32 @@ def main():
609619
if options.function_signature_lookup and not utils.signatures.ethereum_input_decoder:
610620
logger.warning("ethereum_input_decoder package not installed. function signature lookup not available.(pip install ethereum-input-decoder)")
611621

622+
if options.simplify_show_asm or options.simplify_show_unreachable:
623+
options.simplify = True
624+
612625
# get bytecode from stdin, or arg:file or arg:bytcode
613626

614627
if options.address:
615628
contract = Contract(address=options.address,
616629
network=options.network,
617-
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis)
630+
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis,
631+
simplify_show_unreachable=options.simplify_show_unreachable, simplify_show_asm=options.simplify_show_asm)
618632
elif not args:
619633
contract = Contract(bytecode=sys.stdin.read().strip(),
620634
network=options.network,
621-
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis)
635+
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis,
636+
simplify_show_unreachable=options.simplify_show_unreachable, simplify_show_asm=options.simplify_show_asm)
622637
else:
623638
if os.path.isfile(args[0]):
624639
contract = Contract(bytecode=open(args[0], 'r').read(),
625640
network=options.network,
626-
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis)
641+
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis,
642+
simplify_show_unreachable=options.simplify_show_unreachable, simplify_show_asm=options.simplify_show_asm)
627643
else:
628644
contract = Contract(bytecode=args[0],
629645
network=options.network,
630-
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis)
646+
static_analysis=options.static_analysis, dynamic_analysis=options.dynamic_analysis,
647+
simplify_show_unreachable=options.simplify_show_unreachable, simplify_show_asm=options.simplify_show_asm)
631648

632649
#logger.debug(INSTRUCTIONS_BY_OPCODE)
633650

ethereum_dasm/symbolic/simplify.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# Author : <github.com/tintinweb>
44

55
import z3
6+
import logging
7+
import mythril.laser.smt
8+
9+
logger = logging.getLogger(__name__)
610

711
def pp_hexint(a):
812
return z3.z3printer.to_format(get_z3_value_hex(a))
@@ -24,6 +28,8 @@ def get_z3_value_hex(item):
2428
if (type(item) == int):
2529
return hex(item)
2630

31+
elif (type(item) == mythril.laser.smt.bitvec.BitVec and not item.symbolic):
32+
return hex(item.value)
2733
elif (type(item) == z3.BitVecNumRef):
2834
return hex(item.as_long())
2935

@@ -39,6 +45,8 @@ def get_z3_value(item):
3945
if (type(item) == int):
4046
return item
4147

48+
elif (type(item) == mythril.laser.smt.bitvec.BitVec and not item.symbolic):
49+
return item.value
4250
elif (type(item) == z3.BitVecNumRef):
4351
return item.as_long()
4452

@@ -170,7 +178,7 @@ def __str__(self):
170178
(", ".join("%s=%s" % (a, b) for a, b in self.asm.args)))
171179

172180

173-
def simplify(evmcode, show_asm=False, show_pseudocode=True):
181+
def simplify(evmcode, show_asm=False, show_pseudocode=True, show_unreachable=False):
174182
"""
175183
176184
skip:
@@ -198,7 +206,8 @@ def simplify(evmcode, show_asm=False, show_pseudocode=True):
198206
stack=evmcode.symbolic_state_at[instr.address][0][1].mstate.stack if not instr.name in ("JUMPDEST",) else None,
199207
evmcode=evmcode)
200208
except KeyError as ke:
201-
print("\t//Exception @:LOC_%s [!!!!] <-- exception: %r --> %r" % (hex(instr.address), ke, instr))
209+
if show_unreachable:
210+
yield("\t//UnreachableCodeException @:LOC_%s [!!!!] <-- exception: %r --> %r" % (hex(instr.address), ke, instr))
202211
continue
203212

204213
if show_asm and asm_stmt:

0 commit comments

Comments
 (0)