def __init__(self, ea): self.ea = ea self.funcname_or_segname = "" self.text = "" if not ida_bytes.is_code(ida_bytes.get_flags(ea)): ida_ua.create_insn(ea) # text t = ida_lines.generate_disasm_line(ea) if t: self.text = ida_lines.tag_remove(t) # funcname_or_segname n = ida_funcs.get_func_name(ea) \ or ida_segment.get_segm_name(ida_segment.getseg(ea)) if n: self.funcname_or_segname = n
def main(): # Get current ea ea = ida_kernwin.get_screen_ea() # Get segment class seg = ida_segment.getseg(ea) # Loop from segment start to end func_ea = seg.start_ea # Get a function at the start of the segment (if any) func = ida_funcs.get_func(func_ea) if func is None: # No function there, try to get the next one func = ida_funcs.get_next_func(func_ea) seg_end = seg.end_ea while func is not None and func.start_ea < seg_end: funcea = func.start_ea print("Function %s at 0x%x" % (ida_funcs.get_func_name(funcea), funcea)) ref = ida_xref.get_first_cref_to(funcea) while ref != ida_idaapi.BADADDR: print(" called from %s(0x%x)" % (ida_funcs.get_func_name(ref), ref)) ref = ida_xref.get_next_cref_to(funcea, ref) func = ida_funcs.get_next_func(funcea)
def __get_relative_node(self, src_node, key_name): src_node_addr = src_node.get_addr() next_node_addr = ida_xref.get_first_cref_to(src_node_addr) print('[Debug]next_addr 0x%x' % next_node_addr) if next_node_addr == idaapi.BADADDR: return if next_node_addr != idc.PrevHead(src_node_addr): new_tree_node = TreeNode(ida_funcs.get_func_name(next_node_addr), next_node_addr) new_tree_node.add_parent(src_node) src_node.add_child(new_tree_node) print('[*]Add node %s 0x%x' % (new_tree_node.get_name(), new_tree_node.get_addr())) self.__get_relative_node(new_tree_node, key_name) next_node_addr = ida_xref.get_next_cref_to(src_node_addr, next_node_addr) print('[Debug]next_addr 0x%x' % next_node_addr) while next_node_addr != idaapi.BADADDR: if next_node_addr == idc.PrevHead(src_node_addr): continue new_tree_node = TreeNode(ida_funcs.get_func_name(next_node_addr), next_node_addr) new_tree_node.add_parent(src_node) src_node.add_child(new_tree_node) print('[*]Add node %s 0x%x' % (new_tree_node.get_name(), new_tree_node.get_addr())) self.__get_relative_node(new_tree_node, key_name) next_node_addr = ida_xref.get_next_cref_to(src_node_addr, next_node_addr) print('[Debug]next_addr 0x%x' % next_node_addr) return
def gen_sink_func_addr(self): for func_addr in idautils.Functions(): func_name = ida_funcs.get_func_name(func_addr) if func_name in self.sink_func_info: yield (func_name, func_addr) else: continue
def btn_func_xref_count(self, code=0): """ 函数调用次数统计 """ xref_count_dict = OrderedDict() for func_addr_t in idautils.Functions(): count = len(list(idautils.CodeRefsTo(func_addr_t, 0))) xref_count_dict[ida_funcs.get_func_name(func_addr_t)] = [ func_addr_t, count ] ordered_list = sorted(list(xref_count_dict.items()), key=lambda x: x[1][1], reverse=True) cols = [['', 0 | ida_kernwin.Choose.CHCOL_DEC], ['函数名', 15 | ida_kernwin.Choose.CHCOL_PLAIN], ['地址', 10 | ida_kernwin.Choose.CHCOL_HEX], ['次数', 10 | ida_kernwin.Choose.CHCOL_PLAIN]] items = [] for x in ordered_list: data = AnalysisChooseData(vuln=0, name=x[0], ea=x[1][0], other1=str(x[1][1])) items.append(data) chooser = AnalysisChooser(title='函数调用次数统计', cols=cols, item=items) chooser.Show()
def visit_expr(self, e): if e.op != ida_hexrays.cot_call: return 0 func = e.x args = e.a if func.op != ida_hexrays.cot_obj: return 0 name = ida_funcs.get_func_name(func.obj_ea) if name not in self.targets: return 0 idxs = self.targets[name] if not isinstance(idxs, tuple): idxs = (idxs,) name = [] for idx in idxs: if idx >= len(args): return 0 arg = args[idx].obj_ea if not is_str_literal(arg): return 0 name.append(get_str_literal(arg)) if name: self.results.append('_'.join(name)) return 0
def get_func_names(): names = [] for ea in idautils.Functions(): name = ida_funcs.get_func_name(ea) if not name.startswith("sub_"): names.append(name) return names
def make_name(): callz = du.find_all_calls_to(f_name='log_info') for co in callz: # The *second* argument of ``GetProcAddress`` is the API name print("====") try: if co.args[2].type == 'string': api_name = co.args[2].val else: continue except: continue # double check :) # if not du.is_asg(co.node): # continue if ' ' in api_name: continue if '\/' in api_name: continue new_name = "func_{}".format(api_name) func = idc.get_func_attr(co.ea, FUNCATTR_START) if 'sub_' not in ida_funcs.get_func_name(func): continue print("====") print(hex(func)) print(new_name) idc.set_name(func, new_name, SN_CHECK)
def main(): """ for each function in .text segment, we extract name, start_ea, end_ea, code, size attributes from IDA """ results = {} start = time.time() funcs = get_funcs() text_segm = ida_segment.get_segm_by_name(".text") for func in funcs: # we only care about functions in .text segment if not in_range(text_segm, func.start_ea): continue name = ida_funcs.get_func_name(func.start_ea) code = ida_hexrays.decompile_func(func, None) results[name] = { "name": name, "start_ea": func.start_ea, "end_ea": func.end_ea, "code": code.__str__(), "size": func.size() } print("JSON:") print(json.dumps({"time": time.time() - start, "data": results}))
def GetCanonicalName(f): n = ida_funcs.get_func_name(f) parts = n.split("_") if len(parts) == 3: return parts[1] else: return None
def RenameMod(orig, new): i = ida_funcs.get_next_func(0) while (i != ida_idaapi.BADADDR): n = ida_funcs.get_func_name(i) if n.startswith(orig+"_"): RenameFuncWithNewMod(i,new) i = NextFunction(i)
def __repr__(self): try: func_name = get_func_name(self.func_t.start_ea) except: func_name = "<unknown>" return "<Func at 0x{:X}, name: {}>".format(self.func_t.start_ea, func_name)
def get_one_func_xref(self, func_name): for func_addr in idautils.Functions(): func_name_t = ida_funcs.get_func_name(func_addr) if func_name == func_name_t: return self.get_func_xref(func_addr) else: continue
def getFunctionSymbols(self): function_symbols = {} function_offsets = self.getFunctions() for function_offset in function_offsets: function_name = ida_funcs.get_func_name(function_offset) if not re.match("sub_[0-9a-fA-F]+", function_name): function_symbols[function_offset] = function_name return function_symbols
def name(self): ea = self.address() try: flags = ida_bytes.get_full_flags(ea) if ida_bytes.has_name(flags): return ida_funcs.get_func_name(ea) except: pass return ""
def main(): # Get current ea ea = ida_kernwin.get_screen_ea() if ea == ida_idaapi.BADADDR: print("Could not get get_screen_ea()") return seg = ida_segment.getseg(ea) if seg: # Loop from start to end in the current segment for funcea in idautils.Functions(seg.start_ea, seg.end_ea): print("Function %s at 0x%x" % (ida_funcs.get_func_name(funcea), funcea)) # Find all code references to funcea for ref in idautils.CodeRefsTo(funcea, 1): print(" called from %s(0x%x)" % (ida_funcs.get_func_name(ref), ref)) else: print("Please position the cursor within a segment")
def on_get_annotations(self, address, size, mouse_offs): annotations = [] sp = get_sp_val() ip = get_ip_val() fi = FrameInfo() if sp and ip: arrow = sp if self.sp_arrow else None frame_start_ea = fi.ea funcname = get_func_name(ip) annotations.append((None, None, "", None)) annotations.append((arrow, self.palette[4], "[Stack Pointer]", self.palette[1])) annotations.append((None, None, " address: 0x%x" % (sp), self.palette[3])) sp_boundaries = fi.get_element_boundaries(sp) if sp_boundaries and len(fi.members): start, end = sp_boundaries name, offs, msize, foffs = fi.members[start] annotations.append((None, None, " points to: %s" % (name), self.palette[3])) annotations.append((None, None, "", None)) annotations.append((None, None, "[Function]", self.palette[1])) annotations.append((None, None, " name: %s" % (funcname), self.palette[3])) annotations.append((None, None, " frame addr: 0x%x" % (frame_start_ea), self.palette[3])) if mouse_offs and len(fi.members): mouse_boundaries = fi.get_element_boundaries(address+mouse_offs) if mouse_boundaries: start, end = mouse_boundaries name, offs, msize, foffs = fi.members[start] # "dist" is the distance from current variable to # end of stack frame this is where a return address # may be stored depending on the CPU architecture dist = foffs-offs # address of frame member in memory var_addr = frame_start_ea+offs # add annotations annotations.append((None, None, "", None)) annotations.append((None, None, "[Frame Member]", self.palette[1])) annotations.append((None, None, " name: %s" % (name), self.palette[3])) annotations.append((None, None, " addr: 0x%x" % (var_addr), self.palette[3])) annotations.append((None, None, " offs: Frame+0x%x" % (offs), self.palette[3])) annotations.append((None, None, " size: 0x%x" % (msize), self.palette[3])) annotations.append((None, None, " distance: %s0x%x" % ("-" if dist < 0 else "", abs(dist)), self.palette[3])) annotations.append((None, None, " cursor: %s+0x%x" % (name, address + mouse_offs - (frame_start_ea+offs)), self.palette[3])) else: annotations.append((None, None, "Debugger inactive", self.palette[4])) return annotations
def CompileFuncNamesFromRangeAsText(start,end,sep): x = start s = "" while (x<=end): n = ida_funcs.get_func_name(x) if (not n.startswith("sub_")): s += " " + sep + " " + n x = NextFunction(x) return s
def RenameRangeWithAddr(start,end,s): x = start while (x<=end): n = ida_funcs.get_func_name(x) if (n.startswith("sub_")): RenameFuncWithAddr(x,s) else: NameCanonical(x,s,n) x = NextFunction(x)
def PrefixRange(start, end, prefix) : x = start while x < end: n = ida_funcs.get_func_name(x) if n.startswith("sub_"): nn = prefix + n print "Renaming %s to %s\n" % (n, nn) ida_name.set_name(x,nn) x = NextFunction(x)
def _function_name(ea): """Try to get the name of a function.""" try: flags = ida_bytes.get_full_flags(ea) if ida_bytes.has_name(flags): return ida_funcs.get_func_name(ea) except: pass return "sub_{:x}".format(ea)
def get_tooltip(self, addr, mouse_offs): tooltip = '%X: ' % (addr + mouse_offs) if self.switch == 0: tooltip += '%s' % get_name(get_item_head(addr + mouse_offs)) else: f = get_func(addr + mouse_offs) if f: tooltip += '%s' % get_func_name(f.startEA) return tooltip
def color_blocks(fn, pc, size): fn_start = fn.start_ea fn_name = ida_funcs.get_func_name(fn_start) if ("COVERED_" not in fn_name): ida_name.set_name(fn_start, "COVERED_" + fn_name, ida_name.SN_CHECK) fn.color = FUNC_COLOR # PANDA blocks may be shorter than IDA blocks # so use the size to color just what PANDA executed i = 0 while ((pc + i) < (pc + size)): ida_nalt.set_item_color(pc + i, INST_COLOR) i = i + 1
def __init__(self, caller, sp): self.caller = caller self.sp = sp f = ida_funcs.get_func(caller) self.displ = "%08x: " % caller if f: self.displ += ida_funcs.get_func_name(caller) t = caller - f.start_ea if t > 0: self.displ += "+" + hex(t) else: self.displ += hex(caller) self.displ += " [" + hex(sp) + "]"
def add_tmp_func(self, info_only=False): """ 添加临时sink函数 info_only: 在添加函数信息的同时是否添加断点 """ input_str = ida_kernwin.ask_text( 0, '', "请输入任意函数名/函数地址,及各参数类型(none, int, str),可输入多行\n例如:\nstrcmp str str") try: rules = [x.strip() for x in input_str.strip().split('\n')] for rule in rules: tgt_t = rule.split(' ')[0].strip() args_rule = [x.strip() for x in rule.split(' ')[1:]] if not tgt_t in self.tmp_func_dict: if tgt_t.startswith('0x'): addr_t = int(tgt_t, 16) addr_hexstr = hexstr(addr_t) CUSTOM_FUNC[addr_hexstr] = {'args_rule': args_rule} self.tmp_func_dict[addr_hexstr] = [addr_t] if info_only == False: ida_dbg.add_bpt(addr_t, 0, idc.BPT_DEFAULT) else: for func_addr_t in idautils.Functions(): func_name_t = ida_funcs.get_func_name(func_addr_t) if func_name_t == tgt_t: CUSTOM_FUNC[func_name_t] = { 'args_rule': args_rule } self.tmp_func_dict[func_name_t] = [] for xref_addr_t in idautils.CodeRefsTo( func_addr_t, 0): self.tmp_func_dict[func_name_t].append( xref_addr_t) if info_only == False: ida_dbg.add_bpt( xref_addr_t, 0, idc.BPT_DEFAULT) else: continue break else: continue else: CUSTOM_FUNC[tgt_t] = {'args_rule': args_rule} for xref_addr_t in self.tmp_func_dict[tgt_t]: if info_only == False: ida_dbg.add_bpt(xref_addr_t, 0, idc.BPT_DEFAULT) else: continue FELogger.info("已添加断点:%s" % rule) except Exception as e: FELogger.info("输入信息有误:%s" % e)
def __init__(self, caller, sp): self.caller = caller self.sp = sp f = ida_funcs.get_func(caller) self.displ = "%08x: " % caller if f: self.displ += ida_funcs.get_func_name(caller) t = caller - f.start_ea if t > 0: self.displ += "+" + hex(t) else: self.displ += hex(caller) self.displ += " [" + hex(sp) + "]"
def _init_func_thunk_ctrl_flow(self): """Initializes the control flow redirections and targets using function thunks""" # We only support the ELF format for now inf = ida_idaapi.get_inf_structure() if inf.filetype != ida_ida.f_ELF: return # List the function thunks first input_file_path = ida_nalt.get_input_file_path() image_parser = create_elf_image_parser(input_file_path) function_thunk_list = image_parser.get_function_thunk_list() # Go through each function thunk, and look at its cross references; there # should always be only one user, which is the wrapper around the imported # function is_32_bit = image_parser.get_image_bitness() == 32 for function_thunk in function_thunk_list: thunk_va = function_thunk.start redirection_dest = (ida_bytes.get_wide_dword(thunk_va) if is_32_bit else ida_bytes.get_qword(thunk_va)) caller_address = ida_xref.get_first_cref_to(redirection_dest) if caller_address == ida_idaapi.BADADDR: continue redirection_source = idc.get_func_attr(caller_address, idc.FUNCATTR_START) caller_function_name = ida_funcs.get_func_name(redirection_source) if function_thunk.name in caller_function_name: print( "anvill: Redirecting the user {:x} of thunk {} at rva {:x} to {:x}" .format( redirection_source, function_thunk.name, function_thunk.start, redirection_dest, )) self.add_control_flow_redirection(redirection_source, redirection_dest) print( "anvill: Adding target list {:x} -> [{:x}, complete=True] for {}" .format(caller_address, redirection_dest, function_thunk.name)) self.set_control_flow_targets(caller_address, [redirection_dest], True)
def getFunctionSymbols(self): function_symbols = {} function_offsets = self.getFunctions() for function_offset in function_offsets: function_name = ida_funcs.get_func_name(function_offset) # apply demangling if required if "@" in function_name: demangled = ida_name.demangle_name(function_name, 0) if demangled: function_name = demangled if not re.match("sub_[0-9a-fA-F]+", function_name): function_symbols[function_offset] = function_name return function_symbols
def is_func_call(ea): """ 判读是否是一个函数调用指令 """ op1 = idc.print_operand(ea, 0) for func_addr in idautils.Functions(): func_name = ida_funcs.get_func_name(func_addr) if op1 == func_name: return True else: continue return False
def activate(self, ctx): user_input = ida_kernwin.ask_yn( ida_kernwin.ASKBTN_YES, "Would you like to export all functions?") if user_input == ida_kernwin.ASKBTN_CANCEL: return 1 output_file_name_hint = "" p = anvill.get_program() if user_input == ida_kernwin.ASKBTN_NO: screen_cursor = ida_kernwin.get_screen_ea() function_name = ida_funcs.get_func_name(screen_cursor) if function_name is None: print("anvill: The cursor is not located inside a function") return 1 output_file_name_hint = function_name + ".json" try: p.add_function_definition(screen_cursor) except: print( "anvill: Failed to process the function at address {0:x}". format(screen_cursor)) return 1 else: function_address_list = idautils.Functions() for function_address in function_address_list: try: p.add_function_definition(function_address) except: print( "anvill: Failed to process the function at address {0:x}" .format(function_address)) output_file_name_hint = "program.json" output_path = ida_kernwin.ask_file( True, output_file_name_hint, "Select where to save the spec file") if not output_path: return 1 output = json.dumps(p.proto(), sort_keys=False, indent=2) print("anvill: Saving the spec file to {}".format(output_path)) with open(output_path, "w") as f: f.write(output)
def show_graph(): f = ida_funcs.get_func(ida_kernwin.get_screen_ea()) if not f: print("Must be in a function") return # Iterate through all function instructions and take only call instructions result = [] tmp = ida_ua.insn_t() for x in [ x for x in idautils.FuncItems(f.start_ea) if (ida_ua.decode_insn(tmp, x) and ida_idp.is_call_insn(tmp)) ]: for xref in idautils.XrefsFrom(x, ida_xref.XREF_FAR): if not xref.iscode: continue t = ida_funcs.get_func_name(xref.to) if not t: t = hex(xref.to) result.append(t) g = MyGraph(ida_funcs.get_func_name(f.start_ea), result) if g.Show(): return g else: return None
def __process_functions(self): functions = list() start = ida_ida.cvar.inf.min_ea end = ida_ida.cvar.inf.max_ea # find first function head chunk in the range chunk = ida_funcs.get_fchunk(start) if not chunk: chunk = ida_funcs.get_next_fchunk(start) while chunk and chunk.start_ea < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0: chunk = ida_funcs.get_next_fchunk(chunk.start_ea) func = chunk while func and func.start_ea < end: start_ea = func.start_ea func_flags = ida_bytes.get_full_flags(start_ea) func_name = ida_funcs.get_func_name(start_ea) func_name_demangled = ida_name.get_demangled_name( start_ea, 0xFFFF, 0, 0) func_autonamed = func_flags & ida_bytes.FF_LABL != 0 func_public = ida_name.is_public_name(start_ea) function = { 'start_rva': start_ea - self._base, 'name': func_name, 'name_demangled': func_name_demangled, 'is_public': func_public, 'is_autonamed': func_autonamed } # PE32/PE32+ only support binaries up to 2GB if function['start_rva'] >= 2**32: print('RVA out of range for function: ' + function['name'], file=sys.stderr) self.__process_function_typeinfo(function, func) function['labels'] = self.__process_function_labels(func) functions.append(function) func = ida_funcs.get_next_func(start_ea) return functions
def find_import_ref(dllname): imports = find_imported_funcs(dllname) R = dict() for i, (ea, name,_) in enumerate(imports): #print "%x -> %s" % (ea, name) for xref in idautils.XrefsTo(ea): # check if referrer is a thunk ea = xref.frm f = ida_funcs.get_func(ea) if f and (f.flags & ida_funcs.FUNC_THUNK) != 0: imports.append([f.start_ea, ida_funcs.get_func_name(f.start_ea), 0]) #print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.start_ea) continue # save results if i not in R: R[i] = [] R[i].append(ea) return (imports, R)