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.set_inf_attr(idc.INFFL_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 load(infos): idc.set_inf_attr(idc.INF_COMPILER, 6) for info in infos: type = info.get('type', None) ida_name.set_name(info['start'], info['name']) if type: idc.SetType(info['start'], type)
def load_file(li, neflags, format): # pydevd_pycharm.settrace('localhost', port=1234, stdoutToServer=True, stderrToServer=True) fname = idaapi.get_input_file_path() psx = PsxExe(os.path.basename(fname), ONLY_FIRST, MIN_ENTROPY) psx.parse(li, True) idaapi.set_processor_type('mipsl', ida_idp.SETPROC_LOADER) idaapi.cvar.inf.af = \ idaapi.AF_CODE | idaapi.AF_JUMPTBL | idaapi.AF_USED | idaapi.AF_UNK | idaapi.AF_PROC | idaapi.AF_STKARG | \ idaapi.AF_REGARG | idaapi.AF_TRACE | idaapi.AF_VERSP | idaapi.AF_ANORET | idaapi.AF_MEMFUNC | \ idaapi.AF_TRFUNC | idaapi.AF_FIXUP | idaapi.AF_JFUNC | idaapi.AF_IMMOFF | idaapi.AF_STRLIT | \ idaapi.AF_MARKCODE | idaapi.AF_LVAR | idaapi.AF_PROCPTR | idaapi.AF_FLIRT psx.create_segments(li) im = idaapi.compiler_info_t() idaapi.inf_get_cc(im) im.id = idaapi.COMP_GNU im.cm = idaapi.CM_N32_F48 | idaapi.CM_M_NN | idaapi.CM_CC_CDECL im.defalign = 4 im.size_i = 4 im.size_b = 1 im.size_e = 4 im.size_s = 2 im.size_l = 4 im.size_ll = 8 im.size_ldbl = 8 idaapi.inf_set_cc(im) # Replace predefined macros and included directories by id # from IDA.CFG (see 'CC_PARMS' in Built-in C parser parameters) idaapi.set_c_macros(ida_idp.cfg_get_cc_predefined_macros(im.id)) idaapi.set_c_header_path(ida_idp.cfg_get_cc_header_path(im.id)) # Resetting new settings :) idc.set_inf_attr(idc.INF_COMPILER, im.id) idc.process_config_line("MIPS_DEFAULT_ABI=o32") detect = DetectPsyQ(psx.get_exe_name(), ONLY_FIRST, MIN_ENTROPY) version = detect.get_psyq_version(psx.rom_addr, psx.rom_addr + psx.rom_size) if len(version) > 0: psx.apply_psyq_signatures_by_version(version) idaapi.add_entry(psx.init_pc, psx.init_pc, 'start', 1) PsxExe.apply_til(version) psx.update_gp() return 1
def pre_hook(self): self.unhook() hooks.idb.unhook() idc.set_inf_attr(idc.INFFL_AUTO, True) idc.Wait() idaapi.request_refresh(idaapi.IWID_STRUCTS | idaapi.IWID_ENUMS | idaapi.IWID_XREFS) idc.set_inf_attr(idc.INFFL_AUTO, False) idaapi.request_refresh(idaapi.IWID_STRUCTS | idaapi.IWID_ENUMS | idaapi.IWID_XREFS) self.hook() hooks.idb.hook()
def update(self): memory_exporter = ya.MakeModel() modified_files = self.repo_manager.update_cache() 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) idc.set_inf_attr(idc.INFFL_AUTO, True) idc.Wait() idc.set_inf_attr(idc.INFFL_AUTO, False) idc.Refresh() logger.debug("hook") self.ida_hooks.hook()
def processor(processor): # Processor idc.set_processor_type(processor, SETPROC_LOADER) # Assembler idc.set_target_assembler(0x0) # Compiler idc.set_inf_attr(INF_COMPILER, COMP_GNU) # Loader Flags idc.set_inf_attr(INF_LFLAGS, LFLG_PC_FLAT | LFLG_COMPRESS) # Assume GCC3 names idc.set_inf_attr(INF_DEMNAMES, DEMNAM_GCC3) # Analysis Flags idc.set_inf_attr(INF_AF, 0xBFFFBFFF)
def processor(processor, til): # Processor idc.set_processor_type(processor, SETPROC_LOADER) # Assembler idc.set_target_assembler(0x0) # Type Library idc.add_default_til(til) # Compiler idc.set_inf_attr(INF_COMPILER, COMP_GNU) # Loader Flags idc.set_inf_attr(INF_LFLAGS, LFLG_PC_FLAT) # Assume GCC3 names idc.set_inf_attr(INF_DEMNAMES, DEMNAM_GCC3) # Analysis Flags idc.set_inf_attr(INF_AF, 0xC7FFFFD7)
def load_file(li, neflags, format): idaapi.set_processor_type( "arm", idaapi.SETPROC_LOADER_NON_FATAL | idaapi.SETPROC_LOADER) f = load_nxo(li) if f.armv7: idc.set_inf_attr( idc.INF_LFLAGS, idc.get_inf_attr(idc.INF_LFLAGS) | idc.LFLG_PC_FLAT) else: idc.set_inf_attr(idc.INF_LFLAGS, idc.get_inf_attr(idc.INF_LFLAGS) | idc.LFLG_64BIT) idc.set_inf_attr(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til('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) if f.text[1] != None: li.file2base(f.text[1], loadbase + f.text[2], loadbase + f.text[2] + f.text[3], True) if f.ro[1] != None: li.file2base(f.ro[1], loadbase + f.ro[2], loadbase + f.ro[2] + f.ro[3], True) if f.data[1] != None: li.file2base(f.data[1], loadbase + f.data[2], loadbase + f.data[2] + f.data[3], True) 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: idaapi.create_data(undef_ea, idc.FF_QWORD, 8, idaapi.BADADDR) idaapi.force_name(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.force_name(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_dword(target, sym.resolved) elif r_type == R_ARM_RELATIVE: idaapi.put_dword(target, idaapi.get_dword(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.force_name(addr, got_name_lookup[target]) funcs |= find_bl_targets(loadbase, loadbase + f.textsize) for addr in sorted(funcs, reverse=True): idc.AutoMark(addr, idc.AU_CODE) idc.AutoMark(addr, idc.AU_PROC) return 1
def set_start_cs(x): return idc.set_inf_attr(INF_START_CS, x)
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 procomp(self, processor, pointer, til): # Set Processor... idc.set_processor_type(processor, SETPROC_LOADER) # Set Compiler... idc.set_inf_attr(INF_COMPILER, COMP_GNU) idc.set_inf_attr(INF_MODEL, pointer) idc.set_inf_attr(INF_SIZEOF_BOOL, 0x1) idc.set_inf_attr(INF_SIZEOF_LONG, 0x8) idc.set_inf_attr(INF_SIZEOF_LDBL, 0x10) # Type Library idc.add_default_til(til) # Loader Flags idc.set_inf_attr(INF_LFLAGS, LFLG_64BIT) # Assume GCC3 names idc.set_inf_attr(INF_DEMNAMES, DEMNAM_GCC3) # File Type idc.set_inf_attr(INF_FILETYPE, FT_ELF) # Analysis Flags idc.set_inf_attr(INF_AF, 0xC7FFFFD7) # Return Bitsize return self.EI_CLASS
import idc import idaapi import binascii idc.set_inf_attr(INF_AF, idc.get_inf_attr(INF_AF) | AF_DODATA) print("Waiting for the end of the auto analysis...") idc.auto_wait() print("Autoanalysis done!") dumped_netnode_value = 'ca75b28848ea06bcae409699fa2510a03bbaf43bd167eecb17d52918187133a793ebf8d3270230c7164d7a79b53c2c3edd611ede975690784cf2c254abe8b587140d19a3f46b2be109bde1da1b7ed4d7c9f7b58135f2c296db4e86ad29b6f0b999b5599d40c3bae8b29d2cc06ecef63cba0e1b9a9505c1efe9019a7020127e100000000000000000000000000000000000000000000000000000000000000000' idaapi.netnode('$ user1', 0, False).kill() # deleting netnode with plain text info idaapi.netnode('$ original user', 0, False).supset(0, binascii.unhexlify(dumped_netnode_value)) idc.qexit(0)
def SetAppcallOptions(x): return idc.set_inf_attr(INF_APPCALL_OPTIONS, x)
import idc currentEA = '' currentMnem = '' prevMnem = '' nextMnem = '' currentOp = '' print("Running IDA setup script") print("Setting startup options") # set demangled names options to show names idc.set_inf_attr(INF_DEMNAMES, DEMNAM_NAME) # show the address next to each command idc.set_inf_attr(INF_OUTFLAGS, OFLG_SHOW_PREF) idc.set_inf_attr(INF_PREFFLAG, 0) print("Finished setting options") currentEA = idc.get_first_seg() currentEA = idc.next_head(currentEA, 0xFFFFFFFFFFFFFFFF) while (currentEA != BADADDR): currentMnem = idc.print_insn_mnem(currentEA) #Highlight call functions if (currentMnem == "call"): #check to see if it's a call pop nextMnem = idc.print_insn_mnem(idc.get_operand_value(currentEA, 0)) if nextMnem == "pop": idc.set_color(currentEA, CIC_ITEM, 0xff1d4a) idc.set_color(idc.get_operand_value(currentEA, 0), CIC_ITEM,
def Indent(x): return idc.set_inf_attr(INF_INDENT, x)
def procomp(self, processor, pointer, til): # Processor Type idc.set_processor_type(processor, SETPROC_LOADER) # Compiler Attributes idc.set_inf_attr(INF_COMPILER, COMP_GNU) idc.set_inf_attr(INF_MODEL, pointer) idc.set_inf_attr(INF_SIZEOF_BOOL, 0x1) idc.set_inf_attr(INF_SIZEOF_LONG, 0x8) idc.set_inf_attr(INF_SIZEOF_LDBL, 0x10) # Type Library idc.add_default_til(til) # Loader Flags idc.set_inf_attr(INF_LFLAGS, LFLG_64BIT) # Assume GCC3 Names idc.set_inf_attr(INF_DEMNAMES, DEMNAM_GCC3 | DEMNAM_NAME) # File Type idc.set_inf_attr(INF_FILETYPE, FT_ELF) # Analysis Flags # (unchecked) Delete instructions with no xrefs # (unchecked) Coagulate data segments in the final pass idc.set_inf_attr(INF_AF, 0xDFFFFFDF) # Return Bitsize return self.EI_CLASS
def StringStp(x): return idc.set_inf_attr(INF_STRLIT_BREAK, x)
def XrefShow(x): return idc.set_inf_attr(INF_XREFNUM, x)
def TailDepth(x): return idc.set_inf_attr(INF_MAXREF, x)
def HighVoids(x): return idc.set_inf_attr(INF_HIGH_OFF, x)
def CmtIndent(x): return idc.set_inf_attr(INF_COMMENT, x)
def load(infos): idc.set_inf_attr(idc.INF_COMPILER, 6) for info in infos: ida_name.set_name(info['start'], info['name']) if info['type']: idc.SetType(info['start'], info['type'])
def load(info): idc.set_inf_attr(idc.INF_COMPILER, info['compiler'])
def set_start_ip(x): return idc.set_inf_attr(INF_START_IP, x)
import idautils import os import argparse def parse_command(): parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument("--path", type=str, help="The directory where to store the generated .ida file") args = parser.parse_args() return args if __name__ == '__main__': idaapi.autoWait() #args = parse_command() #path = args.path print "open a new binary" path = "D:\\Code\\python\\binary_search\\Genius\\Gencoding-master\\raw-feature-extractor\\extracted-acfg" analysis_flags = get_inf_attr(idc.INF_AF) # 得到analysis_flags INF_AF analysis_flags &= ~AF_IMMOFF # AF_IMMOFF :将32位的指令操作转换为偏移量 # turn off "automatically make offset" heuristic idc.set_inf_attr(INF_AF, analysis_flags) #设置analysis_flags cfgs = get_func_cfgs_c(FirstSeg()) binary_name = GetInputFile() + '.cfg' fullpath = os.path.join(path, binary_name) pickle.dump(cfgs, open(fullpath,'w')) print binary_name idc.Exit(0)
def load_file(li, neflags, format): # Set flags idaapi.set_processor_type( "arm", idaapi.SETPROC_LOADER_NON_FATAL | idaapi.SETPROC_LOADER) idc.set_inf_attr(idc.INF_LFLAGS, idc.get_inf_attr(idc.INF_LFLAGS) | idc.LFLG_64BIT) idc.set_inf_attr(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til('gnulnx_arm64', 1) # Load IRAM memory li.seek(0) pk11 = li.read(PK1L_SIZE) idaapi.mem2base(pk11, PK1L_ADDRESS) # Add identity mappings add_segment(PK1L_ADDRESS, PK1L_SIZE, '.pk1_identity', 'RWX') add_segment(TZRAM_BASE, TZRAM_SIZE, '.tz_identity', 'RWX') # Emulate package1 to determine interesting extents emu = Emulator() emu.run_emulator(pk11) # Refresh IRAM contents to reflect any decompression that may have occurred. idaapi.mem2base(emu.read_mem(PK1L_ADDRESS, PK1L_SIZE), PK1L_ADDRESS) if not emu.found_smc_evp: # Set coldboot crt0 idc.create_insn(emu.entrypoint) idc.set_name(emu.entrypoint, 'coldboot_crt0') return 1 iram_mappings = [] dram_mappings = [] tzram_mappings = [] mmio_mappings = [] for m in emu.mappings: if is_tzram(m): tzram_mappings.append(m) elif is_dram(m): dram_mappings.append(m) elif is_iram(m): iram_mappings.append(m) else: assert is_mmio(m) mmio_mappings.append(m) for m in mmio_mappings: add_mmio_mapping(m) # Process IRAM mappings if len(iram_mappings) == 3: sorted_irams = sorted(iram_mappings, key=lambda m: m[2]) if [m[2] for m in sorted_irams] == [0x1000, 0x1000, 0x10000]: assert len(set([m[3] for m in sorted_irams])) == 2 if sorted_irams[1][3] == sorted_irams[2][3]: add_segment(sorted_irams[0][0], sorted_irams[0][2], '.bl_sync', 'IO') add_segment(sorted_irams[1][0], sorted_irams[1][2], '.sc7_fw', 'DATA') add_segment(sorted_irams[2][0], sorted_irams[2][2], '.sc7_tmp_save', 'DATA') else: assert sorted_irams[0][3] == sorted_irams[2][3] add_segment(sorted_irams[1][0], sorted_irams[1][2], '.bl_sync', 'IO') add_segment(sorted_irams[0][0], sorted_irams[0][2], '.sc7_fw', 'DATA') add_segment(sorted_irams[2][0], sorted_irams[2][2], '.sc7_tmp_save', 'DATA') else: print iram_mappings raise ValueError('Unknown IRAM mapping set') elif len(iram_mappings) == 2: sorted_irams = sorted(iram_mappings, key=lambda m: m[2]) if [m[2] for m in sorted_irams] == [0x1000, 0x10000]: assert len(set([m[3] for m in sorted_irams])) == 2 add_segment(sorted_irams[0][0], sorted_irams[0][2], '.bl_sync', 'IO') add_segment(sorted_irams[1][0], sorted_irams[1][2], '.sc7_tmp_save', 'DATA') else: print iram_mappings raise ValueError('Unknown IRAM mapping set') else: print iram_mappings raise ValueError('Unknown IRAM mapping set') # Process DRAM mappings if len(dram_mappings) == 2: sorted_drams = sorted(dram_mappings, key=lambda m: m[2]) if [m[2] for m in sorted_drams] == [0x1000, 0x10000]: add_segment(sorted_drams[0][0], sorted_drams[0][2], '.sc7_se_ctx', 'DATA') add_segment(sorted_drams[1][0], sorted_drams[1][2], '.sc7_sm_ctz', 'DATA') else: print dram_mappings raise ValueError('Unknown DRAM mapping set') else: print dram_mappings raise ValueError('Unknown DRAM mapping set') # Process TZRAM segments tzram_groups = [] for (vaddr, paddr, size, attr) in sorted(tzram_mappings, key=lambda m: m[0]): inserted = False for i in xrange(len(tzram_groups)): if vaddr == tzram_groups[i][-1][0] + tzram_groups[i][-1][ 2] and tzram_groups[i][-1][2] != 0x40000: tzram_groups[i].append((vaddr, paddr, size, attr)) inserted = True break if not inserted: tzram_groups.append([(vaddr, paddr, size, attr)]) for group in tzram_groups: print 'Group' for m in group: print ' %x %x %x %x' % m # Process groups for group in tzram_groups: if len(group) > 1: if is_executable(group[0]): # .text/.rodata/.rwdata :) if len(group) == 2: add_segment(group[0][0], group[0][2], '.text_rodata', 'CODE') add_segment(group[1][0], group[1][2], '.rwdata', 'DATA') load_mapping(emu, group[0]) load_mapping(emu, group[1]) else: assert len(group) == 3 add_segment(group[0][0], group[0][2], '.text', 'CODE') add_segment(group[1][0], group[1][2], '.rodata', 'CONST') add_segment(group[2][0], group[2][2], '.rwdata', 'DATA') load_mapping(emu, group[0]) load_mapping(emu, group[1]) load_mapping(emu, group[2]) elif is_executable(group[0]): assert len(group) == 1 vaddr, paddr, size, attr = group[0] if size > 0x8000: assert len( filter(lambda g: is_executable(g[0]) and g[0][2] > 0x8000, tzram_groups)) == 1 assert is_writable(group[0]) add_segment(vaddr, size, '.code', 'RWX') load_mapping(emu, group[0]) elif size == 0x2000: assert len( filter(lambda g: is_executable(g[0]) and g[0][2] == 0x2000, tzram_groups)) == 1 add_segment(vaddr, size, '.pk2ldr', 'RWX') load_mapping(emu, group[0]) else: assert size == 0x1000 assert len( filter(lambda g: is_executable(g[0]) and g[0][2] == 0x1000, tzram_groups)) == 1 add_segment(vaddr, size, '.vectors', 'CODE') load_mapping(emu, group[0]) elif len(group) == 1 and (group[0][2] == 0x10000 or group[0][2] == 0x40000): assert len( filter( lambda g: len(g) == 1 and not is_executable(g[0]) and (g[0][2] == 0x10000 or g[0][2] == 0x40000), tzram_groups)) == 1 assert not is_writable(group[0]) vaddr, paddr, size, attr = group[0] add_segment(vaddr, size, '.tzram_ro_view', 'CONST') elif len(group) == 1 and group[0][2] == 0x1000: vaddr, paddr, size, attr = group[0] pk2ldr_group = filter( lambda g: is_executable(g[0]) and g[0][2] == 0x2000, tzram_groups) assert len(pk2ldr_group) == 1 pk2ldr_group = pk2ldr_group[0][0] if paddr == emu.l3_table: add_segment(vaddr, size, '.l3_table', 'DATA') elif paddr == (emu.l3_table - 0x1000): add_segment(vaddr, size, '.l2_table', 'DATA') elif paddr == pk2ldr_group[1]: add_segment(vaddr, size, '.reused_stack0', 'DATA') elif paddr == (pk2ldr_group[1] + 0x1000): add_segment(vaddr, size, '.reused_stack1', 'DATA') elif vaddr == emu.phys_to_virt[ emu.ttbr & ~0xFFF][0] or vaddr == emu.core0_stack_page: add_segment(vaddr, size, '.shared_data', 'DATA') else: print 'Unknown Group' for m in group: print ' %x %x %x %x' % m assert False else: print 'Unknown Group' for m in group: print ' %x %x %x %x' % m assert False # Set vector types as code. for i, ctx in enumerate(['sp0', 'spx', 'a64', 'a32']): for j, kind in enumerate(['synch', 'irq', 'fiq', 'serror']): addr = emu.vbar + 0x200 * i + 0x80 * j name = '%s_%s_exception' % (ctx, kind) idc.create_insn(addr) idc.set_name(addr, name) # Set coldboot crt0 idc.create_insn(emu.entrypoint) idc.set_name(emu.entrypoint, 'coldboot_crt0') # Add SMC list entries assert len(emu.smc_lists) == 2 idc.set_name(emu.smc_lists_addr, 'g_smc_lists') for i, name in enumerate(['user', 'priv']): addr, num_entries, pad = emu.smc_lists[i] idc.set_name(addr, 'g_smc_list_%s' % name) for n in xrange(num_entries): id, access, func = up('<IIQ', emu.read_mem(addr + 0x10 * n, 0x10)) if func == 0: continue smc_name = get_smc_name(name == 'user', id) process_smc(func, smc_name) # We're done return 1
def load_file(li, neflags, fmt): idaapi.set_processor_type( "arm", idaapi.SETPROC_LOADER_NON_FATAL | idaapi.SETPROC_LOADER) idc.set_inf_attr(idc.INF_LFLAGS, idc.get_inf_attr(idc.INF_LFLAGS) | idc.LFLG_64BIT) idc.set_inf_attr(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til('gnulnx_arm64', 1) # Get the meta offset meta_ofs = find_kernel_meta(li) assert meta_ofs != -1 # Read important offsets. li.seek(meta_ofs + 0x40) text_base, init_base, init_base2, kernel_end = struct.unpack( '<QQQQ', li.read(0x20)) # Load the init segment. li.seek(0) init_data = li.read(KERNEL_INIT_SIZE) idaapi.mem2base(init_data, init_base) # Emulate the kernel init segment to determine interesting extents emu = Emulator() emu.run_emulator(init_base, init_data) builder = SegmentBuilder() builder.add_segment(init_base, KERNEL_INIT_SIZE, '.init', 'RWX') text_phys = 0 text_size = 0 ro_size = 0 rw_size = 0 core_dram_mappings = [] for (virt_addr, size, phys_addr, attr) in emu.mappings: print('%x, %x, %x, %x' % (virt_addr, size, phys_addr, attr)) assert attr in [ 0x4000000000078B, 0x78B, 0x6000000000078B, 0x6000000000070B, 0x60000000000607, 0x60000000000709 ] if attr == 0x78B or attr == 0x4000000000078B: # .text assert virt_addr == text_base builder.add_segment(virt_addr, size, '.text', 'CODE') li.seek(phys_addr - init_base) idaapi.mem2base(li.read(size), virt_addr) text_phys = phys_addr text_size = size elif attr == 0x6000000000078B: # .rodata assert text_size != 0 assert virt_addr == text_base + text_size builder.add_segment(virt_addr, size, '.rodata', 'CONST') li.seek(phys_addr - init_base) idaapi.mem2base(li.read(size), virt_addr) ro_size = size elif attr == 0x6000000000070B and virt_addr == text_base + text_size + ro_size: assert text_size != 0 assert ro_size != 0 # .rwdata builder.add_segment(virt_addr, size, '.rwdata', 'DATA') li.seek(phys_addr - init_base) idaapi.mem2base(li.read(size), virt_addr) rw_size = size elif attr == 0x60000000000607: # IO DEVICES = { (0x40000000, 0x40000): '.iram', (0x50041000, 0x01000): '.gicd', (0x50042000, 0x01000): '.gicc', (0x60001000, 0x01000): '.semaphore', (0x60004000, 0x01000): '.primary_ictlr', (0x60006000, 0x01000): '.clkrst', (0x60007000, 0x01000): '.flow_ctlr', (0x6000F000, 0x01000): '.evp', (0x70006000, 0x01000): '.uart', (0x7000E000, 0x01000): '.rtc_pmc', (0x70016000, 0x02000): '.atomics', (0x70019000, 0x01000): '.mc', (0x7001C000, 0x01000): '.mc0', (0x7001D000, 0x01000): '.mc1', } assert (phys_addr, size) in DEVICES.keys() name = DEVICES[(phys_addr, size)] builder.add_segment(virt_addr, size, name, 'IO') elif attr == 0x6000000000070B: # Kernel DRAM if phys_addr == (emu.ttbr & ~0xFFF) and size == 0x1000: builder.add_segment(virt_addr, size, '.ttbr1', 'DATA') else: core_dram_mappings.append( (virt_addr, size, phys_addr, attr)) else: # Linear DRAM assert attr == 0x60000000000709 idaapi.add_segm(0, virt_addr, virt_addr + size, '.linear_dram', 'DATA', idaapi.ADDSEG_SPARSE) segm = idaapi.get_segm_by_name('.linear_dram') segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 2) assert len(core_dram_mappings) % 5 == 0 if len(core_dram_mappings) // 5 == 3: # 1.0.0-style core local mappings assert core_dram_mappings[ 0 + 0][2] == core_dram_mappings[0 + 3][2] - 0x2000 assert core_dram_mappings[ 0 + 3][2] == core_dram_mappings[0 + 6][2] - 0x2000 assert core_dram_mappings[ 0 + 6][2] == core_dram_mappings[0 + 9][2] - 0x2000 assert core_dram_mappings[0 + 0][2] == core_dram_mappings[0 + 12][2] assert core_dram_mappings[ 1 + 0][2] == core_dram_mappings[1 + 3][2] - 0x2000 assert core_dram_mappings[ 1 + 3][2] == core_dram_mappings[1 + 6][2] - 0x2000 assert core_dram_mappings[ 1 + 6][2] == core_dram_mappings[1 + 9][2] - 0x2000 assert core_dram_mappings[1 + 0][2] == core_dram_mappings[1 + 12][2] assert core_dram_mappings[ 2 + 0][2] == core_dram_mappings[2 + 3][2] - 0x1000 assert core_dram_mappings[ 2 + 3][2] == core_dram_mappings[2 + 6][2] - 0x1000 assert core_dram_mappings[ 2 + 6][2] == core_dram_mappings[2 + 9][2] - 0x1000 assert core_dram_mappings[2 + 0][2] == core_dram_mappings[2 + 12][2] builder.add_segment(core_dram_mappings[0][0], 0xA000 * 4, '.core_local_regions', 'DATA') builder.add_segment(core_dram_mappings[3 * 4 + 0][0], core_dram_mappings[3 * 4 + 0][1], '.current_common_stack', 'DATA') builder.add_segment(core_dram_mappings[3 * 4 + 1][0], core_dram_mappings[3 * 4 + 1][1], '.current_main_stack', 'DATA') builder.add_segment(core_dram_mappings[3 * 4 + 2][0], core_dram_mappings[3 * 4 + 2][1], '.current_context', 'DATA') elif len(core_dram_mappings) // 5 == 4: # 3.0.0-style core local mappings assert core_dram_mappings[ 0 + 0][2] == core_dram_mappings[0 + 4][2] - 0x2000 assert core_dram_mappings[ 0 + 4][2] == core_dram_mappings[0 + 8][2] - 0x2000 assert core_dram_mappings[ 0 + 8][2] == core_dram_mappings[0 + 12][2] - 0x2000 assert core_dram_mappings[0 + 0][2] == core_dram_mappings[0 + 16][2] assert core_dram_mappings[ 1 + 0][2] == core_dram_mappings[1 + 4][2] - 0x2000 assert core_dram_mappings[ 1 + 4][2] == core_dram_mappings[1 + 8][2] - 0x2000 assert core_dram_mappings[ 1 + 8][2] == core_dram_mappings[1 + 12][2] - 0x2000 assert core_dram_mappings[1 + 0][2] == core_dram_mappings[1 + 16][2] assert core_dram_mappings[ 2 + 0][2] == core_dram_mappings[2 + 4][2] - 0x2000 assert core_dram_mappings[ 2 + 4][2] == core_dram_mappings[2 + 8][2] - 0x2000 assert core_dram_mappings[ 2 + 8][2] == core_dram_mappings[2 + 12][2] - 0x2000 assert core_dram_mappings[2 + 0][2] == core_dram_mappings[2 + 16][2] assert core_dram_mappings[ 3 + 0][2] == core_dram_mappings[3 + 4][2] - 0x1000 assert core_dram_mappings[ 3 + 4][2] == core_dram_mappings[3 + 8][2] - 0x1000 assert core_dram_mappings[ 3 + 8][2] == core_dram_mappings[3 + 12][2] - 0x1000 assert core_dram_mappings[3 + 0][2] == core_dram_mappings[3 + 16][2] builder.add_segment(core_dram_mappings[0][0], 0xE000 * 4, '.core_local_regions', 'DATA') builder.add_segment(core_dram_mappings[4 * 4 + 0][0], core_dram_mappings[4 * 4 + 0][1], '.current_common_stack', 'DATA') builder.add_segment(core_dram_mappings[4 * 4 + 1][0], core_dram_mappings[4 * 4 + 1][1], '.current_main_stack', 'DATA') builder.add_segment(core_dram_mappings[4 * 4 + 2][0], core_dram_mappings[4 * 4 + 2][1], '.current_idle_stack', 'DATA') builder.add_segment(core_dram_mappings[4 * 4 + 3][0], core_dram_mappings[4 * 4 + 3][1], '.current_context', 'DATA') seg_prefix = '' for start, end, name, kind in builder.flatten(): idaapi.add_segm(0, start, 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 elif kind == 'RWX': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE | idaapi.SEGPERM_EXEC elif kind == 'IO': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 2) # Set vector types as code. for i, ctx in enumerate(['sp0', 'spx', 'a64', 'a32']): for j, kind in enumerate(['synch', 'irq', 'fiq', 'serror']): addr = emu.vbar + 0x200 * i + 0x80 * j name = '%s_%s_exception' % (kind, ctx) idc.create_insn(addr) idc.set_name(addr, name) # Set .init as code. idc.create_insn(init_base) idc.set_name(init_base, 'crt0') # Set text start as code. idc.create_insn(text_base) idc.set_name(text_base, 'HorizonKernelMain') # Patch movk instructions to be better understandable by ida. li.seek(text_phys - init_base) text = li.read(text_size) ro_rw = li.read(ro_size + rw_size) patch_movk_to_adrp(text_base, text, ro_rw, emu.mappings) return 1
def LowVoids(x): return idc.set_inf_attr(INF_LOW_OFF, x)