├── comment-trace.py ├── dbg-loc-off.py ├── deopt.py ├── findsvc.py ├── get_all_code.py ├── get_all_jump.py ├── get_all_opcode.py ├── get_all_svc.py ├── ida_trace.py ├── plugin ├── my_continue.py ├── mystep_into.py ├── mystep_over.py └── step2jump.py ├── range_set_thumb.py └── trace.py /comment-trace.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | import os.path 4 | #idaapi.split_sreg_range(instruction_pointer, idaapi.str2reg("T"), required_t_value, idaapi.SR_user) 5 | 6 | if __name__ == "__main__": 7 | trace_path = "" 8 | filename = "" 9 | in_ida = True 10 | 11 | try: 12 | import idc 13 | in_ida = True 14 | except ImportError as e: 15 | print("not run in ida python skip comment...") 16 | in_ida = False 17 | # 18 | is_clean=0 19 | if (in_ida): 20 | trace_path = idc.AskFile(0, "*.*", "trace path") 21 | is_clean = idc.AskLong(0, "clean path?") 22 | if (not os.path.isabs(trace_path)): 23 | script_path = os.path.split(os.path.realpath(__file__))[0] 24 | trace_path = "%s/%s"%(script_path, trace_path) 25 | # 26 | filename = idc.get_root_filename() 27 | # 28 | else: 29 | trace_path = sys.argv[1] 30 | filename = sys.argv[2] 31 | if (len(sys.argv)<3): 32 | print("usage %s "%sys.argv[0]) 33 | sys.exit(-1) 34 | # 35 | # 36 | dic_call = {} 37 | with open(trace_path) as f: 38 | for line in f: 39 | line = line.strip() 40 | if (line == ""): 41 | continue 42 | # 43 | if (line.find(filename)<0): 44 | continue 45 | # 46 | sa = line.split(":") 47 | start = sa[0].rfind("]")+1 48 | addr = sa[0][start:] 49 | count = 1 50 | if (addr in dic_call): 51 | count = dic_call[addr] + 1 52 | dic_call[addr] = count 53 | # 54 | # 55 | print(dic_call) 56 | if (in_ida): 57 | for addr in dic_call: 58 | comm = "" 59 | color = 0xFFFFFF 60 | int_addr = int(addr, 16) 61 | if is_clean == 0: 62 | int_call = dic_call[addr] 63 | comm = str(int_call) 64 | if (int_call > 0 and int_call < 20): 65 | color = 0xFFAFFF 66 | # 67 | elif (int_call >=20 and int_call < 40): 68 | color = 0xFF7FFF 69 | else: 70 | color = 0xFF00FF 71 | # 72 | # 73 | idc.MakeComm(int_addr, comm) 74 | idc.SetColor(int_addr, idc.CIC_ITEM, color) 75 | # 76 | # 77 | # 78 | -------------------------------------------------------------------------------- /dbg-loc-off.py: -------------------------------------------------------------------------------- 1 | import idc 2 | import os 3 | 4 | somodule = AskStr('libcms.so', 'module name') 5 | 6 | off_str = AskStr('0x0', 'in hex') 7 | 8 | off = int(off_str, 16) 9 | modulebase = GetFirstModule() 10 | 11 | while (modulebase != None) and (GetModuleName(modulebase).find(somodule) == -1): 12 | modulebase = GetNextModule(modulebase) 13 | 14 | if modulebase == None: 15 | print ('failed to find module:' , somodule) 16 | 17 | else: 18 | abs_off = modulebase + off 19 | print ('module of %s base address is: 0x%08X'%(somodule, modulebase)) 20 | print("jump to 0x%08X"%abs_off) 21 | Jump(abs_off) 22 | # -------------------------------------------------------------------------------- /deopt.py: -------------------------------------------------------------------------------- 1 | # 去除虚假控制流 idapython脚本 2 | import ida_xref 3 | import ida_idaapi 4 | from ida_bytes import get_bytes, patch_bytes 5 | 6 | # 将 mov 寄存器, 不透明谓词 修改为 mov 寄存器, 0 7 | def do_patch(ea): 8 | if get_bytes(ea, 1) == b"\x8B": # mov eax-edi, dword 9 | reg = (ord(get_bytes(ea + 1, 1)) & 0b00111000) >> 3 10 | patch_bytes(ea, (0xB8 + reg).to_bytes(1,'little') + b'\x00\x00\x00\x00\x90') 11 | else: 12 | print('error') 13 | 14 | # 不透明谓词在.bss段的范围 15 | start = 0x00428298 16 | end = 0x00428384 17 | 18 | for addr in range(start,end,4): 19 | ref = ida_xref.get_first_dref_to(addr) 20 | print(hex(addr).center(20,'-')) 21 | # 获取所有交叉引用 22 | while(ref != ida_idaapi.BADADDR): 23 | do_patch(ref) 24 | print('patch at ' + hex(ref)) 25 | ref = ida_xref.get_next_dref_to(addr, ref) 26 | print('-' * 20) 27 | -------------------------------------------------------------------------------- /findsvc.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import posixpath 3 | import sys 4 | import os 5 | import traceback 6 | 7 | def find_bytes(f, target): 8 | addrs = [] 9 | f.seek(0, 0) 10 | step = len(target) 11 | off = 0 12 | while True: 13 | b = f.read(step) 14 | if (b == target): 15 | addrs.append(off) 16 | # 17 | if (len(b) == 0): 18 | break 19 | off += step 20 | # 21 | return addrs 22 | # 23 | 24 | if __name__ == "__main__": 25 | if (len(sys.argv) < 2): 26 | print ("usage %s "%sys.argv[0]) 27 | sys.exit(1) 28 | # 29 | soname = sys.argv[1] 30 | svc_arm = bytearray([00, 00, 00, 0xef]) 31 | svc_thumb = bytearray([00, 0xdf]) 32 | svc_arm64_ios = bytearray([0x01,0x10,0x00,0xD4]) 33 | with open(soname, "rb") as f: 34 | svcs_arm = find_bytes(f, svc_arm) 35 | print ("svc arm:") 36 | for svc in svcs_arm: 37 | print(hex(svc)) 38 | # 39 | print ("svc thumb:") 40 | svcs_thumb = find_bytes(f, svc_thumb) 41 | for svc in svcs_thumb: 42 | print(hex(svc)) 43 | # 44 | print ("svc ios64:") 45 | svcs_thumb = find_bytes(f, svc_arm64_ios) 46 | for svc in svcs_thumb: 47 | print(hex(svc)) 48 | # 49 | # 50 | # 51 | -------------------------------------------------------------------------------- /get_all_code.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | funName = idc.AskStr("JNI_OnLoad", "function name") 6 | funAddr = LocByName(funName) 7 | if funAddr == BADADDR: 8 | print("funName %s not found"%funName) 9 | raise RuntimeError("funName %s not found"%funName) 10 | # 11 | 12 | funEndAddr = FindFuncEnd(funAddr) 13 | 14 | heads = Heads(funAddr, funEndAddr) 15 | 16 | script_path = os.path.split(os.path.realpath(__file__))[0] 17 | name = os.path.splitext(idc.get_root_filename())[0] 18 | out_path = "%s/codes-%s-%s.txt"%(script_path, name, funName) 19 | count = 0 20 | with open(out_path, "w") as f: 21 | for h in heads: 22 | if GetMnem(h) != '': 23 | line = "[0x%08X] %s\n"%(h, GetDisasm(h)) 24 | f.write(line) 25 | count = count+1 26 | # 27 | # 28 | # 29 | print("ins count %d"%count) 30 | print("file output to %s"%out_path) -------------------------------------------------------------------------------- /get_all_jump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | import os 6 | import os.path 7 | from idaapi import * 8 | import time 9 | import idc 10 | from idc import * 11 | 12 | def my_get_reg_value(register): 13 | rv = ida_idd.regval_t() 14 | ida_dbg.get_reg_val(register, rv) 15 | regval = rv.ival 16 | return regval 17 | 18 | class MyDbgHooks(DBG_Hooks): 19 | def __init__(self, output_path, fetch_ea): 20 | DBG_Hooks.__init__(self) 21 | self.__output_path = output_path 22 | self.__output = None 23 | self.__ea_prev = 0 24 | self.__cur_blist = [] 25 | self.__cur_opcode = None 26 | self.__mlist = {} 27 | self.__fetch_ea = fetch_ea 28 | 29 | # 30 | 31 | def dbg_process_attach(self, pid, tid, ea, name, base, size): 32 | print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size)) 33 | self.__output = open(self.__output_path, "w") 34 | self.__tm = time.time() 35 | # 36 | 37 | def dbg_bpt(self, tid, ea): 38 | if (ea == self.__ea_prev): 39 | #不知道为何ida大多数指令会这个回调会调用两次 40 | return 0 41 | # 42 | self.__ea_prev = ea 43 | base = int(get_imagebase()) 44 | addr = int(ea) 45 | #print ("Break point at 0x%x pid=%d" % (ea, tid)) 46 | name = idc.get_root_filename() 47 | disasm_str = GetDisasm(ea) 48 | print("0x%08x %s hit"%(ea, disasm_str)) 49 | fetch_abs_ea = base + self.__fetch_ea 50 | #print("%x %x"%(addr, fetch_abs_ea)) 51 | if (addr == fetch_abs_ea): 52 | if (not len(self.__cur_blist) == 0 and self.__cur_opcode != None): 53 | tu = tuple(self.__cur_blist) 54 | if (tu not in self.__mlist): 55 | self.__mlist[tu] = self.__cur_opcode 56 | print("get distinct opcode %d"%len(self.__mlist)) 57 | # 58 | self.__cur_blist = [] 59 | self.__cur_opcode = my_get_reg_value("R5") 60 | # 61 | else: 62 | self.__cur_blist.append(addr) 63 | # # return values: 64 | # # -1 - to display a breakpoint warning dialog 65 | # # if the process is suspended. 66 | # # 0 - to never display a breakpoint warning dialog. 67 | # # 1 - to always display a breakpoint warning dialog. 68 | return 0 69 | # 70 | 71 | def __print_res(self): 72 | base = int(get_imagebase()) 73 | print("base %s"%hex(base)) 74 | if (self.__output != None): 75 | self.__output.close() 76 | # 77 | nmlist = 0 78 | for baddrs in self.__mlist: 79 | opcode = self.__mlist[baddrs] 80 | print("opcode %s reach block:"%(hex(opcode),)) 81 | for baddr in baddrs: 82 | print("block %s"%(hex(baddr), )) 83 | # 84 | print("end block") 85 | nmlist = nmlist + 1 86 | # 87 | print("after print res %d distinct opcode..."%nmlist) 88 | t = time.time() - self.__tm 89 | print("time use %.3f"%t) 90 | # 91 | 92 | def dbg_suspend_process(self): 93 | print ("Process suspended") 94 | self.__print_res() 95 | # 96 | 97 | def dbg_process_exit(self, pid, tid, ea, code): 98 | print("call Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code)) 99 | self.__print_res() 100 | # 101 | 102 | # 103 | 104 | if __name__ == "__main__": 105 | 106 | # Remove an existing debug hook 107 | try: 108 | if debughook: 109 | print("Removing previous hook ...") 110 | debughook.unhook() 111 | # 112 | # 113 | except: 114 | pass 115 | # 116 | 117 | funName = idc.AskStr("vmp", "function name") 118 | funAddr = LocByName(funName) 119 | if funAddr == BADADDR: 120 | print("funName %s not found"%funName) 121 | raise RuntimeError("funName %s not found"%funName) 122 | # 123 | 124 | funEndAddr = FindFuncEnd(funAddr) 125 | if funAddr == BADADDR: 126 | raise RuntimeError("funName %s end not found"%funName) 127 | # 128 | function = idaapi.get_func(funAddr) 129 | 130 | nBpt = 0 131 | flowchart = idaapi.FlowChart(function) 132 | for bb in flowchart: 133 | ea = bb.startEA 134 | AddBpt(ea) 135 | SetBptAttr(ea, BPTATTR_FLAGS, BPT_ENABLED|BPT_TRACE) 136 | nBpt = nBpt + 1 137 | print(nBpt) 138 | 139 | script_path = os.path.split(os.path.realpath(__file__))[0] 140 | name = os.path.splitext(idc.get_root_filename())[0] 141 | file_path = "%s/log-%s.txt"%(script_path, name) 142 | 143 | fetch_ea = 0x0004C0CC 144 | fetch_abs_ea = get_imagebase() + fetch_ea 145 | AddBpt(fetch_abs_ea) 146 | SetBptAttr(fetch_abs_ea, BPTATTR_FLAGS, BPT_ENABLED|BPT_TRACE) 147 | 148 | 149 | #Install the debug hook 150 | debughook = MyDbgHooks(file_path, fetch_ea) 151 | debughook.hook() 152 | debughook.steps = 0 153 | print ("script run...") 154 | # 155 | -------------------------------------------------------------------------------- /get_all_opcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | import os 6 | import os.path 7 | from idaapi import * 8 | import time 9 | import idc 10 | from idc import * 11 | 12 | def my_get_reg_value(register): 13 | rv = ida_idd.regval_t() 14 | ida_dbg.get_reg_val(register, rv) 15 | regval = rv.ival 16 | return regval 17 | 18 | class MyDbgHooks(DBG_Hooks): 19 | def __init__(self, output_path, enter_ea, fetch_ea, exit_ea): 20 | DBG_Hooks.__init__(self) 21 | self.__output_path = output_path 22 | self.__output = None 23 | self.__cur_opset = None 24 | self.__opstack = [] 25 | self.__enter_ea = enter_ea 26 | self.__fetch_ea = fetch_ea 27 | self.__exit_ea = exit_ea 28 | 29 | # 30 | 31 | def dbg_process_attach(self, pid, tid, ea, name, base, size): 32 | print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size)) 33 | self.__output = open(self.__output_path, "w") 34 | self.__tm = time.time() 35 | # 36 | 37 | def __print_res(self): 38 | base = int(get_imagebase()) 39 | tmp_list = list(self.__cur_opset) 40 | tmp_list.sort() 41 | 42 | head = "begin dump opcode base 0x%08x\n"%int(base) 43 | self.__output.write(head) 44 | for opcode in tmp_list: 45 | line = "0x%08x\n"%int(opcode) 46 | self.__output.write(line) 47 | 48 | if (self.__output != None): 49 | self.__output.flush() 50 | # 51 | # 52 | 53 | def dbg_bpt(self, tid, ea): 54 | base = int(get_imagebase()) 55 | addr = int(ea) 56 | fetch_abs_ea = base + self.__fetch_ea 57 | enter_abs_ea = base + self.__enter_ea 58 | exit_abs_ea = base + self.__exit_ea 59 | #print("%x %x"%(addr, fetch_abs_ea)) 60 | if (addr == enter_abs_ea): 61 | print("enter vmp...") 62 | if (self.__cur_opset != None): 63 | self.__opstack.append(self.__cur_opset) 64 | # 65 | self.__cur_opset = set() 66 | 67 | elif (addr == fetch_abs_ea): 68 | cur_opcode = my_get_reg_value("R0") 69 | self.__cur_opset.add(cur_opcode) 70 | print("opcode off 0x%08x"%int(cur_opcode)) 71 | # 72 | elif (addr == exit_abs_ea): 73 | print("exit vmp dump...") 74 | self.__print_res() 75 | self.__cur_opset = self.__opstack.pop() 76 | if (len(self.__opstack) == 0): 77 | print("finish...") 78 | # 79 | # 80 | return 0 81 | # 82 | 83 | 84 | def dbg_suspend_process(self): 85 | print ("Process suspended") 86 | 87 | if (self.__output != None): 88 | self.__output.flush() 89 | # 90 | # 91 | 92 | def dbg_process_exit(self, pid, tid, ea, code): 93 | print("call Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code)) 94 | 95 | if (self.__output != None): 96 | self.__output.close() 97 | # 98 | # 99 | 100 | # 101 | 102 | if __name__ == "__main__": 103 | 104 | # Remove an existing debug hook 105 | try: 106 | if debughook: 107 | print("Removing previous hook ...") 108 | debughook.unhook() 109 | # 110 | # 111 | except: 112 | pass 113 | # 114 | 115 | script_path = os.path.split(os.path.realpath(__file__))[0] 116 | name = os.path.splitext(idc.get_root_filename())[0] 117 | file_path = "%s/opcodes-%s.txt"%(script_path, name) 118 | 119 | fetch_ea = 0x0004C0CC 120 | fetch_abs_ea = get_imagebase() + fetch_ea 121 | AddBpt(fetch_abs_ea) 122 | SetBptAttr(fetch_abs_ea, BPTATTR_FLAGS, BPT_ENABLED|BPT_TRACE) 123 | 124 | enter_ea = 0x0004C028 125 | enter_abs_ea = get_imagebase() + enter_ea 126 | AddBpt(enter_abs_ea) 127 | SetBptAttr(enter_abs_ea, BPTATTR_FLAGS, BPT_ENABLED|BPT_TRACE) 128 | 129 | #用0x4DDB4会崩溃 130 | exit_ea = 0x4DDB0 131 | exit_abs_ea = get_imagebase() + exit_ea 132 | AddBpt(exit_abs_ea) 133 | SetBptAttr(exit_abs_ea, BPTATTR_FLAGS, BPT_ENABLED|BPT_TRACE) 134 | 135 | #Install the debug hook 136 | debughook = MyDbgHooks(file_path, enter_ea, fetch_ea, exit_ea) 137 | debughook.hook() 138 | debughook.steps = 0 139 | print ("script run...") 140 | # 141 | -------------------------------------------------------------------------------- /get_all_svc.py: -------------------------------------------------------------------------------- 1 | 2 | #find all system call in moudle, and and break point on it 3 | form = idaapi.find_tform("Output window") 4 | idaapi.switchto_tform(form, True) 5 | idaapi.process_ui_action("msglist:Clear") 6 | 7 | for ea in Segments(): 8 | heads = Heads(SegStart(ea), SegEnd(ea)) 9 | for h in heads: 10 | if GetMnem(h) != '': 11 | asm = GetDisasm(h) 12 | if (asm.startswith("SVC")): 13 | print ("[0x%08X][%40s] %s"%(h, GetFunctionName(h), asm)) 14 | AddBpt(h) 15 | # 16 | # 17 | # 18 | # 19 | print ("Add break point on all svc ok...") -------------------------------------------------------------------------------- /ida_trace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import idaapi 5 | import idc 6 | import re 7 | import ida_dbg 8 | import ida_idd 9 | from idaapi import * 10 | from collections import OrderedDict 11 | import logging 12 | import time 13 | import datetime 14 | import os 15 | 16 | debughook = None 17 | 18 | def set_breakpoint(ea): 19 | idc.add_bpt(ea) 20 | 21 | def my_get_reg_value(register): 22 | rv = ida_idd.regval_t() 23 | ida_dbg.get_reg_val(register, rv) 24 | current_addr = rv.ival 25 | return current_addr 26 | 27 | ############ 28 | def suspend_other_thread(): 29 | current_thread = idc.get_current_thread() 30 | thread_count = idc.get_thread_qty() 31 | for i in range(0, thread_count): 32 | other_thread = idc.getn_thread(i) 33 | if other_thread != current_thread: 34 | idc.suspend_thread(other_thread) 35 | # 36 | # 37 | # 38 | 39 | 40 | def resume_other_thread(): 41 | current_thread = idc.get_current_thread() 42 | thread_count = idc.get_thread_qty() 43 | for i in range(0, thread_count): 44 | other_thread = idc.getn_thread(i) 45 | if other_thread != current_thread: 46 | idc.resume_thread(other_thread) 47 | #idc.resume_thread(current_thread) 48 | #idc.resume_process() 49 | # 50 | 51 | class MyDbgHook(DBG_Hooks): 52 | """ Own debug hook class that implementd the callback functions """ 53 | 54 | def __init__(self, modules_info, skip_functions, start_ea, end_ea): 55 | super(MyDbgHook, self).__init__() 56 | self.modules_info = modules_info 57 | self.skip_functions = skip_functions 58 | self.trace_step_into_count = 0 59 | self.trace_step_into_size = 1 60 | self.trace_total_size = 300000000 61 | self.trace_size = 0 62 | self.trace_lr = 0 63 | self.end_ea = end_ea 64 | self.start_ea = start_ea 65 | self.line_trace = 0 66 | print("__init__") 67 | 68 | def start_line_trace(self): 69 | self.line_trace = 1 70 | self.start_hook() 71 | 72 | def start_hook(self): 73 | self.hook() 74 | print("start_hook") 75 | 76 | def dbg_process_start(self, pid, tid, ea, name, base, size): 77 | print("Process started, pid=%d tid=%d name=%s" % (pid, tid, name)) 78 | 79 | def dbg_process_exit(self, pid, tid, ea, code): 80 | self.unhook() 81 | print("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code)) 82 | 83 | def dbg_process_detach(self, pid, tid, ea): 84 | self.unhook() 85 | return 0 86 | 87 | def dbg_bpt(self, tid, ea): 88 | print("Break point at 0x%x tid=%d" % (ea, tid)) 89 | if (ea == self.start_ea): 90 | print("auto suspend_other_thread") 91 | suspend_other_thread() 92 | ida_dbg.request_clear_trace() 93 | ida_dbg.run_requests() 94 | 95 | ida_dbg.enable_insn_trace(True) 96 | ida_dbg.enable_step_trace(True) 97 | # 98 | if ea in self.end_ea: 99 | ida_dbg.enable_insn_trace(False) 100 | ida_dbg.enable_step_trace(False) 101 | #ida_dbg.suspend_process() 102 | print("auto resume_other_thread") 103 | resume_other_thread() 104 | # 105 | return 0 106 | 107 | def dbg_trace(self, tid, ea): 108 | #print("Trace tid=%d ea=0x%x" % (tid, ea)) 109 | # return values: 110 | # 1 - do not log this trace event; 111 | # 0 - log it 112 | lr = hex(my_get_reg_value("LR")) 113 | print("%s %s"%(hex(ea), lr)) 114 | if self.line_trace: 115 | in_mine_so = False 116 | for module_info in self.modules_info: 117 | # print (module_info) 118 | so_base = module_info["base"] 119 | so_size = module_info["size"] 120 | if so_base <= ea <= (so_base + so_size): 121 | in_mine_so = True 122 | return 0 123 | 124 | return 1 125 | ''' 126 | self.trace_size += 1 127 | if (not in_mine_so) or (ea in self.skip_functions): 128 | if (self.trace_lr != 0) and (self.trace_step_into_count < self.trace_step_into_size): 129 | self.trace_step_into_count += 1 130 | return 0 131 | 132 | if (self.trace_lr != 0) and (self.trace_step_into_count == self.trace_step_into_size): 133 | ida_dbg.enable_insn_trace(False) 134 | ida_dbg.enable_step_trace(False) 135 | ida_dbg.suspend_process() 136 | if self.trace_size > self.trace_total_size: 137 | self.trace_size = 0 138 | ida_dbg.request_clear_trace() 139 | ida_dbg.run_requests() 140 | 141 | ida_dbg.request_run_to(self.trace_lr & 0xFFFFFFFE) 142 | ida_dbg.run_requests() 143 | self.trace_lr = 0 144 | self.trace_step_into_count = 0 145 | return 0 146 | 147 | if self.trace_lr == 0: 148 | self.trace_lr = my_get_reg_value("LR") 149 | return 0 150 | ''' 151 | 152 | def dbg_run_to(self, pid, tid=0, ea=0): 153 | # print("dbg_run_to 0x%x pid=%d" % (ea, pid)) 154 | if self.line_trace: 155 | ida_dbg.enable_insn_trace(True) 156 | ida_dbg.enable_step_trace(True) 157 | ida_dbg.request_continue_process() 158 | ida_dbg.run_requests() 159 | 160 | 161 | def unhook(): 162 | global debughook 163 | # Remove an existing debug hook 164 | try: 165 | if debughook: 166 | print("Removing previous hook ...") 167 | debughook.unhook() 168 | except: 169 | pass 170 | 171 | 172 | def starthook(): 173 | global debughook 174 | if debughook: 175 | debughook.start_line_trace() 176 | 177 | def main(): 178 | global debughook 179 | #ida7 debug 中有bug,弹AskStr会卡死 180 | #基本流程 181 | #1.需要手动调整下面三个参数 182 | target1 = "libmetasec_ml.so" 183 | start_off_in_target = 0x0004C028 184 | end_off_in_target = 0x0004DDB4 185 | #2.需要在Debugger->Tracing->Tracing option 关闭Trace over debugger segments,并在这个页面输入Trace File路径 186 | #脚本会在开始和结束下断点,点击continue运行.开始trace,命中结束断点trace自动结束,trace结果保存在设置的Trace File路径中 187 | 188 | unhook() 189 | skip_functions = [] 190 | modules_info = [] 191 | start_ea = 0 192 | end_ea = [] 193 | so_modules = [target1] 194 | for module in idc._get_modules(): 195 | module_name = os.path.basename(module.name) 196 | # print("enum: %s" % module_name) 197 | for so_module in so_modules: 198 | if re.search(so_module, module_name, re.IGNORECASE): 199 | print("modules_info append %08X %s %08X" % (module.base, module.name, module.size)) 200 | if module_name == target1: 201 | # module.size = 98304 202 | modules_info.append({"base": module.base, "size": module.size, "name": module.name}) 203 | start_ea = (module.base + start_off_in_target) #encode_func_2 204 | end_ea = [((module.base + end_off_in_target))] 205 | break 206 | # 207 | # 208 | # 209 | # 210 | 211 | if start_ea: # start address 212 | set_breakpoint(start_ea) 213 | if end_ea: # end address 214 | for ea in end_ea: 215 | set_breakpoint(ea) 216 | 217 | if skip_functions: 218 | print("skip_functions") 219 | for skip_function in skip_functions: 220 | print ("%08X" % skip_function) 221 | 222 | debughook = MyDbgHook(modules_info, skip_functions, start_ea, end_ea) 223 | idaapi.jumpto(start_ea) 224 | starthook() 225 | pass 226 | 227 | 228 | if __name__ == "__main__": 229 | main() 230 | pass -------------------------------------------------------------------------------- /plugin/my_continue.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import idautils 3 | import idaapi 4 | import idc 5 | import ida_dbg 6 | #alias of continue except hotkey because of hhkb layout 7 | 8 | class MyContinue(idaapi.plugin_t): 9 | flags=0 #插件类别 或者特性 10 | wanted_name="my continue" #展示名称 11 | wanted_hotkey="9" #其快捷键 12 | comment="my continue" #插件描述 13 | help="Something helpful" #帮助信息 14 | 15 | def init(self): 16 | return idaapi.PLUGIN_OK 17 | 18 | #插件退出时要做的操作,比如说你打开了某个文件,要到插件结束时才能关闭, 19 | #这里就给你这个机会 20 | def term(self): 21 | pass 22 | 23 | #按快捷键等 插件运行时 的地方 24 | def run(self,arg): 25 | if (not ida_dbg.is_debugger_on()): 26 | print("[my continue] should run in debug mode.") 27 | return 28 | ida_dbg.continue_process() 29 | # 30 | #插件入口 31 | def PLUGIN_ENTRY(): 32 | return MyContinue() 33 | # -------------------------------------------------------------------------------- /plugin/mystep_into.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import idautils 3 | import idaapi 4 | import idc 5 | import ida_dbg 6 | #alias of step into except hotkey because of hhkb layout 7 | 8 | class MyStepInto(idaapi.plugin_t): 9 | flags=0 #插件类别 或者特性 10 | wanted_name="my step into" #展示名称 11 | wanted_hotkey="7" #其快捷键 12 | comment="my step into" #插件描述 13 | help="Something helpful" #帮助信息 14 | 15 | def init(self): 16 | return idaapi.PLUGIN_OK 17 | 18 | #插件退出时要做的操作,比如说你打开了某个文件,要到插件结束时才能关闭, 19 | #这里就给你这个机会 20 | def term(self): 21 | pass 22 | 23 | #按快捷键等 插件运行时 的地方 24 | def run(self,arg): 25 | if (not ida_dbg.is_debugger_on()): 26 | print("[my step into] should run in debug mode.") 27 | return 28 | ida_dbg.step_into() 29 | # 30 | #插件入口 31 | def PLUGIN_ENTRY(): 32 | return MyStepInto() 33 | # -------------------------------------------------------------------------------- /plugin/mystep_over.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import idautils 3 | import idaapi 4 | import idc 5 | import ida_dbg 6 | #alias of step over except hotkey because of hhkb layout 7 | 8 | class MyStepOver(idaapi.plugin_t): 9 | flags=0 #插件类别 或者特性 10 | wanted_name="my step over" #展示名称 11 | wanted_hotkey="8" #其快捷键 12 | comment="my step over" #插件描述 13 | help="Something helpful" #帮助信息 14 | 15 | def init(self): 16 | return idaapi.PLUGIN_OK 17 | 18 | #插件退出时要做的操作,比如说你打开了某个文件,要到插件结束时才能关闭, 19 | #这里就给你这个机会 20 | def term(self): 21 | pass 22 | 23 | #按快捷键等 插件运行时 的地方 24 | def run(self,arg): 25 | if (not ida_dbg.is_debugger_on()): 26 | print("[my step over] should run in debug mode.") 27 | return 28 | ida_dbg.step_over() 29 | # 30 | #插件入口 31 | def PLUGIN_ENTRY(): 32 | return MyStepOver() 33 | # -------------------------------------------------------------------------------- /plugin/step2jump.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import idautils 3 | import idaapi 4 | import idc 5 | import ida_dbg 6 | 7 | def my_get_reg_value(register): 8 | rv = ida_idd.regval_t() 9 | ida_dbg.get_reg_val(register, rv) 10 | regval = rv.ival 11 | return regval 12 | 13 | def is_modify_pc(addr): 14 | opnd = GetOpnd(addr, 0) 15 | if (opnd == "PC"): 16 | return True 17 | mnem = GetMnem(addr) 18 | if (mnem.startswith("POP") or mnem.startswith("LDMFD")): 19 | i = 0 20 | while True: 21 | opnd = GetOpnd(addr, i) 22 | 23 | if (opnd == ""): 24 | return False 25 | elif (opnd.find("PC") >-1): 26 | return True 27 | # 28 | i = i + 1 29 | # 30 | # 31 | return False 32 | # 33 | 34 | def is_jump(addr): 35 | mnem = GetMnem(addr) 36 | if (mnem.startswith("B") and mnem not in ("BFC", "BFI", "BIC") or mnem.startswith("IT") or mnem.startswith("CB") or mnem.startswith("TBB")): 37 | return True 38 | # 39 | elif (is_modify_pc(addr)): 40 | return True 41 | # 42 | return False 43 | # 44 | 45 | #runto to jump instruction when debugging 46 | class Step2Jump(idaapi.plugin_t): 47 | flags=0 #插件类别 或者特性 48 | wanted_name="step to jump" #展示名称 49 | wanted_hotkey="6" #其快捷键 50 | comment="debug step to jump" #插件描述 51 | help="Something helpful" #帮助信息 52 | 53 | #初始化时运行的,可以判断是否要启用这个插件,比如你这个插件主要是针对x86的, 54 | #那你就要判断当前分析的是不是x86,然后在决定是否要显示或者启用这个插件 55 | def init(self): 56 | return idaapi.PLUGIN_OK 57 | 58 | #插件退出时要做的操作,比如说你打开了某个文件,要到插件结束时才能关闭, 59 | #这里就给你这个机会 60 | def term(self): 61 | pass 62 | 63 | #按快捷键等 插件运行时 的地方 64 | def run(self,arg): 65 | if (not ida_dbg.is_debugger_on()): 66 | print("[step to jump] should run in debug mode.") 67 | else: 68 | curentEA = my_get_reg_value("PC") 69 | if (is_jump(curentEA)): 70 | #当前是一个jump或者函数调用,直接做一个step_over 71 | ida_dbg.step_over() 72 | # 73 | else: 74 | addr = idc.next_head(curentEA) 75 | while addr != idc.BADADDR: 76 | if (not idaapi.isCode(idaapi.getFlags(addr))): 77 | line = "next_addr Find 0x%08x is not code addr, can not do anything"%addr 78 | print(line) 79 | break 80 | # 81 | if (is_jump(addr)): 82 | ida_dbg.run_to(addr) 83 | print("run to jump") 84 | break 85 | # 86 | addr = idc.next_head(addr) 87 | # 88 | # 89 | #两个dbg事件之间要加上这句话才两个都生效 90 | #ida_dbg.wait_for_next_event(ida_dbg.WFNE_SUSP, -1) 91 | # 92 | #插件入口 93 | def PLUGIN_ENTRY(): 94 | return Step2Jump() 95 | # -------------------------------------------------------------------------------- /range_set_thumb.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import idc 3 | import os 4 | import ida_idaapi 5 | 6 | if __name__ == "__main__": 7 | start = read_selection_start() 8 | end = read_selection_end() 9 | if start != ida_idaapi.BADADDR: 10 | addr = start 11 | print("set thumb 0x%08x - 0x%08x"%(start, end)) 12 | while addr != idc.BADADDR and addr < end: 13 | #改tf寄存器成1 14 | idc.split_sreg_range(addr, "T", 1, SR_user) 15 | addr = idc.next_head(addr) 16 | # 17 | else: 18 | print("start is BADADDR please select a range") 19 | -------------------------------------------------------------------------------- /trace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | import os 6 | import os.path 7 | from idaapi import * 8 | import idc 9 | from idc import * 10 | 11 | 12 | class Tracer(DBG_Hooks): 13 | def __init__(self, output_path): 14 | DBG_Hooks.__init__(self) 15 | self.__output_path = output_path 16 | self.__output = None 17 | self.__ea_prev = 0 18 | # 19 | 20 | def dbg_process_attach(self, pid, tid, ea, name, base, size): 21 | print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size)) 22 | self.__output = open(self.__output_path, "w") 23 | # 24 | 25 | def dbg_bpt(self, tid, ea): 26 | if (ea == self.__ea_prev): 27 | #不知道为何ida大多数指令会这个回调会调用两次 28 | return 0 29 | # 30 | self.__ea_prev = ea 31 | base = int(get_imagebase()) 32 | addr = int(ea) 33 | #print ("Break point at 0x%x pid=%d" % (ea, tid)) 34 | name = idc.get_root_filename() 35 | disasm_str = GetDisasm(ea) 36 | 37 | buf = idc.GetManyBytes(ea, ItemSize(ea)) 38 | 39 | instruction_str = ''.join('{:02X} '.format(ord(x)) for x in buf) 40 | line = "(%20s[0x%08X])[%-12s]0x%08X:\t%s"%(name, base, instruction_str, addr-base, disasm_str) 41 | print(line) 42 | self.__output.write(line+"\n") 43 | # return values: 44 | # -1 - to display a breakpoint warning dialog 45 | # if the process is suspended. 46 | # 0 - to never display a breakpoint warning dialog. 47 | # 1 - to always display a breakpoint warning dialog. 48 | return 0 49 | # 50 | 51 | def dbg_library_load(self, pid, tid, ea, name, base, size): 52 | print ("Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base)) 53 | # 54 | 55 | def dbg_suspend_process(self): 56 | pass 57 | #print "Process suspended" 58 | # 59 | 60 | def dbg_process_exit(self, pid, tid, ea, code): 61 | print("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code)) 62 | if (self.__output != None): 63 | self.__output.close() 64 | # 65 | # 66 | 67 | # 68 | 69 | 70 | # Remove an existing debug hook 71 | try: 72 | if debughook: 73 | print("Removing previous hook ...") 74 | debughook.unhook() 75 | # 76 | # 77 | except: 78 | pass 79 | # 80 | 81 | funName = idc.AskStr("JNI_OnLoad", "function name") 82 | funAddr = LocByName(funName) 83 | if funAddr == BADADDR: 84 | print("funName %s not found"%funName) 85 | raise RuntimeError("funName %s not found"%funName) 86 | # 87 | 88 | funEndAddr = FindFuncEnd(funAddr) 89 | 90 | if funAddr == BADADDR: 91 | raise RuntimeError("funName %s end not found"%funName) 92 | # 93 | 94 | for ea in Heads(funAddr, funEndAddr): 95 | AddBpt(ea) 96 | SetBptAttr(ea, BPTATTR_FLAGS, BPT_ENABLED|BPT_TRACE) 97 | # 98 | 99 | 100 | script_path = os.path.split(os.path.realpath(__file__))[0] 101 | name = os.path.splitext(idc.get_root_filename())[0] 102 | trace_path = "%s/trace-%s.txt"%(script_path, name) 103 | 104 | 105 | # Install the debug hook 106 | debughook = Tracer(trace_path) 107 | debughook.hook() 108 | debughook.steps = 0 109 | print ("script run...") 110 | 111 | --------------------------------------------------------------------------------