def _handle_calls(self, fn, fn_an): num_calls = len(fn_an['calls']) if num_calls != 1: return dis = fn_an['calls'][0] if dis.Op1.type not in (o_imm, o_far, o_near, o_mem): return ea = dis.Op1.value if not ea and dis.Op1.addr: ea = dis.Op1.addr if idaapi.has_dummy_name(idaapi.getFlags(ea)): return # TODO: check is there jmp, push+retn then don't rename the func if fn_an['strange_flow']: return possible_name = idaapi.get_ea_name(ea) if not possible_name or possible_name in blacklist: return normalized = self.normalize_name(possible_name) # if self._cfg.get('auto_rename'): if len(fn_an['math']) < self._MIN_MAX_MATH_OPS_TO_ALLOW_RENAME: idaapi.do_name_anyway(fn.startEA, normalized) # TODO: add an API to the view print 'fn: %#08x: %d calls, %d math%s possible name: %s, normalized: %s' % ( fn.startEA, len(fn_an['calls']), len(fn_an['math']), 'has bads' if fn_an['has_bads'] else '', possible_name, normalized)
def execute_rename(name): """ This is a wrapper to execute the renaming synchronously """ def get_name(): return idc.get_name(name["address"]) def make_name(force=False): """ Thread safe renaming wrapper """ def sync_ask_rename(): """ Dialog asking renaming confirmation to the user """ rename_flag = 0 if force or idc.ask_yn( rename_flag, "Replace %s by %s" % (get_name(), name["data"])) == 1: logger.debug("[x] renaming %s @ 0x%x as %s", get_name(), name["address"], name["data"]) ida_name.set_name(name["address"], name["data"].encode('ascii', 'ignore'), ida_name.SN_AUTO) return idaapi.execute_sync(sync_ask_rename, idaapi.MFF_FAST) old_name = get_name() if not name["data"]: return elif idaapi.has_dummy_name(idaapi.get_flags( name["address"])) or not old_name: make_name(force=True) elif get_name() != name["data"]: make_name()
def run(self, arg): """ loop through all functions, collect "self._data", then show view @param: arg : -- """ try: self._data = dict() count = idaapi.get_func_qty() for i in xrange(count): fn = idaapi.getn_func(i) fn_an = self.analyze_func(fn) # if fn_an['math']: # print 'fn: %#08x has math' % fn.startEA if idaapi.has_dummy_name(idaapi.getFlags(fn.startEA)): self._handle_calls(fn, fn_an) self._handle_tags(fn, fn_an) if self.view: self.view.Close(idaapi.PluginForm.FORM_NO_CONTEXT) self.view = AutoREView(self._data) self.view.Show() except: idaapi.msg('AutoRE: error: %s\n' % traceback.format_exc())
def send_names(self): """ Used to send all the names to the server. Usecase: Previously analyzed IDB """ for head in idautils.Names(): if not idaapi.has_dummy_name(idaapi.get_flags(head[0])): self.skel_conn.push_name(head[0], head[1])
def send_names(self): """ Used to send all the names to the server. Usecase: Previously analyzed IDB """ for head in idautils.Names(): if not idaapi.has_dummy_name(idaapi.get_flags(head[0])): self.skel_conn.push_name(head[0], head[1])
def __getlabel(cls, ea): try: f = idaapi.getFlags(ea) if idaapi.has_dummy_name(f) or idaapi.has_user_name(f): r, = xref.data_up(ea) return cls.__getarray(r) except TypeError: pass raise TypeError, "Unable to instantiate a switch_info_ex_t at target label : %x" % ea
def renamed(self, *args): logger.debug("[IDB Hook] Something is renamed") ea, new_name, is_local_name = args min_ea = idc.get_inf_attr(idc.INF_MIN_EA) max_ea = idc.get_inf_attr(idc.INF_MAX_EA) if ea >= min_ea and ea <= max_ea: if is_local_name: logger.warning("Local names are unimplemented") else: auto = idaapi.has_auto_name(idaapi.get_flags(ea)) dummy = idaapi.has_dummy_name(idaapi.get_flags(ea)) if not dummy and not auto: self.skel_conn.push_name(ea, new_name) else: logger.warning("ea outside program...") return ida_idp.IDB_Hooks.renamed(self, *args)
def run(self, arg): if RDEBUG and RDEBUG_EGG: if not os.path.isfile(RDEBUG_EGG): idaapi.msg( 'AutoRE: Remote debug is enabled, but I cannot find the debug egg: %s' % RDEBUG_EGG) else: import sys if RDEBUG_EGG not in sys.path: sys.path.append(RDEBUG_EGG) import pydevd pydevd.settrace(RDEBUG_HOST, port=RDEBUG_PORT, stdoutToServer=True, stderrToServer=True ) # , stdoutToServer=True, stderrToServer=True try: self._data = dict() count = idaapi.get_func_qty() # pre-process of api wrapper functions known_refs_tags = self._preprocess_api_wrappers(count) for i in xrange(count): fn = idaapi.getn_func(i) fn_an = self.analyze_func(fn) # if fn_an['math']: # print 'fn: %#08x has math' % fn.startEA if idaapi.has_dummy_name(idaapi.getFlags(fn.startEA)): self._handle_calls(fn, fn_an) known_refs = known_refs_tags.get(fn.startEA) self._handle_tags(fn, fn_an, known_refs) if self.view: self.view.Close(idaapi.PluginForm.FORM_NO_CONTEXT) self.view = AutoREView(self._data) self.view.Show() except: idaapi.msg('AutoRE: error: %s\n' % traceback.format_exc())
def GetNameFlags(name, ea): flags = 0 # we don't know what name_value is... name_value, _name_value = idaapi.get_name_value(ea, name) # if(addr != ea): # if(addr == (ea | 0x100000000) or addr == (ea & 0xFFFFFFFF)): # logger.warn("(IDA bug) get_name_value returned bad address : 0x%016X (instead of 0x%016X)" % (addr, ea)) # else: # logger.warn("get_name_value returned bad address : "\ # "0x%016X (instead of 0x%016X), using idc.SN_CHECK" % (addr, ea)) # return default value used by MakeName # return idc.SN_CHECK if name_value == idaapi.NT_LOCAL: # see name.hpp : LOCAL names can not be public nor weak, and are not listed flags |= idaapi.SN_LOCAL | idaapi.SN_NON_PUBLIC | idaapi.SN_NON_WEAK | idaapi.SN_NOLIST else: if idaapi.is_public_name(ea): flags |= idaapi.SN_PUBLIC else: flags |= idaapi.SN_NON_PUBLIC if idaapi.is_weak_name(ea): flags |= idaapi.SN_WEAK else: flags |= idaapi.SN_NON_WEAK if idaapi.is_in_nlist(ea) is False: flags |= idaapi.SN_NOLIST ida_flags = idc.GetFlags(ea) if idaapi.has_user_name(ida_flags) or idc.hasUserName(ida_flags): flags |= idc.SN_NON_AUTO elif idaapi.has_auto_name(ida_flags): flags |= idc.SN_AUTO elif idaapi.has_dummy_name(ida_flags): # names like "dword_XXXX" flags |= idc.SN_AUTO else: logger.debug("name is not user nor auto?? at 0x%016X : 0x%08X" % (ea, ida_flags)) return flags
def get_symbol_name(from_ea, ea=None, allow_dummy=False): if ea is None: ea = from_ea global _FORCED_NAMES if ea in _FORCED_NAMES: return _FORCED_NAMES[ea] flags = idc.get_full_flags(ea) if not allow_dummy and idaapi.has_dummy_name(flags): return "" name = "" try: name = name or idc.get_name(ea, 0) #calc_gtn_flags(from_ea, ea)) except: pass try: name = name or idc.get_func_name(ea) except: pass return name
def get_symbol_name(from_ea, ea=None, allow_dummy=False): if ea is None: ea = from_ea global _FORCED_NAMES if ea in _FORCED_NAMES: return _FORCED_NAMES[ea] flags = idc.GetFlags(ea) if not allow_dummy and idaapi.has_dummy_name(flags): return "" name = "" try: name = name or idc.GetTrueNameEx(from_ea, ea) except: pass try: name = name or idc.GetFunctionName(ea) except: pass return name
def get_symbol_name(from_ea, ea=None, allow_dummy=False): if ea is None: ea = from_ea global _FORCED_NAMES if ea in _FORCED_NAMES: return _FORCED_NAMES[ea] flags = idc.get_full_flags(ea) if not allow_dummy and idaapi.has_dummy_name(flags): return "" name = "" try: name = name or idc.get_name(ea, 0) #calc_gtn_flags(from_ea, ea)) except: pass try: name = name or idc.get_func_name(ea) except: pass return name
def get_symbol_name(from_ea, ea=None, allow_dummy=False): if ea is None: ea = from_ea global _FORCED_NAMES if ea in _FORCED_NAMES: return _FORCED_NAMES[ea] flags = idc.GetFlags(ea) if not allow_dummy and idaapi.has_dummy_name(flags): return "" name = "" try: name = name or idc.GetTrueNameEx(from_ea, ea) except: pass try: name = name or idc.GetFunctionName(ea) except: pass return name
def execute_rename(name): """ This is a wrapper to execute the renaming synchronously """ def get_name(): return idc.get_name(name["address"]) def make_name(force=False): """ Thread safe renaming wrapper """ def sync_ask_rename(): """ Dialog asking renaming confirmation to the user """ rename_flag = 0 if force or idc.ask_yn(rename_flag, "Replace %s by %s" % (get_name(), name["data"])) == 1: logger.debug("[x] renaming %s @ 0x%x as %s", get_name(), name["address"], name["data"]) ida_name.set_name( name["address"], name["data"].encode( 'ascii', 'ignore'), ida_name.SN_AUTO) return idaapi.execute_sync( sync_ask_rename, idaapi.MFF_FAST) old_name = get_name() if not name["data"]: return elif idaapi.has_dummy_name(idaapi.get_flags(name["address"])) or not old_name: make_name(force=True) elif get_name() != name["data"]: make_name()
def activate(self, ctx): if self.menu_title == MenuAskEntryId: self.outer_self.mixto.entry_id = idaapi.ask_str( "", 1000, "Mixto Entry Id") else: if self.outer_self.mixto.entry_id is None: self.outer_self.mixto.entry_id = idaapi.ask_str( "", 1000, "Mixto Entry Id") if self.menu_title == MenuAllFunc: all_func = "" # Get count of all functions in the binary count = idaapi.get_func_qty() for i in range(count): fn = idaapi.getn_func(i) # Function should not have dummy name such as sub_* # and should not start with underscore (possible library functions) if not idaapi.has_dummy_name(get_flags_at( start_ea_of(fn))) and not idaapi.get_func_name( start_ea_of(fn)).startswith("_"): all_func += "{} @ 0x{:x}\n".format( idaapi.get_func_name(start_ea_of(fn)), start_ea_of(fn)) self.outer_self.mixto.AddCommit(all_func, self.outer_self.mixto.entry_id, "(IDA) All Functions") elif self.menu_title == MenuImports: global AllImports AllImports = "" # Get count of all import modules in the binary count = idaapi.get_import_module_qty() for i in range(count): module_name = idaapi.get_import_module_name(i) AllImports += "{}:\n".format(module_name) idaapi.enum_import_names(i, imports_cb) self.outer_self.mixto.AddCommit(AllImports, self.outer_self.mixto.entry_id, "(IDA) All Imports") elif self.menu_title == MenuDecFunc: addr_current = idc.get_screen_ea() addr_func = idaapi.get_func(addr_current) if not addr_func: idaapi.msg("Place cursor inside a function!") return False else: err = None out = str(idaapi.decompile(addr_func)) # print(out) self.outer_self.mixto.AddCommit( str(out), self.outer_self.mixto.entry_id, "(IDA) Function Decompilation {}".format( idc.GetFunctionName(addr_func.startEA)), ) elif self.menu_title == MenuExports: all_exports = "" for entry in idautils.Entries(): _, ord, ea, name = entry if not name: all_exports += "0x{:x}: ord#{}\n".format(ea, ord) else: all_exports += "0x{:x}: {} ord#{}\n".format( ea, name, ord) self.outer_self.mixto.AddCommit(all_exports, self.outer_self.mixto.entry_id, "(IDA) All Exports") elif self.menu_title == MenuAllComments: addr_current = idc.get_screen_ea() addr_func = idaapi.get_func(addr_current) uniq_comments = {} comments = [] for ea in range(addr_func.startEA, addr_func.endEA): comment = idaapi.get_cmt(ea, 0) if comment is not None: # hacky way to make sure only uniq comments are added if uniq_comments.get(comment) == 1: pass else: print(uniq_comments) comments.append("{offset} {value}".format( offset=hex(ea), value=comment)) print("here") uniq_comments[comment] = 1 if len(comments) > 0: out = "\n".join(comments) self.outer_self.mixto.AddCommit( str(out), self.outer_self.mixto.entry_id, "(IDA) Function Comments {}".format( idc.GetFunctionName(addr_func.startEA)), ) else: raise TypeError("No comments found") return True
def activate(self, ctx): if self.menu_title == MenuAskEntryId: self.outer_self.mixto.entry_id = idaapi.ask_str( "", 1000, "Mixto Entry Id") else: if self.outer_self.mixto.entry_id is None: self.outer_self.mixto.entry_id = idaapi.ask_str( "", 1000, "Mixto Entry Id") if self.menu_title == MenuAllFunc: all_func = "" # Get count of all functions in the binary count = idaapi.get_func_qty() for i in range(count): fn = idaapi.getn_func(i) # Function should not have dummy name such as sub_* # and should not start with underscore (possible library functions) if not idaapi.has_dummy_name(get_flags_at( start_ea_of(fn))) and not idaapi.get_func_name( start_ea_of(fn)).startswith("_"): all_func += "{} @ 0x{:x}\n".format( idaapi.get_func_name(start_ea_of(fn)), start_ea_of(fn)) self.outer_self.mixto.AddCommit(all_func, self.outer_self.mixto.entry_id, "(IDA) All Functions") elif self.menu_title == MenuImports: global AllImports AllImports = "" # Get count of all import modules in the binary count = idaapi.get_import_module_qty() for i in range(count): module_name = idaapi.get_import_module_name(i) AllImports += "{}:\n".format(module_name) idaapi.enum_import_names(i, imports_cb) self.outer_self.mixto.AddCommit(AllImports, self.outer_self.mixto.entry_id, "(IDA) All Imports") elif self.menu_title == MenuDecFunc: addr_current = idc.get_screen_ea() addr_func = idaapi.get_func(addr_current) if not addr_func: idaapi.msg("Place cursor inside a function!") return False else: err = None out = ida_hexrays.decompile_func(addr_func, err) # print(out) self.outer_self.mixto.AddCommit( str(out), self.outer_self.mixto.entry_id, "(IDA) Function Decompilation", ) elif self.menu_title == MenuExports: all_exports = "" for entry in idautils.Entries(): _, ord, ea, name = entry if not name: all_exports += "0x{:x}: ord#{}\n".format(ea, ord) else: all_exports += "0x{:x}: {} ord#{}\n".format( ea, name, ord) self.outer_self.mixto.AddCommit(all_exports, self.outer_self.mixto.entry_id, "(IDA) All Exports") elif self.menu_title == MenuAllComments: raise NotImplementedError("Comments not yet implemented TODO") return True
def name(ea=None, *args, **kwds): """name(ea), name(ea, string) First syntax returns the name at the given address. Second syntax changes the name at the given address. """ if len(args) > 1: raise TypeError, "{:s}() takes exactly {!r} arguments ({:d} given)".format( 'name', (1, 2), len(args) + 1 + len(kwds)) if kwds and tuple(kwds.keys()) != ('string', ): raise TypeError, "{:s}() got an unexpected keyword argument '{:s}'".format( 'name', filter(lambda n: n != 'string', kwds.keys())[0]) ea = ui.current.address() if ea is None else ea if len(args) == 1 or kwds.has_key('string'): string = kwds.get('string', args[0]) assert idaapi.SN_NOCHECK == 0, '%s.name : idaapi.SN_NOCHECK != 0' % __name__ SN_NOLIST = idaapi.SN_NOLIST SN_LOCAL = idaapi.SN_LOCAL SN_NON_PUBLIC = idaapi.SN_NON_PUBLIC if idaapi.has_any_name(idaapi.getFlags(ea)): pass flags = idaapi.SN_NON_AUTO flags |= 0 if idaapi.is_in_nlist(ea) else idaapi.SN_NOLIST flags |= idaapi.SN_WEAK if idaapi.is_weak_name( ea) else idaapi.SN_NON_WEAK flags |= idaapi.SN_PUBLIC if idaapi.is_public_name( ea) else idaapi.SN_NON_PUBLIC try: function.top(ea) flags |= idaapi.SN_LOCAL except Exception: flags &= ~idaapi.SN_LOCAL try: # check if we're a label of some kind f = idaapi.getFlags(ea) if idaapi.has_dummy_name(f) or idaapi.has_user_name(f): # that is referenced by an array with a correctly sized pointer inside it (r, sidata), = ((r, type.array(r)) for r in xref.data_up(ea)) if config.bits() == sidata.itemsize * 8 and ea in sidata: # which we check to see if it's a switch_info_t si, = (idaapi.get_switch_info_ex(r) for r in xref.data_up(r)) if si is not None: # because it's name has it's local flag cleared flags ^= idaapi.SN_LOCAL except: pass res, ok = name(ea), idaapi.set_name(ea, string or "", flags) tag(ea, 'name', string) assert ok, '%s.name : unable to call idaapi.set_name(%x, %r, %x)' % ( __name__, ea, string, flags) return res try: return tag(ea, 'name') except KeyError: pass return None