From 02e579df0b9856d257ad56e1691a50eb25858bb2 Mon Sep 17 00:00:00 2001 From: xhyumiracle Date: Sun, 7 Aug 2022 20:12:18 +0800 Subject: [PATCH 1/6] add support for jump(i) trace back when theres no direct push --- evm-cpu.py | 230 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 202 insertions(+), 28 deletions(-) diff --git a/evm-cpu.py b/evm-cpu.py index 92e4694..2115a9b 100755 --- a/evm-cpu.py +++ b/evm-cpu.py @@ -3,7 +3,9 @@ from idc import * from idaapi import * import idautils +# from idadex import ea_t +# from decorators import memoized import known_hashes ''' @@ -11,6 +13,7 @@ ''' class EVMAsm(object): + reverse_table = {} ''' EVM Instruction factory @@ -450,20 +453,36 @@ def is_arithmetic(self): 0xff: ('SELFDESTRUCT', 0, 1, 0, 5000, 'Halt execution and register account for later deletion.') } + # @staticmethod + # # @memoized + # def _get_reverse_table(): + # ''' Build an internal table used in the assembler ''' + # reverse_table = {} + # for (opcode, (name, immediate_operand_size, pops, pushes, gas, description)) in EVMAsm._table.items(): + # mnemonic = name + # if name == 'PUSH': + # mnemonic = '%s%d'%(name, (opcode&0x1f) + 1) + # elif name in ('SWAP', 'LOG', 'DUP'): + # mnemonic = '%s%d'%(name, (opcode&0xf) + 1) + + # reverse_table[mnemonic] = opcode, name, immediate_operand_size, pops, pushes, gas, description + # return reverse_table + @staticmethod - #@memoized + # @memoized def _get_reverse_table(): ''' Build an internal table used in the assembler ''' - reverse_table = {} - for (opcode, (name, immediate_operand_size, pops, pushes, gas, description)) in EVMAsm._table.items(): - mnemonic = name - if name == 'PUSH': - mnemonic = '%s%d'%(name, (opcode&0x1f) + 1) - elif name in ('SWAP', 'LOG', 'DUP'): - mnemonic = '%s%d'%(name, (opcode&0xf) + 1) + if len(EVMAsm.reverse_table) == 0: + + for (opcode, (name, immediate_operand_size, pops, pushes, gas, description)) in EVMAsm._table.items(): + mnemonic = name + if name == 'PUSH': + mnemonic = '%s%d'%(name, (opcode&0x1f) + 1) + elif name in ('SWAP', 'LOG', 'DUP'): + mnemonic = '%s%d'%(name, (opcode&0xf) + 1) - reverse_table[mnemonic] = opcode, name, immediate_operand_size, pops, pushes, gas, description - return reverse_table + EVMAsm.reverse_table[mnemonic] = opcode, name, immediate_operand_size, pops, pushes, gas, description + return EVMAsm.reverse_table @staticmethod def assemble_one(assembler, offset=0): @@ -732,9 +751,97 @@ class EVMProcessor(idaapi.processor_t): "a_sizeof_fmt": "size %s", } + # dup, swap + def __trace_stop(self, insn, ret_pos): + # determine output, if static return, else None + if insn.get_canon_mnem().startswith("PUSH"): + jump_addr = self.get_operand(insn[0]) + # elif insn.get_canon_mnem().startswith("PUSH"): + # jump_addr = self.get_operand(insn[0]) + else: + print "__trace_stop else" + jump_addr = None + print "__trace_stop end", insn.get_canon_mnem(), hex(self.get_operand(insn[0])), 'ret_pos =',ret_pos + return jump_addr, ret_pos + + def add_jump(self, from_ea, to_ea, jp_type): + add_cref(from_ea, to_ea, jp_type) + if to_ea not in self.dst2src: + self.dst2src[to_ea] = [] + print 'add_jump', hex(from_ea), hex(to_ea) + if from_ea not in self.dst2src[to_ea]: + self.dst2src[to_ea].append(from_ea) + + def add_jumps(self, from_ea, to_ea_list, ret_pos_list, jp_type_list): + if len(to_ea_list) > 1: # note: currently in this case, to_ea_list is not the jump dst addr, but the uppderstream branchs + cmtstr = "cant determine, have multiple upperstream branchs: " + ' '.join([hex(ea).strip('L') for ea in to_ea_list]) + ida_bytes.set_cmt(from_ea, cmtstr, True) + elif len(to_ea_list) == 1: + dst_addr = to_ea_list[0] + self.add_jump(from_ea, dst_addr, jp_type_list[0]) + cmtstr = "JUMP TO: " + hex(dst_addr).strip('L') + ida_bytes.set_cmt(from_ea, cmtstr, True) + else: + return + + def get_all_preceding_insn_on_controlflow(self, insn): + if insn.get_canon_mnem() == 'JUMPDEST' and True: #TODO: and previous insn is not reachable + if insn.ea in self.dst2src: + prev_insn_branchs = [idautils.DecodeInstruction(ea) for ea in self.dst2src[insn.ea]] + else: + prev_insn_branchs = [idautils.DecodePreviousInstruction(insn.ea)] + else: + prev_insn_branchs = [idautils.DecodePreviousInstruction(insn.ea)] + + return prev_insn_branchs + + def trace_jumpdest(self, insn, current_stack_offset): + # if output == 0, keep trace, else stop + + # prev_insn, fl = idautils.DecodePrecedingInstruction(insn.ea) + prev_insn_branchs = self.get_all_preceding_insn_on_controlflow(insn) + if len(prev_insn_branchs) > 1: + print 'multiple prev_insn_branchs:', [hex(ins.ea) for ins in prev_insn_branchs] + # prev_insn = None + # note: here the return[0] is not the jump dst addr, but the upperstream branchs + return [_i.ea for _i in prev_insn_branchs], [0]*len(prev_insn_branchs) + elif len(prev_insn_branchs) == 1: + prev_insn = prev_insn_branchs[0] + print 'in trace_jumpdest, cur insn:', hex(insn.ea), 'pre insn:', hex(prev_insn.ea) if prev_insn else None + + _tbl = EVMAsm._get_reverse_table() + opname = prev_insn.get_canon_mnem() + info = _tbl[opname] + pops, pushes = info[3], info[4] + + print "trace_jumpdest", hex(prev_insn.ea), prev_insn.get_canon_mnem(), pops, pushes, current_stack_offset + update_stack_offset = current_stack_offset - pops + pushes + assert current_stack_offset <=0, "current_stack_offset > 0, impossible, should be addressed in previous trace_jumpdest call" + if pushes > -current_stack_offset: + jump_addr, ret_pos = self.__trace_stop(prev_insn, -current_stack_offset) + if jump_addr is not None: + return [jump_addr], [ret_pos] + else: + return None, None + else: + return self.trace_jumpdest(prev_insn, update_stack_offset) + else: + return None, None + # TODO: implement stack modeling to resolve actual top value of stack + def trace_sp(self, insn): pass + # pfn = get_func(insn.ea) + # if not pfn: + # return + # mnemonic = insn.get_canon_mnem() + # if mnemonic == "PUSH2": + # spofs = 2 + # self.add_auto_stkpnt(pfn, insn, -spofs) + # elif mnemonic == "MSTORE": + # spofs = 2 + # self.add_auto_stkpnt(pfn, insn, -spofs) @staticmethod def get_prototype(num): @@ -743,6 +850,7 @@ def get_prototype(num): return function_prototype def notify_emu(self, insn): + print "notify_emu", insn.ea feature = insn.get_canon_feature() #print "emulating", insn.get_canon_mnem(), hex(feature) @@ -773,27 +881,53 @@ def notify_emu(self, insn): # add ref to next instruction for false branch add_cref(insn.ea, insn.ea + insn.size, fl_JN) - # maybe we have a simple puch - prev_insn = idautils.DecodePreviousInstruction(insn.ea) - if prev_insn: - if prev_insn.get_canon_mnem().startswith("PUSH"): - jump_addr = self.get_operand(prev_insn[0]) - add_cref(insn.ea, jump_addr, fl_JN) + # # maybe we have a simple puch + # prev_insn = idautils.DecodePreviousInstruction(insn.ea) + # if prev_insn: + # if prev_insn.get_canon_mnem().startswith("PUSH"): + # jump_addr = self.get_operand(prev_insn[0]) + # add_cref(insn.ea, jump_addr, fl_JN) + jump_addr_list, ret_pos_list = self.trace_jumpdest(insn, 0) + if jump_addr_list is not None and len(jump_addr_list)>0: + print 'jump_addr_list', jump_addr_list + print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list + # print '+add_cref', hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list + #TODO: use ret_pos + self.add_jumps(insn.ea, jump_addr_list, ret_pos_list, [fl_JN]*len(jump_addr_list)) + else: + print '-not add cref' + pass elif mnemonic == "JUMP": - prev_insn = idautils.DecodePreviousInstruction(insn.ea) - if prev_insn: - # TODO: implement stack modeling to resolve actual top value of stack - if prev_insn.get_canon_mnem().startswith("PUSH"): - jump_addr = self.get_operand(prev_insn[0]) + jump_addr_list, ret_pos_list = self.trace_jumpdest(insn, 0) + # = rst[0], rst[1] + if jump_addr_list is not None and len(jump_addr_list)>0: + print 'jump_addr_list', jump_addr_list + print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list + # print '+add_cref', hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list + #TODO: use ret_pos + self.add_jumps(insn.ea, jump_addr_list, ret_pos_list, [fl_JN]*len(jump_addr_list)) + else: + print '-not add cref' + + # prev_insn = idautils.DecodePreviousInstruction(insn.ea) + # if prev_insn: + # # TODO: implement stack modeling to resolve actual top value of stack + # if prev_insn.get_canon_mnem().startswith("PUSH"): + # jump_addr = self.get_operand(prev_insn[0]) #print "found jump to", hex(jump_addr) - add_cref(insn.ea, jump_addr, fl_JN) + # add_cref(insn.ea, jump_addr, fl_JN) + # print "testxhyu" + # TODO: adjust function boundary to include all code - #func = get_func(insn.ea) - #if func: - # #print "appending new tail" - # #append_func_tail(func, jump_addr, BADADDR) - # #reanalyze_function(func) + # func = get_func(insn.ea) + # if func: + # success = append_func_tail(func.start_ea, jump_addr, BADADDR)#BADADDR + # print "appending new tail", type(insn.ea), success + # print '---', get_func_name(insn.ea), insn.ea, func.start_ea, jump_addr, BADADDR + # print 'insn.ea', insn.ea, 'insn.ip', insn.ip + # reanalyze_function(func) + flows = (feature & CF_STOP) == 0 if flows: @@ -808,6 +942,7 @@ def notify_emu(self, insn): return True def notify_func_bounds(self, code, func_ea, max_func_end_ea): + # print "notify_func_bounds", func_ea """ find_func_bounds() finished its work The module may fine tune the function bounds @@ -838,6 +973,7 @@ def get_operand(op): return operand def notify_out_operand(self, ctx, op): + # print "notify_out_operand", op if op.type == o_idpspec0: operand = self.get_operand(op) ctx.out_line("0x%x" %(operand, )) @@ -863,6 +999,7 @@ def notify_out_insn(self, ctx): def notify_ana(self, insn): + # print "notify_ana", insn.ea ea = insn.ea bytes_left = chunk_start(ea) + chunk_size(ea) - ea bytecode = ida_bytes.get_bytes(insn.ea, bytes_left) # get remaining bytes in chunk @@ -928,6 +1065,7 @@ def notify_ana(self, insn): def notify_assemble(self, ea, cs, ip, use32, line): + # print "notify_assemble", ea try: asm = EVMAsm.assemble_one(line, 0) except Exception as e: @@ -975,8 +1113,44 @@ def __init__(self): i += 1 self.instruc_end = len(self.instruc) - + self.has_rebuild_cf = False + self.dst2src = {} + # def notify_init(self, func): + # print "notify_init test" + + # def notify_auto_queue_empty(self, func): + # print "notify_auto_queue_empty test" + # rst = idc.auto_wait() + # print 'wait ret', rst + # if rst: + # print "++++notify_auto_queue_empty test" + # else: + # print "----notify_auto_queue_empty test" + + def notify_coagulate(self, start_ea): + print "notify_coagulate", start_ea + + def notify_out_header(self, outctx): + print "notify_out_header" + idc.auto_wait() + self.rebuild_cf() + + def rebuild_cf(self): + if self.has_rebuild_cf: + return + self.has_rebuild_cf = True + for func_ea in idautils.Functions(): + #0x8d715d9d + print('rebuild_cf func_ea', func_ea,get_func(func_ea),idc.get_func_name(func_ea)) + reanalyze_function(get_func(func_ea)) def PROCESSOR_ENTRY(): return EVMProcessor() + + + +# print "rebuild_cf before wait" +# idc.auto_wait() +# print "rebuild_cf after wait" +# rebuild_cf() \ No newline at end of file From 34a9eb18dd8110a5b0f5beb722e105073d8830b0 Mon Sep 17 00:00:00 2001 From: xhyumiracle Date: Sun, 7 Aug 2022 20:20:33 +0800 Subject: [PATCH 2/6] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index d5b9442..268394d 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,9 @@ IDA Pro 7.0 or newer is required to use IDA-EVM. * Copy `evm-loader.py` to `%IDA%/loaders` * Copy `evm-cpu.py` and `known_hashes.py` to `%IDA%/procs` * Restart IDA + +# What's New in ida-evm-enhanced +Forked from crytic/ida-evm, enhanced jump dest address analysis. +Previously, jump dest addr can only be resolved when the direct previous instruction is PUSH, but not working on other instructions. +Now ida-evm-enhanced can resolve & display the jump dest addr under all instructions. +The only thing left is, it doesn't follow all branches when there's multiple upperstream code branches. As a workaround, it displays all the upperstream branches in the comments of the jump instruction. From 801e6e5c643306a2aeb972d85d1e9d6e3220c470 Mon Sep 17 00:00:00 2001 From: xhyumiracle Date: Sun, 7 Aug 2022 20:21:10 +0800 Subject: [PATCH 3/6] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 268394d..8936081 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ IDA Pro 7.0 or newer is required to use IDA-EVM. * Restart IDA # What's New in ida-evm-enhanced -Forked from crytic/ida-evm, enhanced jump dest address analysis. -Previously, jump dest addr can only be resolved when the direct previous instruction is PUSH, but not working on other instructions. -Now ida-evm-enhanced can resolve & display the jump dest addr under all instructions. -The only thing left is, it doesn't follow all branches when there's multiple upperstream code branches. As a workaround, it displays all the upperstream branches in the comments of the jump instruction. +- Forked from crytic/ida-evm, enhanced jump dest address analysis. +- Previously, jump dest addr can only be resolved when the direct previous instruction is PUSH, but not working on other instructions. +- Now ida-evm-enhanced can resolve & display the jump dest addr under all instructions. +- The only thing left is, it doesn't follow all branches when there's multiple upperstream code branches. As a workaround, it displays all the upperstream branches in the comments of the jump instruction. From e114705d1a4d00e6b4995759c274fa90ddaa3cfe Mon Sep 17 00:00:00 2001 From: xhyumiracle Date: Sun, 7 Aug 2022 20:25:01 +0800 Subject: [PATCH 4/6] clean logs --- evm-cpu.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/evm-cpu.py b/evm-cpu.py index 2115a9b..208fae1 100755 --- a/evm-cpu.py +++ b/evm-cpu.py @@ -759,16 +759,16 @@ def __trace_stop(self, insn, ret_pos): # elif insn.get_canon_mnem().startswith("PUSH"): # jump_addr = self.get_operand(insn[0]) else: - print "__trace_stop else" + # print "__trace_stop else" jump_addr = None - print "__trace_stop end", insn.get_canon_mnem(), hex(self.get_operand(insn[0])), 'ret_pos =',ret_pos + # print "__trace_stop end", insn.get_canon_mnem(), hex(self.get_operand(insn[0])), 'ret_pos =',ret_pos return jump_addr, ret_pos def add_jump(self, from_ea, to_ea, jp_type): add_cref(from_ea, to_ea, jp_type) if to_ea not in self.dst2src: self.dst2src[to_ea] = [] - print 'add_jump', hex(from_ea), hex(to_ea) + # print 'add_jump', hex(from_ea), hex(to_ea) if from_ea not in self.dst2src[to_ea]: self.dst2src[to_ea].append(from_ea) @@ -801,20 +801,20 @@ def trace_jumpdest(self, insn, current_stack_offset): # prev_insn, fl = idautils.DecodePrecedingInstruction(insn.ea) prev_insn_branchs = self.get_all_preceding_insn_on_controlflow(insn) if len(prev_insn_branchs) > 1: - print 'multiple prev_insn_branchs:', [hex(ins.ea) for ins in prev_insn_branchs] + # print 'multiple prev_insn_branchs:', [hex(ins.ea) for ins in prev_insn_branchs] # prev_insn = None # note: here the return[0] is not the jump dst addr, but the upperstream branchs return [_i.ea for _i in prev_insn_branchs], [0]*len(prev_insn_branchs) elif len(prev_insn_branchs) == 1: prev_insn = prev_insn_branchs[0] - print 'in trace_jumpdest, cur insn:', hex(insn.ea), 'pre insn:', hex(prev_insn.ea) if prev_insn else None + # print 'in trace_jumpdest, cur insn:', hex(insn.ea), 'pre insn:', hex(prev_insn.ea) if prev_insn else None _tbl = EVMAsm._get_reverse_table() opname = prev_insn.get_canon_mnem() info = _tbl[opname] pops, pushes = info[3], info[4] - print "trace_jumpdest", hex(prev_insn.ea), prev_insn.get_canon_mnem(), pops, pushes, current_stack_offset + # print "trace_jumpdest", hex(prev_insn.ea), prev_insn.get_canon_mnem(), pops, pushes, current_stack_offset update_stack_offset = current_stack_offset - pops + pushes assert current_stack_offset <=0, "current_stack_offset > 0, impossible, should be addressed in previous trace_jumpdest call" if pushes > -current_stack_offset: @@ -850,7 +850,7 @@ def get_prototype(num): return function_prototype def notify_emu(self, insn): - print "notify_emu", insn.ea + # print "notify_emu", insn.ea feature = insn.get_canon_feature() #print "emulating", insn.get_canon_mnem(), hex(feature) @@ -889,26 +889,27 @@ def notify_emu(self, insn): # add_cref(insn.ea, jump_addr, fl_JN) jump_addr_list, ret_pos_list = self.trace_jumpdest(insn, 0) if jump_addr_list is not None and len(jump_addr_list)>0: - print 'jump_addr_list', jump_addr_list - print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list + # print 'jump_addr_list', jump_addr_list + # print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list # print '+add_cref', hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list #TODO: use ret_pos self.add_jumps(insn.ea, jump_addr_list, ret_pos_list, [fl_JN]*len(jump_addr_list)) else: - print '-not add cref' + # print '-not add cref' pass elif mnemonic == "JUMP": jump_addr_list, ret_pos_list = self.trace_jumpdest(insn, 0) # = rst[0], rst[1] if jump_addr_list is not None and len(jump_addr_list)>0: - print 'jump_addr_list', jump_addr_list - print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list + # print 'jump_addr_list', jump_addr_list + # print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list # print '+add_cref', hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list #TODO: use ret_pos self.add_jumps(insn.ea, jump_addr_list, ret_pos_list, [fl_JN]*len(jump_addr_list)) else: - print '-not add cref' + # print '-not add cref' + pass # prev_insn = idautils.DecodePreviousInstruction(insn.ea) # if prev_insn: @@ -1127,11 +1128,11 @@ def __init__(self): # else: # print "----notify_auto_queue_empty test" - def notify_coagulate(self, start_ea): - print "notify_coagulate", start_ea + # def notify_coagulate(self, start_ea): + # print "notify_coagulate", start_ea def notify_out_header(self, outctx): - print "notify_out_header" + # print "notify_out_header" idc.auto_wait() self.rebuild_cf() From 8ae47cedd4af9ec9c0b8a1107c5eddf8d5de9c16 Mon Sep 17 00:00:00 2001 From: xhyumiracle Date: Sun, 7 Aug 2022 20:30:04 +0800 Subject: [PATCH 5/6] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8936081..3d76b4e 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,6 @@ IDA Pro 7.0 or newer is required to use IDA-EVM. - Forked from crytic/ida-evm, enhanced jump dest address analysis. - Previously, jump dest addr can only be resolved when the direct previous instruction is PUSH, but not working on other instructions. - Now ida-evm-enhanced can resolve & display the jump dest addr under all instructions. +- e.g.:![image](https://user-images.githubusercontent.com/17793687/183290524-3c53a3eb-049c-4c13-905e-f36f314c73e3.png) - The only thing left is, it doesn't follow all branches when there's multiple upperstream code branches. As a workaround, it displays all the upperstream branches in the comments of the jump instruction. +- e.g.:![image](https://user-images.githubusercontent.com/17793687/183290588-03cdbf7e-3444-4d6e-a693-5c7b95f89268.png) From f53c78e5aee6a190328d19a3d72647988777c148 Mon Sep 17 00:00:00 2001 From: xhyumiracle Date: Fri, 19 Jan 2024 17:42:04 +0800 Subject: [PATCH 6/6] misc: clean code for pr --- README.md | 10 +------- evm-cpu.py | 69 ++---------------------------------------------------- 2 files changed, 3 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 3d76b4e..22b4e3e 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,4 @@ IDA Pro 7.0 or newer is required to use IDA-EVM. # Installation * Copy `evm-loader.py` to `%IDA%/loaders` * Copy `evm-cpu.py` and `known_hashes.py` to `%IDA%/procs` -* Restart IDA - -# What's New in ida-evm-enhanced -- Forked from crytic/ida-evm, enhanced jump dest address analysis. -- Previously, jump dest addr can only be resolved when the direct previous instruction is PUSH, but not working on other instructions. -- Now ida-evm-enhanced can resolve & display the jump dest addr under all instructions. -- e.g.:![image](https://user-images.githubusercontent.com/17793687/183290524-3c53a3eb-049c-4c13-905e-f36f314c73e3.png) -- The only thing left is, it doesn't follow all branches when there's multiple upperstream code branches. As a workaround, it displays all the upperstream branches in the comments of the jump instruction. -- e.g.:![image](https://user-images.githubusercontent.com/17793687/183290588-03cdbf7e-3444-4d6e-a693-5c7b95f89268.png) +* Restart IDA \ No newline at end of file diff --git a/evm-cpu.py b/evm-cpu.py index 208fae1..8964c71 100755 --- a/evm-cpu.py +++ b/evm-cpu.py @@ -3,9 +3,7 @@ from idc import * from idaapi import * import idautils -# from idadex import ea_t -# from decorators import memoized import known_hashes ''' @@ -453,23 +451,7 @@ def is_arithmetic(self): 0xff: ('SELFDESTRUCT', 0, 1, 0, 5000, 'Halt execution and register account for later deletion.') } - # @staticmethod - # # @memoized - # def _get_reverse_table(): - # ''' Build an internal table used in the assembler ''' - # reverse_table = {} - # for (opcode, (name, immediate_operand_size, pops, pushes, gas, description)) in EVMAsm._table.items(): - # mnemonic = name - # if name == 'PUSH': - # mnemonic = '%s%d'%(name, (opcode&0x1f) + 1) - # elif name in ('SWAP', 'LOG', 'DUP'): - # mnemonic = '%s%d'%(name, (opcode&0xf) + 1) - - # reverse_table[mnemonic] = opcode, name, immediate_operand_size, pops, pushes, gas, description - # return reverse_table - @staticmethod - # @memoized def _get_reverse_table(): ''' Build an internal table used in the assembler ''' if len(EVMAsm.reverse_table) == 0: @@ -832,16 +814,6 @@ def trace_jumpdest(self, insn, current_stack_offset): def trace_sp(self, insn): pass - # pfn = get_func(insn.ea) - # if not pfn: - # return - # mnemonic = insn.get_canon_mnem() - # if mnemonic == "PUSH2": - # spofs = 2 - # self.add_auto_stkpnt(pfn, insn, -spofs) - # elif mnemonic == "MSTORE": - # spofs = 2 - # self.add_auto_stkpnt(pfn, insn, -spofs) @staticmethod def get_prototype(num): @@ -850,7 +822,6 @@ def get_prototype(num): return function_prototype def notify_emu(self, insn): - # print "notify_emu", insn.ea feature = insn.get_canon_feature() #print "emulating", insn.get_canon_mnem(), hex(feature) @@ -889,26 +860,17 @@ def notify_emu(self, insn): # add_cref(insn.ea, jump_addr, fl_JN) jump_addr_list, ret_pos_list = self.trace_jumpdest(insn, 0) if jump_addr_list is not None and len(jump_addr_list)>0: - # print 'jump_addr_list', jump_addr_list - # print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list - # print '+add_cref', hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list #TODO: use ret_pos self.add_jumps(insn.ea, jump_addr_list, ret_pos_list, [fl_JN]*len(jump_addr_list)) else: - # print '-not add cref' pass elif mnemonic == "JUMP": jump_addr_list, ret_pos_list = self.trace_jumpdest(insn, 0) - # = rst[0], rst[1] if jump_addr_list is not None and len(jump_addr_list)>0: - # print 'jump_addr_list', jump_addr_list - # print hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list - # print '+add_cref', hex(insn.ea), [hex(ea) for ea in jump_addr_list], 'ret_pos:', ret_pos_list #TODO: use ret_pos self.add_jumps(insn.ea, jump_addr_list, ret_pos_list, [fl_JN]*len(jump_addr_list)) else: - # print '-not add cref' pass # prev_insn = idautils.DecodePreviousInstruction(insn.ea) @@ -943,7 +905,6 @@ def notify_emu(self, insn): return True def notify_func_bounds(self, code, func_ea, max_func_end_ea): - # print "notify_func_bounds", func_ea """ find_func_bounds() finished its work The module may fine tune the function bounds @@ -974,7 +935,6 @@ def get_operand(op): return operand def notify_out_operand(self, ctx, op): - # print "notify_out_operand", op if op.type == o_idpspec0: operand = self.get_operand(op) ctx.out_line("0x%x" %(operand, )) @@ -1000,7 +960,6 @@ def notify_out_insn(self, ctx): def notify_ana(self, insn): - # print "notify_ana", insn.ea ea = insn.ea bytes_left = chunk_start(ea) + chunk_size(ea) - ea bytecode = ida_bytes.get_bytes(insn.ea, bytes_left) # get remaining bytes in chunk @@ -1066,7 +1025,6 @@ def notify_ana(self, insn): def notify_assemble(self, ea, cs, ip, use32, line): - # print "notify_assemble", ea try: asm = EVMAsm.assemble_one(line, 0) except Exception as e: @@ -1116,23 +1074,8 @@ def __init__(self): self.instruc_end = len(self.instruc) self.has_rebuild_cf = False self.dst2src = {} - # def notify_init(self, func): - # print "notify_init test" - - # def notify_auto_queue_empty(self, func): - # print "notify_auto_queue_empty test" - # rst = idc.auto_wait() - # print 'wait ret', rst - # if rst: - # print "++++notify_auto_queue_empty test" - # else: - # print "----notify_auto_queue_empty test" - - # def notify_coagulate(self, start_ea): - # print "notify_coagulate", start_ea - + def notify_out_header(self, outctx): - # print "notify_out_header" idc.auto_wait() self.rebuild_cf() @@ -1141,17 +1084,9 @@ def rebuild_cf(self): return self.has_rebuild_cf = True for func_ea in idautils.Functions(): - #0x8d715d9d print('rebuild_cf func_ea', func_ea,get_func(func_ea),idc.get_func_name(func_ea)) reanalyze_function(get_func(func_ea)) def PROCESSOR_ENTRY(): - return EVMProcessor() - - - -# print "rebuild_cf before wait" -# idc.auto_wait() -# print "rebuild_cf after wait" -# rebuild_cf() \ No newline at end of file + return EVMProcessor() \ No newline at end of file