def retrieve_ea_list_set(cond_list): """ Args: cond_list: List of conditions to determine the address. Returns: A list of set of found addresses. Each set of addresses corresponds to a condition. """ found_addr_list_set = [] # List of set of found addresses. for cond in cond_list: print("{0}".format(cond)) split_cond = cond.split(':') if(len(split_cond) != 2): print("Condition is malformed. It should be of form <type>:<value> but I am getting {0}".format(split_cond)) exit(1) cond_type = split_cond[0] cond_value = split_cond[1] curr_addr = idc.get_inf_attr(INF_MIN_EA) # Get start of addr of entire binary end_addr = idc.get_inf_attr(INF_MAX_EA) # Get end of addr of entire binary cond_found_addr_set = set() while(curr_addr < end_addr): (result_addr_set, curr_addr) = process_cond(cond_type, cond_value, curr_addr) cond_found_addr_set |= result_addr_set print("cond_found_addr_set: {0} result_addr_set: {1}".format(cond_found_addr_set, result_addr_set)) found_addr_list_set.append(cond_found_addr_set) return found_addr_list_set
def find_binary_instruction_start( search_start_location, search_direction, target, min_location=idc.get_inf_attr(idc.INF_MIN_EA), max_location=idc.get_inf_attr(idc.INF_MAX_EA)): """ Description: Given a starting location, target, and direction, find an instruction starting with the target bytes. Input: search_start_location - The EA to start searching at search_direction - either idc.SEARCH_UP or idc.SEARCH_DOWN target - The target as space separated bytes (i.e. '55' for 'push ebp') min_location - The minimum EA to accept results for (default: idc.get_inf_attr(idc.INF_MIN_EA)) max_location - The maximum EA to accept results for (default: idc.get_inf_attr(idc.INF_MAX_EA)) Output: Returns the first matching location if found, otherwise idc.BADADDR """ target = target.upper() while search_start_location < max_location: ea = idc.find_binary(search_start_location, search_direction, target) if (min_location <= ea < max_location and ea == idc.get_item_head(ea) and idc.get_bytes( ea, idc.get_item_size(ea)).encode('hex').upper().startswith( target.replace(' ', ''))): return ea else: search_start_location = ea + (1 if search_direction == idc.SEARCH_DOWN else -1) return idc.BADADDR
def is_valid_ea(ea): """ Description: Returns true for valid EAs, False for invalid ones. Input: ea - The EA to check Output: True if the EA is valid, False if it is not """ return ea not in (None, idc.BADADDR) and idc.get_inf_attr( idc.INF_MIN_EA) <= ea <= idc.get_inf_attr(idc.INF_MAX_EA)
def demangle(self, name): mask = idc.get_inf_attr(idc.INF_SHORT_DEMNAMES) demangled = idc.demangle_name(name, mask) if demangled is None: return name else: return demangled
def run(self, arg): # 查找需要的函数 ea, ed = getSegAddr() search_result = [] for func in idautils.Functions(ea, ed): try: functionName = str(idaapi.ida_funcs.get_func_name(func)) demangled = idc.demangle_name(functionName, idc.get_inf_attr( idc.INF_SHORT_DN)) functionName = demangled if demangled else functionName if len(list(idautils.FuncItems(func))) > 10: # 如果是thumb模式,地址+1 arm_or_thumb = idc.get_sreg(func, "T") if arm_or_thumb: func += 1 search_result.append([hex(func), functionName]) except: pass so_path, so_name = getSoPathAndName() search_result = [f"{so_name}!{a}!{b}" for a, b in search_result] search_result = "\n".join(search_result) save_path = os.path.join(so_path, so_name.split(".")[0] + ".txt") with open(save_path, "w", encoding="utf-8")as F: F.write(search_result) print("使用方法如下:") print(f"frida-trace -UF -z {save_path}")
def build_export_table(linlist, winlist): instance = (int, long) if version_info[0] < 3 else int for i, v in enumerate(linlist): if isinstance(v, instance): linlist = linlist[:i] # Skipping thisoffs break listnode = linlist[:] for i, v in enumerate(linlist): name = str(v) if name.startswith("__cxa"): listnode[i] = None continue s = "L{:<6}".format(i) try: s += " W{}".format(winlist.index(name)) except: pass funcname = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) s = "{:<16} {}".format(s, funcname) listnode[i] = s return [i for i in listnode if i != None]
def write_exact_comp(strdict, funcdict, myfuncs): global FOUND_FUNCS update_window("Writing exact comparisons") count = 0 for strippedname, strippedlist in get_bcompat_iter(strdict): if not ida_funcs.get_func_name(myfuncs[strippedname]).startswith("sub_"): continue possibilities = [] strippedlist = sorted(strippedlist) for symname, symlist in get_bcompat_iter(funcdict): if strippedlist == sorted(symlist): possibilities.append(str(symname)) else: continue if len(possibilities) >= 2: break if len(possibilities) != 1: continue if possibilities[0] not in FOUND_FUNCS and possibilities[0] not in myfuncs: # print(ida_funcs.get_func_name(myfuncs[strippedname])) idc.set_name(myfuncs[strippedname], possibilities[0], ida_name.SN_FORCE) count += 1 FOUND_FUNCS.add(possibilities[0]) update_window("Writing exact comparisons") elif DEBUG: print("{} is probably wrong!".format(idc.demangle_name(possibilities[0], idc.get_inf_attr(idc.INF_SHORT_DN)))) return count
def demangle_name(self): """ Property which return the demangle name of the function. :return str: The demangle name of the function. """ return idc.demangle_name(self.name, idc.get_inf_attr(idc.INF_SHORT_DN))
def update(self, ctx): if (idc.get_inf_attr(idc.INF_PROCNAME) != "metapc"): return AST_DISABLE if (ctx.action == 'klfdb:run'): if (idc.get_process_state() == idc.DSTATE_SUSP): return AST_ENABLE return AST_DISABLE elif (ctx.action == 'klfdb:runnext'): if (idc.get_process_state() == idc.DSTATE_SUSP): return AST_ENABLE return AST_DISABLE elif (ctx.action == 'klfdb:delbpts'): return AST_ENABLE elif (ctx.action == 'klfdb:setbpts'): return AST_ENABLE elif (ctx.action == 'klfdb:ignore'): return AST_ENABLE elif (ctx.action == 'klfdb:loadmap'): return AST_ENABLE elif (ctx.action == 'klfdb:delmap'): return AST_ENABLE return AST_DISABLE
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 demangle_name(self): """ Property which return the demangle name of the element. :return str: The demangle name of the element or None if there is no demangle version of the name. """ return idc.demangle_name(self.name, idc.get_inf_attr(idc.INF_SHORT_DN))
def search_bytes_addr(byt, start_ea=None, end_ea=None, down=True, nxt=True): """ Static method for searching a sequence of bytes. This will search for the bytes which ever the data type is. This is a wrapper on the ``ida_search.find_binary`` (previously ``FindBinary``) function from IDA with a radix of 16. The byte should be represented in hexadecimal seperated by space. A ``?`` can be put for replacing a byte, for example: ``41 8B 44 ? 20``. :param byt: A string representing a sequence of byte. :param start_ea: The address at which to start the search, if ``None`` the current address will be used. :param end_ea: The address at which to stop the search, if ``None`` the maximum or minimum (depending of searching up or down) will be used. :param down: If True (the default) search below the given address, if False search above. :param nxt: If True (the default) the current element will not be included in the search. :return: The address at which the byte sequence is present or ``None`` if no element were found during the search. """ if start_ea is None: start_ea = ida_kernwin.get_screen_ea() if down: fl = ida_search.SEARCH_DOWN if end_ea is None: end_ea = idc.get_inf_attr(idc.INF_MAX_EA) else: fl = ida_search.SEARCH_UP if end_ea is None: end_ea = idc.get_inf_attr(idc.INF_MIN_EA) if nxt: fl |= ida_search.SEARCH_NEXT r = ida_search.find_binary(start_ea, end_ea, byt, 16, fl) if r == idc.BADADDR: return None else: return r
def vtable_symbol_get_class(symbol): """Get the class name for a vtable symbol.""" try: demangled = idc.demangle_name(symbol, idc.get_inf_attr(idc.INF_SHORT_DEMNAMES)) pre, post = demangled.split("`vtable for'", 1) assert pre == '' return post except: return None
def get_func_postname(name): unmangled = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) if unmangled is None: return "" if unmangled[:unmangled.find("(")].rfind("::") != -1: unmangled = unmangled[unmangled[:unmangled.find("(")].rfind("::") + 2:] return unmangled
def get_func_argnames(name): unmangled = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) if unmangled is None: return "" if unmangled.find("(") != -1: unmangled = unmangled[unmangled.find("("):] return unmangled
def __init__(self): super(FunctionsPlus, self).__init__() if idc.get_inf_attr(idc.INF_PROCNAME).lower() != 'metapc': print('Functions+ warning: not tested in this configuration') self.tree = None self.icon = 135 # Enable this if you want to see extra information about function self.show_extra_fields = False self.cols = Cols(self.show_extra_fields)
def name(self): name = idc.get_name(self.address) if ida_name.is_valid_typename(name): return name demangled_name = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) if not demangled_name: raise ValueError("Couldn't demangle name: {} at 0x{:x}".format( name, self.address)) return common.demangled_name_to_c_str(demangled_name)
def demangle(cls, name): ''' Demangles name. ''' mask = idc.get_inf_attr(idc.INF_SHORT_DN) demangled = idc.demangle_name(name, mask) if demangled is None: return name return demangled
def init(self): """ Init plugin function """ if idc.get_inf_attr(idc.INF_FILETYPE) != idc.FT_PE: # skip if it's not a PE return idaapi.PLUGIN_SKIP ComIDA.log("'%s' loaded. %s activates/deactivates synchronization." % (ComIDA.wanted_name, ComIDA.wanted_hotkey)) return idaapi.PLUGIN_KEEP
def _getArgsDescription(ea: int) -> str: name = demangle_name(get_func_name(ea), get_inf_attr(INF_SHORT_DN)) # get from mangled name if not name: name = get_type(ea) # get from type if not name: return parse_function_args(ea) # cannot get params from the mangled name args_start = name.find('(') if args_start is not None and args_start != (-1): return name[args_start:] return ""
def _getFunctionNameAt(ea: int) -> str: name = get_func_name(ea) disable_mask = get_inf_attr(INF_SHORT_DN) demangled_name = demangle_name(name, disable_mask) if demangled_name is None: return name args_start = demangled_name.find('(') if args_start is None: return demangled_name return demangled_name[:args_start]
def mark_string(ea, name=None): strlen = len(idc.get_strlit_contents(ea, -1) or '') ida_bytes.del_items( ea, ida_bytes.DELIT_EXPAND | ida_bytes.DELIT_DELNAMES | ida_bytes.DELIT_NOCMT, strlen + 1) ida_bytes.create_strlit(ea, strlen + 1, idc.get_inf_attr(idc.INF_STRTYPE)) if name: ida_name.set_name(ea, name, ida_name.SN_CHECK) idc.apply_type(ea, idc.parse_decl('char const a[]', 0), idc.TINFO_DEFINITE) return get_cstring(ea)
def name(self): name = idaapi.get_name(self.addr) demangled_name = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled_name: name = demangled_name_to_c_str(demangled_name) if len(name) == 0: name = 'func_%X' % (self.addr) return name
def class_from_vtable_method_symbol(method_symbol): """Get the base class in a vtable method symbol. Extract the name of the base class from a canonical method symbol. """ demangled = idc.demangle_name(method_symbol, idc.get_inf_attr(idc.INF_SHORT_DN)) if not demangled: return None classname = demangled.split('::', 1)[0] if classname == demangled: return None return classname
def import_vtable(classname, struc): ea = get_vtable(classname) if ea == idc.BADADDR: return # Mildly adapted from Asherkin's vtable dumper ea = ea + 8 # Skip typeinfo and thisoffs funcs = [] while ea != idc.BADADDR: offs = idc.get_wide_dword(ea) if not ida_bytes.is_code(ida_bytes.get_full_flags(offs)): break name = idc.get_name(offs, ida_name.GN_VISIBLE) funcs.append(name) ea = ida_bytes.next_not_tail(ea) # print(funcs) if not len(funcs): return strucid = add_struc_ex(classname + "_vtbl") vstruc = ida_struct.get_struc(strucid) for i in funcs: # Gotta do a fancy demangle, it can't have special chars # and there can't be multiples of the same name, so let's just jazz around all of that demangled = idc.demangle_name(i, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled == None: demangled = i else: demangled = demangled[demangled.find("::") + 2:demangled.find("(")] demangled = demangled.replace("~", "_").replace("<", "_").replace(">", "_") while 1: error = ida_struct.add_struc_member(vstruc, demangled, idc.BADADDR, idc.FF_DWORD, None, 4) if error == 0: break demangled += "_{}".format( hex(ida_struct.get_struc_last_offset(vstruc) * 4 + 4)[2:]) # Now assign the vtable to the actual struct ti = idaapi.tinfo_t() idaapi.parse_decl(ti, None, classname + "_vtbl;", 0) ti.create_ptr(ti) ida_struct.set_member_tinfo(struc, ida_struct.get_member(struc, 0), 0, ti, 0)
def import_vtable(typename, funcs): typestrucid = add_struc_ex(typename) typestruc = ida_struct.get_struc(typestrucid) vstrucid = add_struc_ex(typename + "_vtbl") vstruc = ida_struct.get_struc(vstrucid) loffs = ida_struct.get_struc_last_offset(vstruc) if loffs != idc.BADADDR: ida_struct.del_struc_members(vstruc, 0, loffs + 4) for i in funcs: demangled = idc.demangle_name(i, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled == None: demangled = i else: demangled = demangled[demangled.find("::")+2:demangled.find("(")] # As per https://stackoverflow.com/questions/3411771/best-way-to-replace-multiple-characters-in-a-string # this isn't as slow as you'd think demangled = demangled\ .replace("~", "_")\ .replace("<", "_")\ .replace(">", "_")\ .replace(",", "_")\ .replace("*", "_")\ .replace(" ", "_")\ .replace("operator==", "__eq__")\ .replace("operator+", "__add__")\ .replace("operator-", "__sub__")\ .replace("operator*", "__mul__")\ .replace("operator/", "__div__")\ .replace("operator%", "__mod__")\ .replace("operator<<", "__lshift__")\ .replace("operator>>", "__rshift__")\ .replace("operator&", "__and__")\ .replace("operator|", "__or__")\ .replace("operator^", "__xor__")\ .replace("operator~", "__invert__") while 1: error = ida_struct.add_struc_member(vstruc, demangled, idc.BADADDR, idc.FF_DWORD, None, 4) if error == 0: break demangled += "_{}".format(hex(ida_struct.get_struc_last_offset(vstruc) + 4)[2:]) try: ti = idaapi.tinfo_t() idaapi.parse_decl(ti, None, typename + "_vtbl;", 0) ti.create_ptr(ti) ida_struct.add_struc_member(typestruc, "__vftable", 0, idc.FF_DWORD, None, 4) ida_struct.set_member_tinfo(typestruc, ida_struct.get_member(typestruc, 0), 0, ti, 0) except: print("Prevented a terrible, horrible, no good, very bad crash with {}!".format(typename))
def method_name(symbol): """Get the name of the C++ method from its symbol. If the symbol demangles to 'Class::method(args)', this function returns 'method'. """ try: demangled = idc.demangle_name(symbol, idc.get_inf_attr(idc.INF_SHORT_DEMNAMES)) func = demangled.split('::', 1)[1] base = func.split('(', 1)[0] return base or None except: return None
def method_arguments_string(symbol): """Get the arguments string of the C++ method from its symbol. If the symbol demangles to 'Class::method(arg1, arg2)', this function returns 'arg1, arg2'. """ try: demangled = idc.demangle_name(symbol, idc.get_inf_attr(idc.INF_LONG_DEMNAMES)) func = demangled.split('::', 1)[1] args = func.split('(', 1)[1] args = args.rsplit(')', 1)[0].strip() return args except: return None
def create_segement(segm, offset): name = segm.get("name") if type(segm.get("start")) != int: start = int(segm.get("start"), 16) end = int(segm.get("end"), 16) else: start = segm.get("start") end = segm.get("end") R = int(segm.get("R")) W = int(segm.get("W")) X = int(segm.get("X")) D = int(segm.get("D")) L = int(segm.get("L")) align = int(segm.get("align")) base = int(segm.get("base")) class_ = segm.get("class") ad = int(segm.get("ad")) T = int(segm.get("T")) DS = int(segm.get("DS")) idaapi.set_segm_end(start, start, 0) if idaapi.is_seg(idc.get_inf_attr(idc.INF_MAX_EA), 0): ok = idaapi.add_segm(base, start, 0xFFFFFFFF, name, class_) else: ok = idaapi.add_segm(base, start, idc.get_inf_attr(idc.INF_MAX_EA), name, class_) if ok: idc.set_segm_attr(start, 20, align) perm = 0 if R: perm = perm + 4 if W: perm = perm + 2 if X: perm = perm + 1 idc.set_segm_attr(start, 22, perm)
def parse_vtable_name(address): name = idaapi.get_name(address) if idaapi.is_valid_typename(name): if name[0:3] == 'off': # off_XXXXXXXX case return "Vtable" + name[3:], False elif "table" in name: return name, True print "[Warning] Weird virtual table name -", name return "Vtable_" + name, False name = idc.demangle_name(idaapi.get_name(address), idc.get_inf_attr(idc.INF_SHORT_DN)) assert name, "Virtual table must have either legal c-type name or mangled name" return common.demangled_name_to_c_str(name), True