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 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
parser.add_argument("-l", "--generate-lst", action="store_true", default=False, help="Generate disassembly listing file" ) args = parser.parse_args(args=idc.ARGV[1:]) if args.debug: _DEBUG = True # for batch mode: ensure IDA is done processing if args.batch: analysis_flags = idc.GetShortPrm(idc.INF_START_AF) analysis_flags &= ~idc.AF_IMMOFF # turn off "automatically make offset" heuristic idc.SetShortPrm(idc.INF_START_AF, analysis_flags) idaapi.autoWait() myname = idc.GetInputFile() mypath = path.dirname(__file__) EMAP = {} EMAP_DATA = {} if args.std_defs: for defsfile in args.std_defs: sys.stdout.write("Loading Standard Definitions file: {0}\n".format(defsfile.name)) em_update, emd_update = parseDefsFile(defsfile) EMAP.update(em_update) EMAP_DATA.update(emd_update)
# Try to find the defs file or this OS OS_NAME = args.os os_defs_file = os.path.join(tools_disass_dir, "defs", "{}.txt".format(args.os)) if os.path.isfile(os_defs_file): args.std_defs.insert(0, os_defs_file) # Load in all defs files, include custom ones. for defsfile in args.std_defs: with open(defsfile, "r") as df: DEBUG("Loading Standard Definitions file: {0}".format(defsfile)) parse_os_defs_file(df) # Turn off "automatically make offset" heuristic, and set some # other sane defaults. idc.SetShortPrm(idc.INF_START_AF, 0xdfff) idc.SetShortPrm(idc.INF_AF2, 0xfffd) # Ensure that IDA is done processing DEBUG("Using Batch mode.") idaapi.autoWait() DEBUG("Starting analysis") try: # Pre-define a bunch of symbol names and their addresses. Useful when reading # a core dump. if args.syms: for line in args.syms: name, ea_str = line.strip().split(" ") ea = int(ea_str, base=16) if not is_internal_code(ea):