def get_mem_string(cls, addr): """ 获取内存中的字符串 """ addr_t = addr dref = idautils.DataRefsFrom(addr_t) strs = [cls.strings[x] for x in dref if x in cls.strings] # 处理几种特殊情况 # LDR R1, =sub_xxxx # LDR R1, =loc_xxxx if idc.print_operand(addr, 1)[:5] in ['=sub_', '=loc_']: return [] # LDR R1, =unk_53B4B6 # .rodata:0053B4B6 http: # .rodata:0053B4BB //%s%s if strs != [] and strs[0].find('%') == -1: strs = [] dref = idautils.DataRefsFrom(addr_t) for x in dref: segname = ida_segment.get_segm_name(ida_segment.getseg(x)) if segname not in ['.text', '.bss']: strs.append(cls.get_string_from_mem(x)) # LDR R1, =(aFailedToGetAnI+0x22) # LDR R2, =(aSS - 0xCFA4) # ADD R2, PC, R2 if strs == []: dref = idautils.DataRefsFrom(addr_t) for x in dref: segname = ida_segment.get_segm_name(ida_segment.getseg(x)) if segname not in ['.text', '.bss']: strs.append(cls.get_string_from_mem(x)) elif len(list(idautils.DataRefsFrom(x))) == 0: reg_t = idc.print_operand(addr_t, 0) num1 = ida_bytes.get_wide_dword(x) while get_mnem(addr_t) != 'ADD' or (idc.print_operand(addr_t, 0) != reg_t and idc.print_operand(addr_t, 1) != 'PC'): addr_t = ida_bytes.next_head(addr_t, ida_idaapi.BADADDR) num2 = addr_t + 8 addr_t = num1 + num2 strs.append(cls.get_string_from_mem(addr_t)) # MOVW R1, #0x87B4 # MOVT.W R1, #0x52 if strs == [] and get_mnem(addr_t) == 'MOVW': reg_t = idc.print_operand(addr_t, 0) num1 = int(idc.print_operand(addr_t, 1).split('#')[1], 16) while get_mnem(addr_t) not in ['MOVTGT', 'MOVTLE', 'MOVT'] or idc.print_operand(addr_t, 0) != reg_t: addr_t = ida_bytes.next_head(addr_t, ida_idaapi.BADADDR) num2 = int(idc.print_operand(addr_t, 1).split('#')[1], 16) addr_t = (num2<<16) + num1 strs.append(cls.get_string_from_mem(addr_t)) return strs
def main(): for segstart, segend, segname in enum_segments(): for head in idautils.Heads(segstart, segend): if not is_code(head): continue # pattern: # # lea rax, unk_6BDF88 # mov [rsp+0], rax # mov qword ptr [rsp+8], 40h if ida_ua.ua_mnem(head) != "lea": continue next_head = ida_bytes.next_head(head, idc.BADADDR) if ida_ua.ua_mnem(next_head) != "mov": continue next_head2 = ida_bytes.next_head(next_head, idc.BADADDR) if ida_ua.ua_mnem(next_head2) != "mov": continue dst = idc.get_operand_value(head, 1) if idc.get_segm_name(dst) not in (".rdata", "UPX1"): continue size = idc.get_operand_value(next_head2, 1) if size > 0x100: continue if size <= 2: continue buf = ida_bytes.get_bytes(dst, size) if not buf: continue if b"\x00" in buf: continue try: s = buf.decode("ascii") except UnicodeDecodeError: continue print("string pointer: 0x%x -> 0x%x: %s" % (head, dst, s)) ida_bytes.del_items(dst, 1) ida_bytes.create_data(dst, idc.FF_BYTE, 1, idc.BADADDR) ida_bytes.set_cmt(dst, s, True) ida_name.set_name(dst, "s_%x" % (dst))
def btn_add_next_inst_bpt(self, code=0): """ 给所有断点的下一条指令下断点 """ bpt_list = self.get_all_bpt_list() for bpt in bpt_list: ida_dbg.add_bpt(ida_bytes.next_head(bpt, ida_idaapi.BADADDR), 0, idc.BPT_DEFAULT)
def main(): is_selected, sel_start, sel_end = ida_kernwin.read_selection() if not is_selected: logger.error('range must be selected') return -1 sel_end = ida_bytes.next_head(sel_end) buf = ida_bytes.get_bytes(sel_start, sel_end - sel_start) if buf is None: logger.error('failed to fetch instruction bytes') return -1 f = ida_funcs.get_func(sel_start) if f != ida_funcs.get_func(sel_end): logger.error('range must be within a single function') return -1 # find mappings from "$localN" to "custom_name" regvars = {} for i in range(0x1000): regvar = ida_frame.find_regvar(f, sel_start, '$local%d' % i) if regvar is None: continue regvars[regvar.canon] = regvar.user if len(regvars) >= f.regvarqty: break globals_ = {} for i, offset in netnode.Netnode('$ wasm.offsets').get('globals', {}).items(): globals_['$global' + i] = ida_name.get_name(offset) frame = {} if f.frame != ida_idaapi.BADADDR: names = set([]) for i in range(ida_struct.get_struc_size(f.frame)): s = ida_struct.get_struc(f.frame) if not s: continue m = ida_struct.get_member(s, i) if not m: continue name = ida_struct.get_member_name(m.id) if name in names: continue frame[i] = name names.add(name) emu = Emulator(buf) emu.run() print( emu.render(ctx={ 'regvars': regvars, 'frame': frame, 'globals': globals_, }))
def Heads(start=None, end=None): """ Get a list of heads (instructions or data) @param start: start address (default: inf.min_ea) @param end: end address (default: inf.max_ea) @return: list of heads between start and end """ if not start: start = ida_ida.cvar.inf.min_ea if not end: end = ida_ida.cvar.inf.max_ea ea = start if not idc.is_head(ida_bytes.get_flags(ea)): ea = ida_bytes.next_head(ea, end) while ea != ida_idaapi.BADADDR: yield ea ea = ida_bytes.next_head(ea, end)
def get_disasm(self, start_address, end_address) -> list: result = [] current_start = start_address while current_start < end_address: # https://github.com/idapython/src/blob/master/python/idautils.py#L202 result.append(idc.GetDisasm(current_start)) current_start = ida_bytes.next_head(current_start, ida_ida.cvar.inf.max_ea) return result
def get_disasm(self, start_address, end_address) -> list: result = [] start = int(start_address, 16) end = int(end_address, 16) while start <= end: # https://github.com/idapython/src/blob/master/python/idautils.py#L202 next_start = ida_bytes.next_head(start, ida_ida.cvar.inf.max_ea) result.append(idc.GetDisasm(start)) start = next_start return result
def trace_block(self, blk, node, reg): """ 在一个基本块内回溯 """ reg_t = reg cur_t = node['addr'] while reg_t and cur_t >= blk.start_ea: cur_t, reg_t = self.trace_handle(cur_t, reg_t) return (ida_bytes.next_head(cur_t, ida_idaapi.BADADDR), reg_t)
def get_hex(self, start_address, end_address) -> list: result = [] start = int(start_address, 16) end = int(end_address, 16) while start <= end: # https://github.com/idapython/src/blob/master/python/idautils.py#L202 next_start = ida_bytes.next_head(start, ida_ida.cvar.inf.max_ea) result.append( binascii.hexlify(ida_bytes.get_bytes(start, next_start - start)).decode()) start = next_start return result
def get_string(self, start_address, end_address) -> list: result = [] start = int(start_address, 16) end = int(end_address, 16) while start <= end: # https://github.com/idapython/src/blob/master/python/idautils.py#L202 next_start = ida_bytes.next_head(start, ida_ida.cvar.inf.max_ea) if ida_nalt.get_str_type(start) < 4294967295: result.append( ida_bytes.get_strlit_contents( start, -1, ida_nalt.get_str_type(start)).decode()) start = next_start return result
def get_func_items_from_xref(xref): """ Returns the rest of the instruction from a given xref """ items = list(idautils.FuncItems(xref)) if len(items): idx = items.index(xref)+1 items = items[idx:] else: print " - Xref at 0x{:08x} wasn't marked as a function".format(xref) cur = ida_bytes.next_head(xref, idaapi.cvar.inf.maxEA) while True: if cur not in items: items.append(cur) print "adding 0x{:08x}: ".format(cur, disasm(cur)) inst = idautils.DecodeInstruction(cur) if inst.get_canon_mnem() in ['call', 'jmp', 'retn']: break cur = ida_bytes.next_head(cur, idaapi.cvar.inf.maxEA) return items
def get_string(self, start_address, end_address) -> list: result = [] current_start = start_address while current_start < end_address: if ida_nalt.get_str_type(current_start) < 4294967295: result.append( ida_bytes.get_strlit_contents( current_start, -1, ida_nalt.get_str_type(current_start)).decode()) # https://github.com/idapython/src/blob/master/python/idautils.py#L202 current_start = ida_bytes.next_head(current_start, ida_ida.cvar.inf.max_ea) return result
def enum_function_addrs(fva): ''' yield the effective addresses of each instruction in the given function. these addresses are not guaranteed to be in any order. Args: fva (int): the starting address of a function Returns: sequence[int]: the addresses of each instruction ''' f = idaapi.get_func(fva) if not f: raise ValueError('not a function') for block in idaapi.FlowChart(f): ea = block.start_ea while ea <= block.end_ea: yield ea ea = ida_bytes.next_head(ea, idc.BADADDR)
def jump_next_comment(v): """ Starting at the current line, keep generating lines until a comment is found. When this happens, position the viewer at the right coordinates. """ loc = ida_moves.lochist_entry_t() if ida_kernwin.get_custom_viewer_location(loc, v): place = loc.place() idaplace = ida_kernwin.place_t_as_idaplace_t(place) ea = idaplace.ea while ea != ida_idaapi.BADADDR: _, disass = ida_lines.generate_disassembly( ea, 1000, # maximum number of lines False, # as_stack=False False ) # notags=False - we want tags, in order to spot comments found = None # If this is the start item, start at the next line start_lnnum = (idaplace.lnnum + 1) if ea == idaplace.ea else 0 for rel_lnnum, line in enumerate(disass[start_lnnum:]): vis_cx = find_comment_visual_position_in_tagged_line(line) if vis_cx > -1: found = (ea, rel_lnnum, vis_cx) break if found is not None: idaplace.ea = found[0] idaplace.lnnum = start_lnnum + found[1] loc.set_place(idaplace) loc.renderer_info().pos.cx = found[2] ida_kernwin.custom_viewer_jump(v, loc, ida_kernwin.CVNF_LAZY) break ea = ida_bytes.next_head(ea, ida_idaapi.BADADDR)
def _invent_var_type(ea, seg_ref, min_size=1): """Try to invent a variable type. This will basically be an array of bytes that spans what we need. We will, however, try to be slightly smarter and look for cross-references in the range, and when possible, use their types.""" seg = find_segment_containing_ea(ea, seg_ref) if not seg: return ea, None head_ea = ida_bytes.get_item_head(ea) if head_ea < ea: head_seg = find_segment_containing_ea(head_ea, seg_ref) if head_seg != seg: return ea, None return _invent_var_type(head_ea, seg_ref, ea - head_ea) min_size = max(min_size, ida_bytes.get_item_size(ea)) next_ea = ida_bytes.next_head(ea + 1, seg.end_ea) next_seg = find_segment_containing_ea(next_ea, seg_ref) arr = ArrayType() arr.set_element_type(IntegerType(1, False)) if not next_seg or next_seg != seg: arr.set_num_elements(min_size) return ea, arr min_size = min(min_size, next_ea - ea) # TODO(pag): Go and do a better job, e.g. find pointers inside of the global. # i = 0 # while i < min_size: # for ref_ea in xref_generator(ea + i, seg_ref): # break # i += 1 arr.set_num_elements(min_size) return ea, arr
def dump_heads(out): # out is a file like object, sys.stdout or an acual file object # There doesn't seem to a good way to determine what function a # particular address is in. Almost everyone recommends iterating # of the functions, and then getting the bytes out of each, but # that's not really what we want because it skips non function # bytes and reports them in the wrong order. It appears that the # best we can do is to build a map in advance. :-( a2fmap = build_a2fmap() min_ea = idaapi.cvar.inf.minEA max_ea = idaapi.cvar.inf.maxEA ea = min_ea while ea != ida_idaapi.BADADDR: ida_auto.show_addr(ea) isize = ida_bytes.get_item_size(ea) ibytes = ida_bytes.get_bytes(ea, isize) ihexbytes = binascii.b2a_hex(ibytes).upper() iflags = ida_bytes.get_flags(ea) # Skip the PE header? if not ida_bytes.is_head(iflags): ea = ida_bytes.next_head(ea, max_ea) continue # Loop up this address in the address-to-function map. if ea in a2fmap: faddrs = a2fmap[ea] else: faddrs = [ea] tcode = "ERROR" imnem = "???" iops = "???" if ida_bytes.is_code(iflags): tcode = "INSN" imnem = "???" iops = "???" insn = idautils.DecodeInstruction(ea) if insn == None: imnem = "BAD" iops = "" elif not insn.is_canon_insn(): imnem = "NCAN" iops = "" else: imnem = insn.get_canon_mnem() sops = [] for n in range(8): ostr = ida_ua.print_operand(ea, n) if ostr is not None: ostrnt = ida_lines.tag_remove(ostr) if ostrnt != '': sops.append(ostrnt) iops = ', '.join(sops) elif ida_bytes.is_data(iflags): tcode = "DATA" imnem = "db" iops = "???" if ida_bytes.is_align(iflags): tcode += "_ALIGN" #elif ida_bytes.is_struct(iflags): # tcode += "_STRUCT" #elif ida_bytes.is_char(iflags): # tcode += "_STR" # There are other types that IDA recognizes. elif ida_bytes.is_unknown(iflags): tcode = "UNK-%08X" % iflags imnem = "???" iops = "???" for faddr in sorted(faddrs): out.write('"PART",0x%08X,"%s",0x%08X,"%s","%s","%s"\n' % (ea, tcode, faddr, ihexbytes, imnem, iops)) ea = ida_bytes.next_head(ea, max_ea) print "Analysis complete!"
def activate(self, ctx): selection = idaapi.read_selection() if not selection[0]: return 0 start = selection[1] - 1 stop = selection[2] + 1 print('Parsing selection between %X -> %X' % (start, stop)) prefix = ida_kernwin.ask_str('', 0, 'Prefix') if prefix is not None: prefix = prefix.replace('/', '::') while True: name_address = ida_bytes.next_head(start, stop) if name_address == idaapi.BADADDR: break name_offset = ida_bytes.get_dword(name_address) name = ida_bytes.get_strlit_contents(name_offset, -1, 0) if prefix is not None: name = prefix + '::' + name signature_address = ida_bytes.next_head(name_address, stop) if signature_address == idaapi.BADADDR: break signature_offset = ida_bytes.get_dword(signature_address) signature = ida_bytes.get_strlit_contents(signature_offset, -1, 0) function_address = ida_bytes.next_head(signature_address, stop) if function_address == idaapi.BADADDR: break function_offset = ida_bytes.get_dword(function_address) if function_offset % 2 != 0: function_offset -= 1 try: c_signature = JNINativeMethodSignature(name, signature).c except JNINativeMethodError: break start = function_address parsed_decl = ida_typeinf.idc_parse_decl(None, c_signature, ida_typeinf.PT_SIL) if parsed_decl is None: return 0 ida_typeinf.apply_type(None, parsed_decl[1], parsed_decl[2], function_offset, 1) ida_name.set_name(function_offset, name, ida_name.SN_FORCE) return 1
def __init__(self): ida_kernwin.UI_Hooks.__init__(self) # We'll color all lines starting with the current # one, with all available highlights... self.instantiated_at = ida_kernwin.get_screen_ea() self.color_info = [] data = [ ida_kernwin.CK_EXTRA1, ida_kernwin.CK_EXTRA2, ida_kernwin.CK_EXTRA3, ida_kernwin.CK_EXTRA4, ida_kernwin.CK_EXTRA5, ida_kernwin.CK_EXTRA6, ida_kernwin.CK_EXTRA7, ida_kernwin.CK_EXTRA8, ida_kernwin.CK_EXTRA9, ida_kernwin.CK_EXTRA10, ida_kernwin.CK_EXTRA11, ida_kernwin.CK_EXTRA12, ida_kernwin.CK_EXTRA13, ida_kernwin.CK_EXTRA14, ida_kernwin.CK_EXTRA15, ida_kernwin.CK_EXTRA16, # let's also try these colors keys, because why not ida_kernwin.CK_TRACE, ida_kernwin.CK_TRACE_OVL, [ ida_kernwin.CK_TRACE, ida_kernwin.CK_TRACE_OVL, ], ] ea = self.instantiated_at for one in data: self.color_info.append((ea, one)) ea = ida_bytes.next_head(ea, ida_idaapi.BADADDR) # ...and then we'll a few more things, such as # overriding parts of a previously-specified overlay, # and restricting the override to a few glyphs self.color_info.append((self.color_info[6][0], [ (ida_kernwin.CK_EXTRA2, 7, 3), (ida_kernwin.CK_EXTRA4, 2, 1), (ida_kernwin.CK_EXTRA10, 2, 0), (ida_kernwin.CK_EXTRA10, 20, 10), ])) self.color_info.append((self.color_info[7][0], [ (ida_kernwin.CK_EXTRA1, 1, 1), (ida_kernwin.CK_EXTRA2, 3, 1), (ida_kernwin.CK_EXTRA3, 5, 1), (ida_kernwin.CK_EXTRA4, 7, 1), (ida_kernwin.CK_EXTRA5, 9, 1), (ida_kernwin.CK_EXTRA6, 11, 1), (ida_kernwin.CK_EXTRA7, 13, 1), (ida_kernwin.CK_EXTRA8, 15, 1), (ida_kernwin.CK_EXTRA9, 17, 1), (ida_kernwin.CK_EXTRA10, 19, 1), (ida_kernwin.CK_EXTRA11, 21, 1), (ida_kernwin.CK_EXTRA12, 23, 1), (ida_kernwin.CK_EXTRA13, 25, 1), (ida_kernwin.CK_EXTRA14, 27, 1), (ida_kernwin.CK_EXTRA15, 29, 1), (ida_kernwin.CK_EXTRA16, 31, 1), ])) self.color_info.append((self.color_info[8][0], [ (ida_kernwin.CK_EXTRA1, 16, 45), (ida_kernwin.CK_EXTRA2, 19, 45), (ida_kernwin.CK_EXTRA3, 22, 45), (ida_kernwin.CK_EXTRA4, 25, 45), ]))