def load_crash_report(self, log_file): with open(log_file, 'r') as f: log = f.read() traceback = process_stack_trace(log) self.log_txt.setText(log) self.stack_trace_table.clear() self.stack_trace_table.setHorizontalHeaderLabels( ["Address", "Function"]) self.stack_trace_table.setRowCount(len(traceback)) for i, addr in enumerate(traceback): func_name = idc.GetFunctionName(addr) func_name_demangled = idc.Demangle( func_name, idc.GetLongPrm(idc.INF_SHORT_DN)) if func_name_demangled is not None: func_name = func_name_demangled self.stack_trace_table.setRowHeight(i, 20) self.stack_trace_table.setItem( i, 0, QtWidgets.QTableWidgetItem("0x{:016x}".format(addr))) self.stack_trace_table.setItem( i, 1, QtWidgets.QTableWidgetItem(func_name)) self.log_txt.setEnabled(True) self.stack_trace_table.setEnabled(True)
def kernelcache_find_virtual_method_overrides(classname=None, method=None): import idc import idaapi import ida_kernelcache as kc # Define the form to ask for the arguments. class MyForm(idaapi.Form): def __init__(self): swidth = 40 idaapi.Form.__init__( self, r"""STARTITEM 0 Find virtual method overrides <#The class#Class :{classname}> <#The virtual method#Method:{method}>""", { 'classname': idaapi.Form.StringInput(tp=idaapi.Form.FT_IDENT, swidth=swidth), 'method': idaapi.Form.StringInput(tp=idaapi.Form.FT_IDENT, swidth=swidth), }) def OnFormChange(self, fid): return 1 kc.collect_class_info() if any(arg is None for arg in (classname, method)): f = MyForm() f.Compile() f.classname.value = classname or '' f.method.value = method or '' ok = f.Execute() if ok != 1: print 'Cancelled' return False classname = f.classname.value method = f.method.value f.Free() if classname not in kc.class_info: print 'Not a valid class: {}'.format(classname) return False print 'Subclasses of {} that override {}:'.format(classname, method) baseinfo = kc.class_info[classname] found = False for classinfo in baseinfo.descendants(): for _, override, _ in kc.vtable.class_vtable_overrides( classinfo, superinfo=baseinfo, methods=True): name = idc.NameEx(idc.BADADDR, override) demangled = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) name = demangled if demangled else name if method in name: print '{:#x} {}'.format(override, classinfo.classname) found = True if not found: print 'No subclass of {} overrides {}'.format(classname, method) return found
def kernelcache_find_virtual_method_overrides(classname=None, method=None): import idc import ida_kernelcache as kc kc.collect_class_info() if not classname: classname = idc.AskStr('IOUserClient', 'Enter class name') if classname not in kc.class_info: print 'Not a valid class: {}'.format(classname) return False if not method: method = idc.AskStr('externalMethod', 'Enter method name') print 'Subclasses of {} that override {}:'.format(classname, method) baseinfo = kc.class_info[classname] found = False for classinfo in baseinfo.descendants(): for _, override, _ in kc.vtable.class_vtable_overrides( classinfo, superinfo=baseinfo, methods=True): name = idc.NameEx(idc.BADADDR, override) demangled = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) name = demangled if demangled else name if method in name: print '{:#x} {}'.format(override, classinfo.classname) found = True if not found: print 'No subclass of {} overrides {}'.format(classname, method) return found
def _split_basic_block(start_ea, end_ea): """ IDA Pro's ``idaapi.Flowchart`` does not consider function calls as basic block boundaries. This function takes an address range and splits the basic blocks found within that range so that function calls are considered basic block boundaries. """ split_bbs = [] func_name = idc.GetFunctionName(start_ea) demangled_name = idc.Demangle(func_name, idc.GetLongPrm(idc.INF_SHORT_DN)) if demangled_name: func_name = demangled_name bb_start_addr = start_ea block = idautils.Heads(start_ea, end_ea) for inst in block: mnem = idc.GetMnem(inst) if mnem == 'call' and inst != end_ea: split_bbs.append( dict(start_addr=bb_start_addr, end_addr=idc.NextHead(inst, end_ea + 1) - 1, function=func_name)) bb_start_addr = idc.NextHead(inst, end_ea + 1) if bb_start_addr < end_ea: split_bbs.append( dict(start_addr=bb_start_addr, end_addr=end_ea - 1, function=func_name)) return split_bbs
def __get_functions(self): functions = list(idautils.Functions()) for start_function in functions: tinfo = idc.GetTinfo(start_function) if tinfo is None: continue mangled_name = idc.GetFunctionName(start_function) demangled = {idc.INF_SHORT_DN: '', idc.INF_LONG_DN: ''} for record in demangled.iteritems(): (type, value) = record demangled[type] = idc.Demangle(mangled_name, idc.GetLongPrm(type)) ida_type, ida_fields = tinfo yield models_ida.IdaRawFunctions( start=start_function, end=idc.GetFunctionAttr(start_function, idc.FUNCATTR_END), ida_type=ida_type, ida_fields=ida_fields, mangled_name=mangled_name, short_name=demangled[idc.INF_SHORT_DN], long_name=demangled[idc.INF_LONG_DN])
def demangle(self, name): mask = idc.GetLongPrm(idc.INF_SHORT_DN) demangled = idc.Demangle(name, mask) if demangled is None: return name else: return demangled
def getFunctionName(self, ea): """Returns the name of the function to which ea belongs""" demangled_name = idc.Demangle(idc.GetFunctionName(ea), idc.GetLongPrm(idc.INF_SHORT_DN)) if not demangled_name: return idc.GetFunctionName(ea) else: return demangled_name
def GetFuncName(self, ea, demangle=True): name = get_func_name(ea) demangled_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) if demangled_name == None: return name else: return demangled_name
def _demangle(name, short=True): dtype = idc.INF_LONG_DN if short: dtype = idc.INF_SHORT_DN tmp = idc.Demangle(name, idc.GetLongPrm(dtype)) if tmp: name = tmp name = name.replace('__', '::') return name
def vtable_symbol_get_class(symbol): """Get the class name for a vtable symbol.""" try: demangled = idc.Demangle(symbol, idc.GetLongPrm(idc.INF_SHORT_DN)) pre, post = demangled.split("`vtable for'", 1) assert pre == '' return post except: return None
def demangle(name, strip_arg_types=False): def strip_args(name): if strip_arg_types is True: return name.split("(", 1)[0] else: return name demangled = idc.Demangle(name, idc.GetLongPrm(idc.INF_LONG_DN)) if demangled is not None: return strip_args(demangled) # The names in RTTI are not mangled normally, so try prepending # the '_Z' demangled = idc.Demangle("_Z" + name, idc.GetLongPrm(idc.INF_LONG_DN)) if demangled is not None: return strip_args(demangled) return strip_args(name)
def demangle_name(cls, name): '''Demangle name.''' tmp = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) if tmp: name = tmp matches = re.match(r'^(.*?)\(.*?\)', name) if matches: name = matches.group(1) return name
def architecture(self): """Return the IDA guessed processor Ripped from Miasm2 / examples / ida / utils """ processor_name = idc.GetLongPrm(idc.INF_PROCNAME) if processor_name in self.IDAarch2MiasmArch: name = self.IDAarch2MiasmArch[processor_name] elif processor_name == "metapc": # HACK: check 32/64 using INF_START_SP inf = idaapi.get_inf_structure() if inf.is_32bit(): name = "x86_32" elif inf.is_64bit(): name = "x86_64" elif idc.GetLongPrm(idc.INF_START_SP) == 0x80: name = "x86_16" else: raise ValueError('cannot guess 32/64 bit! (%x)' % max_size) elif processor_name == "ARM": # TODO ARM/thumb # hack for thumb: set armt = True in globals :/ # set bigendiant = True is bigendian is_armt = globals().get('armt', False) is_bigendian = globals().get('bigendian', False) if is_armt: if is_bigendian: name = "armtb" else: name = "armtl" else: if is_bigendian: name = "armb" else: name = "arml" else: print repr(processor_name) raise ValueError("Unknown corresponding architecture") return name
def get_func_name(self, address): name = idc.Demangle(idaapi.get_func_name(address), idc.GetLongPrm(idc.INF_LONG_DN)) if name != None: name = re.sub(r'[A-Za-z0-9_]+::', r'', name) name = re.sub(r'^public: ', r'', name) name = re.sub(r'unsigned short const \*', r'const wchar_t *', name) name = re.sub(r'unsigned short \*', r'wchar_t *', name) return name else: return idaapi.get_func_name(address)
def _get_imported_names(self): '''Create and return a list of imported function names.''' tmp = [] for _, imp_entries in self._build_imports().items(): for imp_name in imp_entries: tmp_name = idc.Demangle(imp_name, idc.GetLongPrm(idc.INF_SHORT_DN)) if tmp_name: imp_name = tmp_name tmp.append(imp_name) return tmp
def init_demangled_names(*args): """ Creates dictionary of demangled names => address, that will be used further at double click on methods got from symbols. """ demangled_names.clear() for address, name in idautils.Names(): short_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) if short_name: demangled_names[short_name.split('(') [0]] = address - idaapi.get_imagebase() print "[DEBUG] Demangled names have been initialized"
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(symbol, idc.GetLongPrm(idc.INF_SHORT_DN)) func = demangled.split('::', 1)[1] base = func.split('(', 1)[0] return base or None except: return None
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(method_symbol, idc.GetLongPrm(idc.INF_SHORT_DN)) if not demangled: return None classname = demangled.split('::', 1)[0] if classname == demangled: return None return classname
def block_split(output_file, startEA, endEA): curName = GetFunctionName(startEA); dem = idc.Demangle(curName, idc.GetLongPrm(INF_SHORT_DN)); if dem != None: curName = dem; first=startEA h = idautils.Heads(startEA, endEA) for i in h: mnem = idc.GetMnem(i) if mnem == "call" and i != endEA: first=idc.NextHead(i, endEA+1)
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(symbol, idc.GetLongPrm(idc.INF_LONG_DN)) func = demangled.split('::', 1)[1] args = func.split('(', 1)[1] args = args.rsplit(')', 1)[0].strip() return args except: return None
def imp_cb(self, ea, name, ord1): """Callback passed to idaapi.enum_import_name in buildImportDictionary(). Sets the name of the PE segment in which the import table resides, and inserts current import in dictionary of imported APIS""" if self.firstImport: self.imports_segment_name = idaapi.get_segm_name(ea) self.firstImport = False demangled_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) if not demangled_name: self.import_dict[ea] = (name, self.curr_mod_name) else: self.import_dict[ea] = (demangled_name, self.curr_mod_name) return True
def getText(self, addy): #print "Fetching text for %08x" % addy color = idaapi.SCOLOR_STRING if addy == function.top(addy): name = idc.NameEx(addy, addy) try: name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) except: pass else: name = idc.NameEx(addy, addy) if name: return idaapi.COLSTR(" %s " % name, color) else: return idaapi.COLSTR(" 0x%08x " % addy, color)
def cls_split_block(fp, startEA, endEA): curName = GetFunctionName(startEA) dem = idc.Demangle(curName, idc.GetLongPrm(INF_SHORT_DN)) if dem != None: curName = dem first = startEA h = idautils.Heads(startEA, endEA) for i in h: mnem = idc.GetMnem(i) if mnem == "call" and i != endEA: print >> fp, "%#010x %#010x %s" % ( first, idc.NextHead(i, endEA + 1) - 1, curName) first = idc.NextHead(i, endEA + 1) if first < endEA: print >> fp, "%#010x %#010x %s" % (first, endEA - 1, curName)
def decrypt(argv, funcName): myEH = flare_emu.EmuHelper() print("decrypting...") mu = myEH.emulateRange(idc.get_name_ea_simple(funcName), stack=[0, argv[0], argv[1]], memAccessHook=mem_hook) decrypted_data = myEH.getEmuBytes(argv[0], argv[1]) print('decrypted: {}'.format(decrypted_data)) # make string in idb file if funcName == "DecryptAsciiStr": # make ascii str idc.MakeStr(argv[0], argv[0] + argv[1]) if funcName == "DecryptUnicodeStr": # make unicode str old_type = idc.GetLongPrm(INF_STRTYPE) idc.SetLongPrm(idc.INF_STRTYPE, idc.ASCSTR_UNICODE) idc.MakeStr(argv[0], argv[0] + (argv[1] * 2)) idc.SetLongPrm(idc.INF_STRTYPE, old_type) return decrypted_data
def get_function_name(ea): """ Get the real function name """ # Try to demangle funcName = idc.Demangle(idc.GetFunctionName(ea), idc.GetLongPrm(idc.INF_SHORT_DN)) if funcName: first_parens = funcName.find("(") if first_parens != -1: funcName = funcName[0:first_parens] # Function name is not mangled if not funcName: funcName = idc.GetFunctionName(ea) if funcName is None or funcName is "": funcName = idc.Name(ea) return funcName
def init_demangled_names(*args): """ Creates dictionary of demangled names => address, that will be used further at double click on methods got from symbols. """ demangled_names.clear() for address, name in idautils.Names(): short_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) if short_name: demangled_names[short_name.split('(')[0]] = address - idaapi.get_imagebase() # Names can have templates and should be transformed before creating local type name = re.sub(r'[<>]', '_t_', name) # Thunk functions with name like "[thunk]:CWarmupHostProvider::Release`adjustor{8}'" result = re.search(r"(\[thunk\]:)?([^`]*)(.*\{(\d+)}.*)?", short_name) name, adjustor = result.group(2), result.group(4) if adjustor: demangled_names[name + "_adj_" + adjustor] = address - idaapi.get_imagebase() print "[DEBUG] Demangled names have been initialized"
def cls_split_block(fp, start_ea, end_ea): """ ``idaapi.Flowchart`` does not consider function calls as basic block boundaries. This function takes a range of addresses and splits additional basic blocks. """ cur_name = idc.GetFunctionName(start_ea) dem_name = idc.Demangle(cur_name, idc.GetLongPrm(idc.INF_SHORT_DN)) if dem_name != None: cur_name = dem_name first = start_ea block = idautils.Heads(start_ea, end_ea) for inst in block: mnem = idc.GetMnem(inst) if mnem == 'call' and inst != end_ea: fp.write('%#010x %#010x %s\n' % (first, idc.NextHead(inst, end_ea + 1) - 1, cur_name)) first = idc.NextHead(inst, end_ea + 1) if first < end_ea: fp.write('%#010x %#010x %s\n' % (first, end_ea - 1, cur_name))
def get_function_name(ea): """ Get the real function name """ # Try to demangle function_name = idc.Demangle(idc.GetFunctionName(ea), idc.GetLongPrm(idc.INF_SHORT_DN)) if function_name: function_name = function_name.split("(")[0] # Function name is not mangled if not function_name: function_name = idc.GetFunctionName(ea) if not function_name: function_name = idc.Name(ea) # If we still have no function name, make one up. Format is - 'UNKN_FNC_4120000' if not function_name: function_name = "UNKN_FNC_%s" % hex(ea) return function_name
def main(): #print('INF_VERSION: %s' % (str(idc.GetLongPrm(idc.INF_VERSION)))) #print('INF_PROCNAME: %s' % (str(idc.GetLongPrm(idc.INF_PROCNAME)))) #print('INF_COMPILER: %s' % (str(idc.GetLongPrm(idc.INF_COMPILER)))) #print('INF_FILETYPE: %s' % (str(idc.GetLongPrm(idc.INF_FILETYPE)))) processor = str(idc.GetLongPrm(idc.INF_PROCNAME)) is_x86 = processor == 'metapc' is_ARM = processor == 'ARM' if not is_x86: idc.Message('*** Sorry, currently only supported x86.\n') return def_struct() load_metadata() #return code_reg, meta_reg = analyze_reg() if code_reg != idc.BADADDR: analyze_code_reg(code_reg) if meta_reg != idc.BADADDR: analyze_meta_reg(meta_reg, code_reg) init_array = analyze_init_array() analyze_invoke_unityengine() analyze_invoke_library() print('%X: INIT_IL2CPP' % (idc.LocByName('INIT_IL2CPP'))) print('%X: %s' % (code_reg, idc.Name(code_reg))) print('%X: %s' % (meta_reg, idc.Name(meta_reg))) print('%X: .init_array' % (init_array))
def demangle(string): return idc.Demangle(string, idc.GetLongPrm(idc.INF_LONG_DN))