def pre_hook(self): self.unhook() hooks.idb.unhook() idc.SetCharPrm(idc.INF_AUTO, True) idc.Wait() idaapi.request_refresh(idaapi.IWID_STRUCTS | idaapi.IWID_ENUMS | idaapi.IWID_XREFS) idc.SetCharPrm(idc.INF_AUTO, False) idaapi.request_refresh(idaapi.IWID_STRUCTS | idaapi.IWID_ENUMS | idaapi.IWID_XREFS) self.hook() hooks.idb.hook()
def start(self): logger.info("YaCo.start()") self.YaCoUI.hook() try: self.ida_hooks.unhook() self.initial_load() idc.Wait() self.ida_hooks.hook() except: traceback.print_exc() self.YaCoUI.unhook() self.ida_hooks.unhook() logger.error('Error during load cache, YaCo is disabled !') idc.SetCharPrm(idc.INF_AUTO, False) for menu_item in self.yaco_menus: name = menu_item[0] text = menu_item[1] callback = menu_item[2] shortcut = menu_item[3] handler = YaCoHandler(self, callback) action = idaapi.action_desc_t(name, text, handler, shortcut, "") idaapi.register_action(action) idaapi.attach_action_to_menu("Edit/YaTools/", name, idaapi.SETMENU_APP) if PROFILE_YACO_LOADING: self.pr.disable() f = open("yaco-loading.profile", 'w') ps = pstats.Stats(self.pr, stream=f).sort_stats('time') ps.print_stats() f.close()
def update(self): # pydevd.settrace() logger.debug("Yaco.update()") (modified_object_ids_str, deleted_object_ids_str, modified_files, _deleted_files) = self.repo_manager.update_cache() modified_object_ids = [] deleted_object_ids = [] for obj_id in modified_object_ids_str: modified_object_ids.append(ya.YaToolObjectId_From_String(obj_id)) for obj_id in deleted_object_ids_str: deleted_object_ids.append(ya.YaToolObjectId_From_String(obj_id)) logger.debug("delete objects") # fixme do something logger.debug("invalidate objects") # fixme do something logger.debug("loading XML") logger.debug("modified files : %r", modified_files) memory_exporter = ya.MakeModel() logger.debug("exporting XML to memory") ya.MakeXmlFilesDatabaseModel(modified_files).accept( memory_exporter.visitor) logger.debug("unhook") self.ida_hooks.unhook() logger.debug("export mem->ida") ya.export_to_ida(memory_exporter.model, self.hash_provider, ya.UseFrames) idc.SetCharPrm(idc.INF_AUTO, True) idc.Wait() idc.SetCharPrm(idc.INF_AUTO, False) idc.Refresh() logger.debug("hook") self.ida_hooks.hook()
def load_file(li, neflags, format): idaapi.set_processor_type("arm", SETPROC_ALL|SETPROC_FATAL) f = load_nxo(li) if f.armv7: idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_PC_FLAT) else: idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_64BIT) idc.SetCharPrm(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1) loadbase = 0x60000000 if f.armv7 else 0x7100000000 f.binfile.seek(0) as_string = f.binfile.read(f.bssoff) idaapi.mem2base(as_string, loadbase) for start, end, name, kind in f.sections: if name.startswith('.got'): kind = 'CONST' idaapi.add_segm(0, loadbase+start, loadbase+end, name, kind) segm = idaapi.get_segm_by_name(name) if kind == 'CONST': segm.perm = idaapi.SEGPERM_READ elif kind == 'CODE': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC elif kind == 'DATA': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE elif kind == 'BSS': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2) # do imports # TODO: can we make imports show up in "Imports" window? undef_count = 0 for s in f.symbols: if not s.shndx and s.name: undef_count += 1 last_ea = max(loadbase + end for start, end, name, kind in f.sections) undef_entry_size = 8 undef_ea = ((last_ea + 0xFFF) & ~0xFFF) + undef_entry_size # plus 8 so we don't end up on the "end" symbol idaapi.add_segm(0, undef_ea, undef_ea+undef_count*undef_entry_size, "UNDEF", "XTRN") segm = idaapi.get_segm_by_name("UNDEF") segm.type = idaapi.SEG_XTRN idaapi.update_segm(segm) for i,s in enumerate(f.symbols): if not s.shndx and s.name: idc.MakeQword(undef_ea) idaapi.do_name_anyway(undef_ea, s.name) s.resolved = undef_ea undef_ea += undef_entry_size elif i != 0: assert s.shndx s.resolved = loadbase + s.value if s.name: if s.type == STT_FUNC: print hex(s.resolved), s.name idaapi.add_entry(s.resolved, s.resolved, s.name, 0) else: idaapi.do_name_anyway(s.resolved, s.name) else: # NULL symbol s.resolved = 0 funcs = set() for s in f.symbols: if s.name and s.shndx and s.value: if s.type == STT_FUNC: funcs.add(loadbase+s.value) got_name_lookup = {} for offset, r_type, sym, addend in f.relocations: target = offset + loadbase if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32): if not sym: print 'error: relocation at %X failed' % target else: idaapi.put_long(target, sym.resolved) elif r_type == R_ARM_RELATIVE: idaapi.put_long(target, idaapi.get_long(target) + loadbase) elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64): idaapi.put_qword(target, sym.resolved + addend) if addend == 0: got_name_lookup[offset] = sym.name elif r_type == R_AARCH64_RELATIVE: idaapi.put_qword(target, loadbase + addend) if addend < f.textsize: funcs.add(loadbase + addend) else: print 'TODO r_type %d' % (r_type,) ida_make_offset(f, target) for func, target in f.plt_entries: if target in got_name_lookup: addr = loadbase + func funcs.add(addr) idaapi.do_name_anyway(addr, got_name_lookup[target]) funcs |= find_bl_targets(loadbase, loadbase+f.textsize) for addr in sorted(funcs, reverse=True): idc.AutoMark(addr, AU_CODE) idc.AutoMark(addr, AU_PROC) return 1
def make_stackframe(self, object_version, address): object_id = object_version.get_id() parent_object_id = object_version.get_parent_object_id() # associate stack frame id to function id self.stackframes_functions[object_id] = parent_object_id # association stackframe id to internal struc id eaFunc = object_version.get_object_address() logger.debug("stackframe[%s] : address of function is 0x%08X" % (self.hash_provider.hash_to_string(object_id), eaFunc)) attributes = object_version.get_attributes() stack_lvars = None stack_regvars = None stack_args = None try: stack_lvars = self.yatools.hex_string_to_address( attributes["stack_lvars"]) stack_regvars = self.yatools.hex_string_to_address( attributes["stack_regvars"]) stack_args = self.yatools.hex_string_to_address( attributes["stack_args"]) except KeyError: logger.warning("Stackframe at %s has missing attribute" % self.yatools.address_to_hex_string(eaFunc)) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X" % (self.hash_provider.hash_to_string(object_id), eaFunc)) self.analyze_function(eaFunc) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X after reanalysis" % (self.hash_provider.hash_to_string(object_id), eaFunc)) idc.SetCharPrm(idc.INF_AUTO, 1) idc.Wait() idc.SetCharPrm(idc.INF_AUTO, 0) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X after full reanalysis" % (self.hash_provider.hash_to_string(object_id), eaFunc)) idc.MakeFrame(eaFunc, stack_lvars, stack_regvars, stack_args) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X after idc.MakeFrame" % (self.hash_provider.hash_to_string(object_id), eaFunc)) else: self.struc_ids[object_id] = stack_frame.id _yatools_ida_exporter.set_struct_id(object_id, stack_frame.id) stack_lvars = None try: stack_lvars = self.yatools.hex_string_to_address( object_version.get_attributes()["stack_lvars"]) except KeyError: logger.warning( "Stackframe at %s has no stack_lvars attribute" % self.yatools.address_to_hex_string(eaFunc)) if stack_lvars is not None: logger.debug( "Clearing everything for stackframe at 0x%08X, with stack_lvars=0x%04X", eaFunc, stack_lvars) self.clear_struc_fields( stack_frame.id, object_version.get_size(), object_version.get_xrefed_id_map().iterkeys(), member_type=ya.OBJECT_TYPE_STACKFRAME_MEMBER, name_offset=stack_lvars)
def make_data(self, object_version, address): size = 0 try: size = object_version.get_size() except KeyError: pass flags = None try: flags = object_version.get_object_flags() except KeyError: pass if size == 0: idc.MakeUnkn(address, idc.DOUNK_EXPAND) else: if flags is not None: if idc.isASCII(flags): try: str_type = object_version.get_string_type() YaToolIDATools.check_and_set_str_type(str_type) except KeyError: pass idc.MakeStr(address, address + size) idc.SetFlags(address, flags) if idc.isStruct(flags): found = False for xref_offset_operand, xref_id_attr in object_version.get_xrefed_id_map( ).iteritems(): (xref_offset, xref_operand) = xref_offset_operand for xref_hash, xref_attrs in xref_id_attr: if xref_hash in self.struc_ids: struc_id = self.struc_ids[xref_hash] if DEBUG_EXPORTER: logger.debug( "making unknown from 0x%08X to 0x%08X" % (address, address + size)) idaapi.do_unknown_range( address, size, idc.DOUNK_DELNAMES) # idc.MakeUnkn(address, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # for i in xrange(1, size): # MakeName(address + i, "") # idc.MakeUnkn(address + i, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # idc.MakeStructEx uses idaapi.doStruct (but asks for name while # we already have the struc id) if DEBUG_EXPORTER: logger.debug( "Making struc at %s : %s (sizeof(%s)=0x%08X, size=0x%08X, flags=0x%08X" % (self.yatools.address_to_hex_string( address), self.yatools.address_to_hex_string( struc_id), idaapi.get_struc_name(struc_id), idc.GetStrucSize(struc_id), size, flags)) idc.SetCharPrm(idc.INF_AUTO, True) idc.Wait() if idaapi.doStruct(address, size, struc_id) == 0: if DEBUG_EXPORTER: logger.warning("Making struc failed") idc.SetCharPrm(idc.INF_AUTO, False) # idc.SetFlags(address, flags) found = True else: logger.error( "bad struc flags : idc.isStruct is true but no xref available for object %s" % self.hash_provider.hash_to_string( object_version.get_id())) if not found: logger.error( "bad struc flags : idc.isStruct is true " "but no struc available for object %s (%s)" % (self.hash_provider.hash_to_string( object_version.get_id()), object_version.get_name())) else: idc.MakeData(address, flags & (idc.DT_TYPE | idc.MS_0TYPE), size, 0) else: idc.MakeData(address, idc.FF_BYTE, size, 0) self.make_name(object_version, address, False) self.set_type(object_version, address)
def load_one_file(li, options, idx, basename=None): bypass_plt = OPT_BYPASS_PLT in options f = load_nxo(li) if idx == 0: if f.armv7: idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_PC_FLAT) else: idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_64BIT) idc.SetCharPrm(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1) # don't create tails idc.set_inf_attr(idc.INF_AF, idc.get_inf_attr(idc.INF_AF) & ~idc.AF_FTAIL) if OPT_LOAD_31_BIT in options: loadbase = 0x8000000 step = 0x1000000 elif f.armv7: loadbase = 0x60000000 step = 0x10000000 else: loadbase = 0x7100000000 step = 0x100000000 loadbase += idx * step f.binfile.seek(0) as_string = f.binfile.read(f.bssoff) idaapi.mem2base(as_string, loadbase) seg_prefix = basename if basename is not None else '' for start, end, name, kind in f.sections: if name.startswith('.got'): kind = 'CONST' idaapi.add_segm(0, loadbase+start, loadbase+end, seg_prefix+name, kind) segm = idaapi.get_segm_by_name(seg_prefix+name) if kind == 'CONST': segm.perm = idaapi.SEGPERM_READ elif kind == 'CODE': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC elif kind == 'DATA': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE elif kind == 'BSS': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2) # do imports # TODO: can we make imports show up in "Imports" window? undef_count = 0 for s in f.symbols: if not s.shndx and s.name: undef_count += 1 last_ea = max(loadbase + end for start, end, name, kind in f.sections) undef_entry_size = 8 undef_ea = ((last_ea + 0xFFF) & ~0xFFF) + undef_entry_size # plus 8 so we don't end up on the "end" symbol undef_seg = basename + '.UNDEF' if basename is not None else 'UNDEF' idaapi.add_segm(0, undef_ea, undef_ea+undef_count*undef_entry_size, undef_seg, 'XTRN') segm = idaapi.get_segm_by_name(undef_seg) segm.type = idaapi.SEG_XTRN idaapi.update_segm(segm) for i,s in enumerate(f.symbols): if not s.shndx and s.name: idc.MakeQword(undef_ea) idaapi.do_name_anyway(undef_ea, s.name) s.resolved = undef_ea undef_ea += undef_entry_size elif i != 0: assert s.shndx s.resolved = loadbase + s.value if s.name: if s.type == STT_FUNC: idaapi.add_entry(s.resolved, s.resolved, s.name, 0) else: idaapi.do_name_anyway(s.resolved, s.name) else: # NULL symbol s.resolved = 0 funcs = set() for s in f.symbols: if s.name and s.shndx and s.value: if s.type == STT_FUNC: funcs.add(loadbase+s.value) symend = loadbase+s.value+s.size if Dword(symend) != 0: funcs.add(symend) got_name_lookup = {} for offset, r_type, sym, addend in f.relocations: target = offset + loadbase if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32): if not sym: print 'error: relocation at %X failed' % target else: idaapi.put_long(target, sym.resolved) elif r_type == R_ARM_RELATIVE: idaapi.put_long(target, idaapi.get_long(target) + loadbase) elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64): idaapi.put_qword(target, sym.resolved + addend) if addend == 0: got_name_lookup[offset] = sym.name elif r_type == R_AARCH64_RELATIVE: idaapi.put_qword(target, loadbase + addend) if addend < f.textsize: funcs.add(loadbase + addend) else: print 'TODO r_type %d' % (r_type,) ida_make_offset(f, target) for func, target in f.plt_entries: if target in got_name_lookup: addr = loadbase + func funcs.add(addr) idaapi.do_name_anyway(addr, got_name_lookup[target]) if not f.armv7: funcs |= find_bl_targets(loadbase, loadbase+f.textsize) if bypass_plt: plt_lookup = f.plt_lookup for pco in xrange(0, f.textsize, 4): pc = loadbase + pco d = Dword(pc) if (d & 0x7c000000) == (0x94000000 & 0x7c000000): imm = d & 0x3ffffff if imm & 0x2000000: imm |= ~0x1ffffff if 0 <= imm <= 2: continue target = (pc + imm * 4) - loadbase if target in plt_lookup: new_target = plt_lookup[target] + loadbase new_instr = (d & ~0x3ffffff) | (((new_target - pc) / 4) & 0x3ffffff) idaapi.put_long(pc, new_instr) for pco in xrange(0, f.textsize, 4): pc = loadbase + pco d = Dword(pc) if d == 0x14000001: funcs.add(pc + 4) for pc, _ in f.eh_table: funcs.add(loadbase + pc) for addr in sorted(funcs, reverse=True): idaapi.auto_make_proc(addr) return 1
def check_and_set_str_type(new_type): global latest_str_type if latest_str_type != new_type: latest_str_type = new_type if idc.GetCharPrm(idc.INF_STRTYPE) != new_type: idc.SetCharPrm(idc.INF_STRTYPE, new_type)
def EnableAutoAnalysis(): global do_wait idc.SetCharPrm(idc.INF_AUTO, True) do_wait = True idc.Wait()
def DisableAutoAnalysis(): global do_wait idc.SetCharPrm(idc.INF_AUTO, False) do_wait = False