def relocate_bootblock(): bootblk_start = 0xF000 << 4 bootblk_end = 0x10000 << 4 bootblk_baseparagraph = 0xF000 bootblk_size = 0x10000 # 64 Kbyte idaapi.add_segm(bootblk_baseparagraph, bootblk_start, bootblk_end, "BOOTBLK", "CODE") bootblk = idaapi.get_segm_by_name("BOOTBLK") idaapi.set_segm_addressing(bootblk, 16) bootblk_addr = get_bootblock_start_address() print("Found bootblock at {0} addr!".format(hex(bootblk_addr))) relocate_segment(bootblk_addr, bootblk_start, bootblk_size)
def add_segment(start, size, name, kind): end = start + size idaapi.add_segm(0, start, 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 elif kind == 'IO': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE elif kind == 'RWX': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 2)
def load_file(li, neflags, format): idaapi.set_processor_type("arm", idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) f = load_nxo(li) if f.armv7: SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_PC_FLAT) else: SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_64BIT) SetCharPrm(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) 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: 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): AutoMark(addr, AU_CODE) 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
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 load_file(li, neflags, format): # Read in the bFLT header fields li.seek(0) (magic, version, entry, data_start, data_end, bss_end, stack_size, reloc_start, reloc_count, flags) = struct.unpack(">IIIIIIIIII", li.read(4 * 10)) # Check for the GZIP flag. # The loader doesn't de-compress GZIP'd files, as these can be easily decompressed with external tools prior to loading the file into IDA if (flags & FLAGS_GZIP) == FLAGS_GZIP: Warning( "Code/data is GZIP compressed. You probably want to decompress the bFLT file with the flthdr or gunzip_bflt utilities before loading it into IDA." ) # Load the file data into IDA li.file2base(BFLT_HEADER_SIZE, BFLT_HEADER_SIZE, data_end, True) # Add the .text .data and .bss segments idaapi.add_segm(0, BFLT_HEADER_SIZE, data_start, ".text", "CODE") idaapi.add_segm(0, data_start, data_end, ".data", "DATA") idaapi.add_segm(0, data_end, bss_end, ".bss", "BSS") if DEBUG: print "Created File Segments: " print "\t.text 0x%.8X - 0x%.8X" % (BFLT_HEADER_SIZE, data_start) print "\t.data 0x%.8X - 0x%.8X" % (data_start, data_end) print "\t.bss 0x%.8X - 0x%.8X" % (data_end, bss_end) # Entry point is at the beginning of the .text section idaapi.add_entry(entry, entry, "_start", 1) # Set default processor idaapi.set_processor_type(DEFAULT_CPU, SETPROC_ALL) # Explicitly set 32 bit addressing on .text segment idaapi.set_segm_addressing(idaapi.getseg(entry), 1) # prepare structure for set_fixup() fd = idaapi.fixup_data_t() fd.type = idaapi.FIXUP_OFF32 # Is there a global offset table? if (flags & FLAGS_GOTPIC) == FLAGS_GOTPIC: # Add a reptable comment and name the offset so that all references to GOT are obvious MakeRptCmt(data_start, "GLOBAL_OFFSET_TABLE") MakeName(data_start, "GOT") if DEBUG: print "Global Offset Table detected, patching..." # GOT starts at the beginning of the data section; loop through the data section, patching up valid GOT entries. i = data_start while i < data_end: # Get the next GOT entry li.seek(i) got_entry = struct.unpack("<I", li.read(4))[0] # The last GOT entry is -1 if got_entry == 0xFFFFFFFF: if DEBUG: print "Finished processing Global Offset Table." break # All other non-zero entries are valid GOT entries elif got_entry > 0: # The actual data is located at <original GOT entry> + <BFLT_HEADER_SIZE> new_entry = got_entry + BFLT_HEADER_SIZE if DEBUG: print "Replacing GOT entry value 0x%.8X with 0x%.8X at offset 0x%.8X" % ( got_entry, new_entry, i) # Replace the GOT entry with the correct pointer idaapi.put_long(i, new_entry) # add info about relocation to help analyzer fd.off = new_entry idaapi.set_fixup(i, fd) # Make each GOT entry a DWORD MakeDword(i) # Point i at the next GOT entry address i = i + 4 # Patch relocation addresses for i in range(0, reloc_count): try: # Get the next relocation entry. # Relocation entry = <address of bytes to be patched> - <BFLT_HEADER_SIZE> li.seek(reloc_start + (i * 4)) reloc_offset = struct.unpack(">I", li.read(4))[0] + BFLT_HEADER_SIZE # Sanity check, make sure the relocation offset is in a defined segment if reloc_offset < bss_end: try: # reloc_offset + base_offset == <pointer to actual data> - <BFLT_HEADER_SIZE> li.seek(reloc_offset) reloc_val = struct.unpack(">I", li.read(4))[0] if reloc_val == 0: # skip zero relocs # see fs/binfmt_flat.c if DEBUG: print "Skipping zero reloc at (0x%.8X)" % reloc_offset continue reloc_data_offset = reloc_val + BFLT_HEADER_SIZE if DEBUG: print "Patching reloc: (0x%.8X) == 0x%.8X" % ( reloc_offset, reloc_data_offset) # Replace pointer at reloc_offset with the address of the actual data idaapi.put_long(reloc_offset, reloc_data_offset) # add info about relocation to help analyzer fd.off = reloc_data_offset idaapi.set_fixup(reloc_offset, fd) except Exception, e: print "Error patching relocation entry #%d: %s" % (i, str(e)) elif DEBUG: print "Relocation entry #%d outside of defined file sections, skipping..." % i