def load_file(li, neflags, format): # Select the PC processor module idaapi.set_processor_type("BPF", SETPROC_ALL|SETPROC_FATAL) buf = read_whole_file(li, 8) if not buf: return 0 start = 0x0 seg = idaapi.segment_t() size = len(buf) end = start + size # Create the segment seg.startEA = start seg.endEA = end seg.bitness = 1 # 32-bit idaapi.add_segm_ex(seg, "bpf_c", "CODE", 0) # Copy the bytes idaapi.mem2base(buf, start, end) # add entry point idaapi.add_entry(start, start, "start", 1) # add comment to beginning of disassembly idaapi.describe(start, True, "BPF bytecode disassembly") # Mark for analysis AutoMark(start, AU_CODE) setup_enums() return 1
def create_segment(context_dir: str, segment: dict, is_be: bool): """Create segment in IDA and map in the data from the file :param context_dir: Parent directory of the context files :param segment: Segment information from _index.json :param is_be: True if processor is big endian, otherwise False """ input_name = get_input_name() if Path(segment["name"]).name != input_name: ida_seg = idaapi.segment_t() ida_seg.start_ea = segment["start"] ida_seg.end_ea = segment["end"] ida_seg.bitness = 1 if is_be else 0 if segment["permissions"]["r"]: ida_seg.perm |= ida_segment.SEGPERM_READ if segment["permissions"]["w"]: ida_seg.perm |= ida_segment.SEGPERM_WRITE if segment["permissions"]["x"]: ida_seg.perm |= ida_segment.SEGPERM_EXEC idaapi.add_segm_ex(ida_seg, Path(segment["name"]).name, "CODE", idaapi.ADDSEG_OR_DIE) else: idaapi.add_segm_ex(ida_seg, Path(segment["name"]).name, "DATA", idaapi.ADDSEG_OR_DIE) if segment["content_file"]: write_segment_bytes(segment["start"], PurePath(context_dir, segment["content_file"]))
def create_load_seg(li, start, end, modificationType, name, segmentType="CODE"): # add_segm(0, start, end, name, "") seg = idaapi.segment_t() seg.start_ea = start seg.end_ea = end seg.bitness = 1 # 32-bit idaapi.add_segm_ex(seg, name, "", 0) # AddSeg(start, end, 0, 1, idaapi.saAbs, idaapi.scPub) offset = li.tell() # li.file2base(offset, start, end, 0) data = li.read(end - start) # put_dword if modificationType == 2: byteswapped = bytearray([0]) * len(data) byteswapped[0::2] = data[1::2] byteswapped[1::2] = data[0::2] # idaapi.mem2base(str(byteswapped), start, end) for i in range(0, end - start): idaapi.put_byte(start + i, byteswapped[i]) else: idaapi.mem2base(data, start, end)
def load_file(li, neflags, format): idaapi.set_processor_type("n2t-hack", idaapi.SETPROC_ALL|idaapi.SETPROC_FATAL) li.seek(0) hack_data = li.read(li.size()) hack_instructions = [int(instruction, 2) for instruction in hack_data.splitlines()] hack_instructions_bin = ''.join(struct.pack("!H", instruction) for instruction in hack_instructions) print "Found %d hack instructions" % len(hack_instructions) seg = idaapi.segment_t() seg.startEA= 0 seg.endEA = len(hack_instructions) seg.align = idaapi.saAbs seg.comb = idaapi.scPriv seg.bitness = 0 # 16-bit idaapi.add_segm_ex(seg, "Hack-ROM", "CODE", idaapi.ADDSEG_OR_DIE) # This method seems to change in next versions. #idaapi.mem2base(hack_instructions_bin, 0, -1) idaapi.mem2base(hack_instructions_bin, 0) return 1
def add_segment(start, end, name, type_): segment = idaapi.segment_t() segment.startEA = start segment.endEA = end segment.bitness = 1 # 32-bit idaapi.add_segm_ex(segment, name, type_, idaapi.ADDSEG_SPARSE | idaapi.ADDSEG_OR_DIE)
def myAddSeg(startea, endea, base, use32, name, clas): s = idaapi.segment_t() s.startEA = startea s.endEA = endea s.sel = idaapi.setup_selector(base) s.bitness = use32 s.align = idaapi.saRelPara s.comb = idaapi.scPub idaapi.add_segm_ex(s, name, clas, idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
def load_file(li, neflags, format): # Select the PC processor module idaapi.set_processor_type("EVM", SETPROC_ALL | SETPROC_FATAL) # TODO: detect and emulate contract creation code li.seek(0) buf = li.read(li.size()) if not buf: return 0 if buf[0:2] == '0x': print "Detected hex" new_buf = buf[2:].strip().rstrip() buf_set = set() for c in new_buf: buf_set.update(c) hex_set = set(list('0123456789abcdef')) if buf_set <= hex_set: # subset print "Replacing original buffer with hex decoded version" buf = new_buf.decode('hex') # Load all shellcode into different segments start = 0x0 seg = idaapi.segment_t() size = len(buf) end = start + size # Create the segment seg.startEA = start seg.endEA = end seg.bitness = 1 # 32-bit idaapi.add_segm_ex(seg, "evm", "CODE", 0) # TODO: make segments for stack, memory, storage # Copy the bytes idaapi.mem2base(buf, start, end) # check for swarm hash and make it data instead of code swarm_hash_address = buf.find('ebzzr0') if swarm_hash_address != -1: print "Swarm hash detected, making it data" for i in range(swarm_hash_address - 1, swarm_hash_address + 42): MakeByte(i) ida_bytes.set_cmt(swarm_hash_address - 1, "swarm hash", True) # add entry point idaapi.add_entry(start, start, "start", 1) # add comment to beginning of disassembly idaapi.describe(start, True, "EVM bytecode disassembly") # Mark for analysis AutoMark(start, AU_CODE) #setup_enums() return 1
def seg(fd, segm, ss, se, ft, lf): base = segm.start_ea del_segm(segm.start_ea) text = idaapi.segment_t() text.bitness = 1 # 32-bit text.end_ea = lf + 0x8 text.start_ea = base idaapi.add_segm_ex(text, "__text", "CODE", idaapi.ADDSEG_OR_DIE)
def create_segment(segment: Segment): segm = idaapi.segment_t() segm.bitness = segment.seg_bitness segm.start_ea = segment.start segm.end_ea = segment.end segm_type = segment.seg_type.name.upper() idaapi.add_segm_ex(segm, segment.name, segm_type, idaapi.ADDSEG_OR_DIE)
def myAddSeg(startea, endea, base, use32, name, clas): s = idaapi.segment_t() s.start_ea = startea s.end_ea = endea s.sel = idaapi.setup_selector(base) s.bitness = use32 s.align = idaapi.saRelPara s.comb = idaapi.scPub idaapi.add_segm_ex(s, name, clas, idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
def add_seg(startea, endea, bank, name): s = idaapi.segment_t() s.start_ea = startea + bank * 0x10000 s.end_ea = endea + bank * 0x10000 s.sel = idaapi.setup_selector(bank * 0x1000) s.bitness = 0 s.align = idaapi.saRelPara s.comb = idaapi.scPub idaapi.add_segm_ex(s, name, "", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
def AddWasmSegment(startea, endea, name, cls=None, base=0): s = segment_t() s.start_ea = startea s.end_ea = endea s.sel = setup_selector(base) s.use32 = 0 s.align = saRelByte # saRelDble s.perm = SEGPERM_EXEC | SEGPERM_WRITE | SEGPERM_READ fl = ADDSEG_OR_DIE idaapi.add_segm_ex(s, name, cls, fl) return
def make_seg(start, size): seg = idaapi.segment_t() seg.bitness = 1 # 32bit seg.startEA = start seg.endEA = start + size seg.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE | idaapi.SEGPERM_EXEC # NOTE: we have no real way to determine what is code or not. for example, 40010001 kinda looks # like it begins with code, but really the entire thing is data. seg.type = idaapi.SEG_CODE # they never seem to use dflash anyways idaapi.add_segm_ex(seg, 'cflash' if start < 0x80000 else 'dflash', 'CODE', 0)
def __call__(self): s = idaapi.segment_t() s.start_ea = self.start_ea s.end_ea = self.end_ea s.orgbase = self.orgbase s.align = self.align s.comb = self.comb s.perm = self.perm s.bitness = self.bitness s.flags = self.flags idaapi.add_segm_ex(s, self.name.encode('utf-8'), self.class_, idaapi.ADDSEG_QUIET | idaapi.ADDSEG_NOSREG)
def make_segment(base, size, name): s = idc.get_segm_by_sel(base) if not s == 0xffffffff: return s = idaapi.segment_t() s.startEA = base s.endEA = base+size s.sel = 0 s.bitness = 1 s.comb = idaapi.scPub idaapi.add_segm_ex(s, name.strip('.').upper(), "", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_SPARSE)
def make_seg(addr_range, record_type = 0): seg = idaapi.segment_t() seg.bitness = 1 # 32bit seg.startEA = addr_range[0] seg.endEA = addr_range[1] seg.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE | idaapi.SEGPERM_EXEC seg.type = idaapi.SEG_CODE seg.align = idaapi.saRelByte # Force regions to be CODE if record_type == 1: idaapi.add_segm_ex(seg, 'ROM', 'CODE', idaapi.ADDSEG_NOSREG) else: idaapi.add_segm_ex(seg, 'RAM', 'CODE', idaapi.ADDSEG_NOSREG)
def AdditionalSegment(size, offset, name): s = idaapi.segment_t() step = 0x1000000 - 1 s.startEA = idaapi.freechunk(0x1000000, size, step) s.endEA = s.startEA + size s.sel = idaapi.setup_selector((s.startEA - offset) >> 4) s.type = idaapi.SEG_DATA if byte_size("X") > 2: s.bitness = 1 else: s.bitness = 0 idaapi.add_segm_ex(s, name, "DATA", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE) return s.startEA - offset
def AdditionalSegment(size, offset, name): s = idaapi.segment_t() step = 0x1000000-1 s.startEA = idaapi.freechunk(0x1000000, size, step) s.endEA = s.startEA + size s.sel = idaapi.setup_selector((s.startEA-offset) >> 4) s.type = idaapi.SEG_DATA if byte_size('X') > 2: s.bitness = 1 else: s.bitness = 0 idaapi.add_segm_ex(s, name, "DATA", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_OR_DIE) return s.startEA - offset
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ li.seek(0) vmlinux = li.read(li.size()) do_get_bits(kallsyms, vmlinux) do_kallsyms(kallsyms, vmlinux) # print_kallsyms(kallsyms, vmlinux) if kallsyms['arch'] == 'arm': idaapi.set_processor_type('arm', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) elif kallsyms['arch'] == 'mips' and not kallsyms['is_big_endian']: idaapi.set_processor_type('mipsl', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) elif kallsyms['arch'] == 'mips' and not kallsyms['is_big_endian']: idaapi.set_processor_type('mipsb', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) elif kallsyms['arch'] == 'x86': idaapi.set_processor_type('metapc', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) #NOT tested if kallsyms['bits'] == 64: idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT li.file2base(0, kallsyms['_start'], kallsyms['_start'] + li.size(), True) s = idaapi.segment_t() s.bitness = kallsyms['bits'] / 32 s.startEA = kallsyms['_start'] s.endEA = kallsyms['_start'] + li.size() idaapi.add_segm_ex(s, ".text", "CODE", idaapi.ADDSEG_OR_DIE) for i in xrange(kallsyms['numsyms']): if kallsyms['type'][i] in ['t', 'T']: idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 1) else: idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 0) print "Android/Linux vmlinux loaded..." return 1
def _AddSegment(self, name, base_address, data=None): """Add a segment to the IDB with some basic options set for convenience.""" s = idaapi.segment_t() s.startEA = base_address s.endEA = base_address + len(data) s.bitness = 1 # 32-bit s.align = idaapi.saRelByte s.comb = idaapi.scPub s.sel = idaapi.setup_selector(0) # We mark the segments as code, as we know these are loops in memory idaapi.add_segm_ex(s, name, "CODE", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE) idaapi.mem2base(data, base_address)
def AddSegment(name, base_address, data): """Add a segment to the IDB with some basic options set for convenience.""" s = idaapi.segment_t() s.startEA = base_address s.endEA = base_address + len(data) s.bitness = 1 # 32-bit s.align = idaapi.saRelByte s.comb = idaapi.scPub s.sel = idaapi.setup_selector(0) idaapi.add_segm_ex(s, name, None, idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE) idaapi.mem2base(data, base_address)
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ # Select the PC processor module idaapi.set_processor_type("metapc", ida_idp.SETPROC_LOADER) # read MBR into buffer li.seek(0, os.SEEK_SET) buf = li.read(li.size()) seg = idaapi.segment_t() start = 0x7C00 size = len(buf) end = start + size # Create the segment seg.start_ea = start seg.end_ea = end seg.bitness = 0 # 16-bit idaapi.add_segm_ex(seg, "seg0", "CODE", 0) # Copy the bytes idaapi.mem2base(buf, start, end) # add entry point idaapi.add_entry(start, start, "start", 1) strid = add_struct_def() idaapi.set_name(start + 0x1BE, "MBR_PARTITION_TABLE", idaapi.SN_CHECK) str_size = idaapi.get_struc_size(strid) idaapi.create_struct(start + 0x1BE, str_size, strid) idaapi.set_name(510, "MBR_SIGN", idaapi.SN_CHECK) # Mark for analysis AutoMark(start, AU_CODE) load_debugger("bochs", 0) return 1
def add_seg(start_ea, end_ea, name, cls, use32, align, comb): s = idaapi.segment_t() s.startEA = start_ea s.endEA = end_ea s.sel = idaapi.setup_selector(0) s.bitness = use32 s.align = align s.comb = comb return idaapi.add_segm_ex(s, name, cls, idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_OR_DIE)
def add_seg(start_ea, end_ea, name, cls, use32, align, comb): s = idaapi.segment_t() s.startEA = start_ea s.endEA = end_ea s.sel = idaapi.setup_selector(0) s.bitness = use32 s.align = align s.comb = comb return idaapi.add_segm_ex(s, name, cls, idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ # Select the PC processor module idaapi.set_processor_type("metapc", SETPROC_ALL|SETPROC_FATAL) buf = read_whole_file(li) r = extract_pdf_shellcode(buf) if not r: return 0 # Load all shellcode into different segments start = 0x10000 seg = idaapi.segment_t() for id, ver, n, sc in r: size = len(sc) end = start + size # Create the segment seg.startEA = start seg.endEA = end seg.bitness = 1 # 32-bit idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0) # Copy the bytes idaapi.mem2base(sc, start, end) # Mark for analysis AutoMark(start, AU_CODE) # Compute next loading address start = ((end / 0x1000) + 1) * 0x1000 # Select the bochs debugger LoadDebugger("bochs", 0) return 1
def create(offset, size, name, **kwds): '''Create a segment at /offset/ and /size/ and name it /name/ /bits/ can be used to specify the bit size of the segment /comb/ can be used to specify any flags (idaapi.sc*) /align/ can be used to specify paragraph alignment (idaapi.sa*) /org/ specifies the origin of the segment (must be paragraph aligned due to ida) ''' s = idaapi.get_segm_by_name(name) if s is not None: logging.fatal( "segment.create(%x, %x, %r, %r) : a segment with the specified name already exists : %s", offset, size, name, kwds, name) return None bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset). abits()) # FIXME: use disassembler default bit length instead of 32 if bits == 16: ## create a selector with the requested origin org = kwds.get('org', 0) if org & 0xf > 0: logging.fatal( "segment.create(%x, %x, %r, %r) : origin (.org) is not aligned to the size of a paragraph (0x10):%x", offset, size, name, kwds, org) return None para = offset / 16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para - kwds.get('org', 0) / 16) & 0xffffffff) else: ## auto-create a selector for everything else sel = idaapi.setup_selector( kwds['selector'] ) if 'selector' in kwds else idaapi.find_free_selector() # create segment. ripped from idc s = idaapi.segment_t() s.startEA = offset s.endEA = offset + size s.sel = sel s.bitness = {16: 0, 32: 1, 64: 2}[bits] s.comb = kwds.get('comb', idaapi.scPub) # public s.align = kwds.get('align', idaapi.saRelByte) # paragraphs res = idaapi.add_segm_ex(s, name, "", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_SPARSE) if res == 0: logging.warn( "segment.create(%x, %x, %r, %r) : unable to add a new segment", offset, size, name, kwds) res = idaapi.del_selector(sel) #assert res != 0 return None return s
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ # Select the PC processor module idaapi.set_processor_type("metapc", SETPROC_LOADER) buf = read_whole_file(li) r = extract_pdf_shellcode(buf) if not r: return 0 # Load all shellcode into different segments start = 0x10000 seg = idaapi.segment_t() for id, ver, n, sc in r: size = len(sc) end = start + size # Create the segment seg.start_ea = start seg.end_ea = end seg.bitness = 1 # 32-bit idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0) # Copy the bytes idaapi.mem2base(sc, start, end) # Mark for analysis AutoMark(start, AU_CODE) # Compute next loading address start = ((end / 0x1000) + 1) * 0x1000 # Select the bochs debugger load_debugger("bochs", 0) return 1
def load_file(li, neflags, format): """Load the file into database Args: li: a file-like object which can be used to access the input data neflags: options selected by the user, see loader.hpp Returns: 0-failure 1-ok """ idaapi.set_processor_type("sh4", SETPROC_ALL | SETPROC_FATAL) li.seek(0, idaapi.SEEK_END) size = li.tell() li.seek(0) rom_data = li.read(size) s = idaapi.segment_t() s.startEA = 0 s.endEA = size s.bitness = 1 # 32-bit s.align = idaapi.saRelByte s.comb = idaapi.scPub s.sel = idaapi.setup_selector(0) idaapi.add_segm_ex(s, "ROM", "DATA", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE) idaapi.mem2base(rom_data, 0) headr = JasperThe2kCat() headr.AnotateHeader(binary_file=li) headr.MakeStrings(binary_file=li) gentries = gameEntries() gentries.readGameLoops(binary_file=li) gentries.CreateSegments(binary_file=li) gentries.makeDWordTables() gentries.makeDWordTables(start_address=0x2a0, end_address=0x1000) gentries.addIDA_entry() print("load ok") return 1
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ li.seek(0) vmlinux = li.read(li.size()) do_get_arch(kallsyms, vmlinux) do_kallsyms(kallsyms, vmlinux) # print_kallsyms(kallsyms, vmlinux) if kallsyms['numsyms'] == 0: print '[!]get kallsyms error...' return 0 idaapi.set_processor_type("arm", SETPROC_ALL|SETPROC_FATAL) if kallsyms['arch'] == 64: idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT li.file2base(0, kallsyms['_start'], kallsyms['_start']+li.size(), True) s = idaapi.segment_t() s.bitness = kallsyms['arch'] / 32 s.startEA = kallsyms['_start'] s.endEA = kallsyms['_start']+li.size() idaapi.add_segm_ex(s,".text","CODE",ADDSEG_OR_DIE) for i in xrange(kallsyms['numsyms']): if kallsyms['type'][i] in ['t','T']: idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 1) else: idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 0) print "Android vmlinux loaded..." return 1
def process(fd, bitness): enable_auto(False) base_addr = 0x0 if bitness == 1: idaapi.set_processor_type('ARM:ARMv7-A', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) idaapi.get_inf_structure().lflags |= idaapi.LFLG_PC_FLAT elif bitness == 2: idaapi.set_processor_type("arm", idaapi.SETPROC_LOADER_NON_FATAL) idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT fd.seek(0, idaapi.SEEK_END) size = fd.tell() segm = idaapi.segment_t() segm.bitness = bitness segm.start_ea = 0 segm.end_ea = size if base_addr != 0: print("[*] Rebasing to address 0x%x" % (base_addr)) idaapi.rebase_program(base_addr, MSF_NOFIX) idaapi.autoWait() idaapi.add_segm_ex(segm, "SecureROM", "CODE", idaapi.ADDSEG_OR_DIE) fd.seek(0) fd.file2base(0, 0, size, False) print("[*] Pass One") print("[*] Defining functions") #locate_functions(segm) print("[*] Defining early initialation instructions") build_jump_table(segm) print("[*] Attempting to force string definitons") global string_start, string_end string_start, string_end = process_strings(segm) print("[*] Pass Two") print("[*] Hunting for and defining symbols") symbolicate(segm)
def AddDefaultSH4Segments(self): """Add a segment to the IDB with some basic options set for convenience.""" base_address = 0x0C000000 # Create segments on the range of 0x04000000 bytes for segment in range(5): name = "Area_%d" % (segment + 3) s = idaapi.segment_t() s.startEA = base_address s.endEA = base_address + 0x04000000 s.bitness = 1 # 32-bit s.align = idaapi.saRelByte s.comb = idaapi.scPub s.sel = idaapi.setup_selector(0) # We mark the segments as code, as we know these are loops in memory idaapi.add_segm_ex(s, name, 'CODE', idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE) base_address += 0x04000000 # Second set of segments (now is the privileged ones) base_address = 0x80000000 # Create segments on the range of 0x04000000 bytes for segment in range(4): name = "Priv_%d" % (segment + 1) s = idaapi.segment_t() s.startEA = base_address if base_address == 0xE0000000: s.endEA = base_address + 0x10000000 else: s.endEA = base_address + 0x20000000 s.bitness = 1 # 32-bit s.align = idaapi.saRelByte s.comb = idaapi.scPub s.sel = idaapi.setup_selector(0) # We mark the segments as code, as we know these are loops in memory idaapi.add_segm_ex(s, name, None, idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE) base_address += 0x20000000
def create(offset, size, name, **kwds): '''Create a segment at /offset/ and /size/ and name it /name/ /bits/ can be used to specify the bit size of the segment /comb/ can be used to specify any flags (idaapi.sc*) /align/ can be used to specify paragraph alignment (idaapi.sa*) /org/ specifies the origin of the segment (must be paragraph aligned due to ida) ''' s = idaapi.get_segm_by_name(name) if s is not None: logging.fatal("segment.create(%x, %x, %r, %r) : a segment with the specified name already exists : %s", offset, size, name, kwds, name) return None bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits()) # FIXME: use disassembler default bit length instead of 32 if bits == 16: ## create a selector with the requested origin org = kwds.get('org',0) if org&0xf > 0: logging.fatal("segment.create(%x, %x, %r, %r) : origin (.org) is not aligned to the size of a paragraph (0x10):%x", offset, size, name, kwds, org) return None para = offset/16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para-kwds.get('org',0)/16)&0xffffffff) else: ## auto-create a selector for everything else sel = idaapi.setup_selector(kwds['selector']) if 'selector' in kwds else idaapi.find_free_selector() # create segment. ripped from idc s = idaapi.segment_t() s.startEA = offset s.endEA = offset+size s.sel = sel s.bitness = {16:0,32:1,64:2}[bits] s.comb = kwds.get('comb', idaapi.scPub) # public s.align = kwds.get('align', idaapi.saRelByte) # paragraphs res = idaapi.add_segm_ex(s, name, "", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_SPARSE) if res == 0: logging.warn("segment.create(%x, %x, %r, %r) : unable to add a new segment", offset, size, name, kwds) res = idaapi.del_selector(sel) #assert res != 0 return None return s
def new(offset, size, name, **kwds): """Create a segment at ``offset`` with ``size`` and name it according to ``name``. ``bits`` can be used to specify the bit size of the segment ``comb`` can be used to specify any flags (idaapi.sc*) ``align`` can be used to specify paragraph alignment (idaapi.sa*) ``org`` specifies the origin of the segment (must be paragraph aligned due to ida) """ s = idaapi.get_segm_by_name(name) if s is not None: logging.fatal("{:s}.new({:x}, {:x}, {!r}, {!r}) : a segment with the specified name already exists : {:s}".format(__name__, offset, size, name, kwds, name)) return None bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits()) # FIXME: use disassembler default bit length instead of 32 if bits == 16: ## create a selector with the requested origin org = kwds.get('org',0) if org&0xf > 0: logging.fatal("{:s}.new({:x}, {:x}, {!r}, {!r}) : origin (.org) is not aligned to the size of a paragraph (0x10) : {:x}".format(__name__, offset, size, name, kwds, org)) return None para = offset/16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para-kwds.get('org',0)/16)&0xffffffff) else: ## auto-create a selector for everything else sel = idaapi.setup_selector(kwds['selector']) if 'selector' in kwds else idaapi.find_free_selector() # create segment. ripped from idc s = idaapi.segment_t() s.startEA = offset s.endEA = offset+size s.sel = sel s.bitness = {16:0,32:1,64:2}[bits] s.comb = kwds.get('comb', idaapi.scPub) # public s.align = kwds.get('align', idaapi.saRelByte) # paragraphs res = idaapi.add_segm_ex(s, name, "", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_SPARSE) if res == 0: logging.warn("{:s}.new({:x}, {:x}, {!r}, {!r}) : unable to add a new segment".format(__name__, offset, size, name, kwds)) res = idaapi.del_selector(sel) #assert res != 0 return None return s
def load_file(li, neflags, format): """ Load the SEGA Master System ROM :param li: Loader input :param neflags: :param format: :return: 1 on success, otherwise 0 """ idaapi.set_processor_type('z80', idaapi.SETPROC_LOADER) is_reload = (neflags & idaapi.NEF_RELOAD) != 0 if is_reload: return 1 # Create ROM segment rom_seg = idaapi.segment_t() rom_seg.start_ea = 0x0000 rom_seg.end_ea = 0xbfff rom_seg.bitness = 0 idaapi.add_segm_ex(rom_seg, 'ROM', 'CODE', idaapi.ADDSEG_OR_DIE) # Read file into ROM segment li.seek(0) li.file2base(0, 0, li.size(), False) # Create RAM Segment ram_seg = idaapi.segment_t() ram_seg.start_ea = 0xc000 ram_seg.end_ea = 0xdfff ram_seg.bitness = 0 idaapi.add_segm_ex(ram_seg, 'RAM', 'DATA', idaapi.ADDSEG_OR_DIE) # Create RAM mirror segment ram_mirror_seg = idaapi.segment_t() ram_mirror_seg.start_ea = 0xe000 ram_mirror_seg.end_ea = 0xffff ram_mirror_seg.bitness = 0 idaapi.add_segm_ex(ram_mirror_seg, 'RAM_MIRROR', 'DATA', idaapi.ADDSEG_OR_DIE) # Define the I/O ports create_io_ports() # Disassemble reset vectors create_reset_vectors() # Specify entry idaapi.add_entry(0x0000, 0x0000, 'RST0', 1) return 1
def new(offset, size, name, **kwds): """Create a segment at `offset` with `size` and name it according to `name`. The keyword `bits` can be used to specify the bit size of the segment The keyword `comb` can be used to specify any flags (idaapi.sc*) The keyword `align` can be used to specify paragraph alignment (idaapi.sa*) The keyword `org` specifies the origin of the segment (must be paragraph aligned due to ida) """ res = utils.string.to(name) # find the segment according to the name specified by the user seg = idaapi.get_segm_by_name(res) if seg is not None: raise E.DuplicateItemError(u"{:s}.new({:#x}, {:+#x}, \"{:s}\"{:s}) : A segment with the specified name (\"{:s}\") already exists.".format(__name__, offset, size, utils.string.escape(name, '"'), u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', utils.string.escape(name, '"'))) # FIXME: use disassembler default bit length instead of 32 bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits()) ## create a selector with the requested origin if bits == 16: org = kwds.get('org',0) if org & 0xf > 0: raise E.InvalidTypeOrValueError(u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : The specified origin ({:#x}) is not aligned to the size of a paragraph (0x10).".format(__name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', org)) para = offset/16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para-kwds.get('org',0)/16)&0xffffffff) ## if the user specified a selector, then use it elif 'sel' in kwds or 'selector' in kwds: sel = kwds.get('sel', kwds.get('selector', idaapi.find_free_selector())) ## choose the paragraph size defined by the user elif 'para' in kwds or 'paragraphs' in kwds: para = kwds.get('paragraph', kwds.get('para', 1)) sel = idaapi.setup_selector(para) ## find a selector that is 1 paragraph size, elif idaapi.get_selector_qty(): sel = idaapi.find_selector(1) # otherwise find a free one and set it. else: sel = idaapi.find_free_selector() idaapi.set_selector(sel, 1) # populate the segment_t using code ripped from the idc module seg = idaapi.segment_t() seg.startEA = offset seg.endEA = offset+size seg.sel = sel seg.bitness = {16:0,32:1,64:2}[bits] seg.comb = kwds.get('comb', idaapi.scPub) # public seg.align = kwds.get('align', idaapi.saRelByte) # paragraphs # now we can add our segment_t to the database res = utils.string.to(name) ok = idaapi.add_segm_ex(seg, res, "", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_SPARSE) if not ok: ok = idaapi.del_selector(sel) if not ok: logging.warn(u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to delete the created selector ({:#x}) for the new segment.".format(__name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', sel)) raise E.DisassemblerError(u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to add a new segment.".format(__name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '')) return seg
def load_file(li, netflags, format): nsis = nsisfile.NSIS.from_path(idaapi.get_input_file_path()) # Create NSIS netnode. nsis_netnode = idaapi.netnode("$ NSIS", 0, True) nsis_netnode.hashset("VERSION_MAJOR", nsis.version_major) nsis_netnode.hashset("VERSION_MINOR", nsis.version_minor) # Create blocks segments. for name, n, sclass in BLOCKS: offset = nsis.header.blocks[n].offset if offset == 0: continue content = nsis.block(n) # Create block segment seg = idaapi.segment_t() seg.startEA = offset seg.endEA = offset + len(content) idaapi.add_segm_ex(seg, name, sclass, 0) idaapi.mem2base(content, offset) # Add one virtual segment to hold variables. var_seg = idaapi.segment_t() var_start = align(nsis.size()) var_seg.startEA = var_start var_seg.endEA = var_start + 0x1000 # Size chosen arbitrarily, should be enough. idaapi.add_segm_ex(var_seg, "VARS", "BSS", 0) # Create standard vars. for i, v in enumerate(nrs.strings.SYSVAR_NAMES.values()): idaapi.do_name_anyway(var_seg.startEA + i + 20, "$" + v) code_base = nsis.header.blocks[fileform.NB_ENTRIES].offset # Create sections functions. for i, section in enumerate(nsis.sections): if section.code == PTR_NONE: continue name = nsis.get_string(section.name_ptr) if not name: name = "_section" + str(i) ea = code_base + nrs.entry_to_offset(section.code) cname = canonize_name(name) AddEntryPoint(ea, ea, cname, 1) # Mark pages handlers. for i, page in enumerate(nsis.pages): for fn in ["prefunc", "showfunc", "leavefunc"]: addr = getattr(page, fn) if addr != PTR_NONE: name = "_page_{}_{}".format(i, fn) ea = code_base + nrs.entry_to_offset(addr) AddEntryPoint(ea, ea, name, 1) # Mark installer handlers. for event in [ "Init", "InstSuccess", "InstFailed", "UserAbort", "GUIInit", "GUIEnd", "MouseOverSection", "VerifyInstDir", "SelChange", "RebootFailed", ]: addr = getattr(nsis.header, "code_on" + event) if addr != PTR_NONE: name = "_on" + event ea = code_base + nrs.entry_to_offset(addr) AddEntryPoint(ea, ea, name, 1) # Create strings. """ strings_data = nsis.block(fileform.NB_STRINGS) strings_off = nsis.header.blocks[fileform.NB_STRINGS].offset i = 0 while i < len(strings_data): decoded_string, length = \ nrs.strings.decode(strings_data, i, nsis.version_major) decoded_string = str(decoded_string) string_name = canonize_name(decoded_string) idaapi.make_ascii_string(strings_off + i, length, ASCSTR_C) idaapi.set_cmt(strings_off + i, decoded_string, True) idaapi.do_name_anyway(strings_off + i, string_name) i += length #""" # Set processor to nsis script. SetProcessorType("nsis", SETPROC_ALL | SETPROC_FATAL) return 1
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ li.seek(0) vmlinux = li.read(li.size()) do_get_arch(kallsyms, vmlinux) do_kallsyms(kallsyms, vmlinux) if kallsyms['numsyms'] == 0: print_log('[!]get kallsyms error...') return 0 idaapi.set_processor_type("arm", idaapi.SETPROC_ALL|idaapi.SETPROC_FATAL) if kallsyms['arch'] == 64: idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT li.file2base(0, kallsyms['_start'], kallsyms['_start']+li.size(), True) sinittext_addr = 0 max_sym_addr = 0 for i in range(kallsyms['numsyms']): if kallsyms['arch'] == 32: if kallsyms['address'][i] > 0xd0000000: continue if kallsyms['name'][i] == '_sinittext': sinittext_addr = kallsyms['address'][i] if kallsyms['address'][i] > max_sym_addr: max_sym_addr = kallsyms['address'][i] max_sym_addr = max_sym_addr + 1024 print_log("max_sym_addr = ", hex(max_sym_addr)) if (kallsyms['_start']+li.size()) > max_sym_addr: max_sym_addr = kallsyms['_start']+li.size() s = idaapi.segment_t() s.bitness = kallsyms['arch'] // 32 s.startEA = kallsyms['_start'] if sinittext_addr == 0: s.endEA = max_sym_addr else: s.endEA = sinittext_addr s.perm = 5 idaapi.add_segm_ex(s,".text","CODE",idaapi.ADDSEG_OR_DIE) if sinittext_addr > 0: s = idaapi.segment_t() s.bitness = kallsyms['arch'] // 32 s.startEA = sinittext_addr s.endEA = max_sym_addr s.perm = 7 idaapi.add_segm_ex(s,".data","DATA",idaapi.ADDSEG_OR_DIE) for i in range(kallsyms['numsyms']): if kallsyms['type'][i] in ['t','T']: idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 1) else: idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 0) print_log("Android/Linux vmlinux loaded...") return 1
def load_file(li, neflags, format): """ Load the SG/SMD ROM :param li: Loader input :param neflags: :param format: :return: 1 on success, otherwise 0 """ idaapi.set_processor_type('68000', idaapi.SETPROC_LOADER) is_reload = (neflags & idaapi.NEF_RELOAD) != 0 if is_reload: return 1 # Get ROM end li.seek(0x1a4) rom_end = struct.unpack('>I', li.read(4))[0] # Create ROM segment rom_seg = idaapi.segment_t() rom_seg.start_ea = 0 rom_seg.end_ea = rom_end rom_seg.bitness = 1 idaapi.add_segm_ex(rom_seg, 'ROM', 'CODE', idaapi.ADDSEG_OR_DIE) # Get RAM start/end li.seek(0x1a8) ram_start = struct.unpack('>I', li.read(4))[0] ram_end = struct.unpack('>I', li.read(4))[0] # Create RAM segment ram_seg = idaapi.segment_t() ram_seg.start_ea = ram_start ram_seg.end_ea = ram_end ram_seg.bitness = 1 idaapi.add_segm_ex(ram_seg, 'RAM', 'DATA', idaapi.ADDSEG_OR_DIE) # Read file into ROM segment li.seek(0) li.file2base(0, 0, rom_end, False) # Create Z80 memory segment z80_seg = idaapi.segment_t() z80_seg.start_ea = 0xa00000 z80_seg.end_ea = 0xa1ffff # Actually ends at 0xa0ffff, but for the sake of applying labels we make it 0xa1ffff z80_seg.bitness = 0 # 16 bit idaapi.add_segm_ex(z80_seg, 'Z80', 'DATA', idaapi.ADDSEG_OR_DIE) label_z80_memory() # Create a segment so we can create labels for VDP ports and debug registers misc_ports_regs = idaapi.segment_t() misc_ports_regs.start_ea = 0xc00000 misc_ports_regs.end_ea = 0xc00020 misc_ports_regs.bitness = 1 idaapi.add_segm_ex(misc_ports_regs, 'MISC', 'DATA', idaapi.ADDSEG_OR_DIE) label_misc_regs_ports() # Create interrupt vector table create_dword_and_name(0, 'StackOffset') create_dword_and_name(4, 'ProgramStart') create_interrupt_table() create_interrupt_handlers(li) # Create ROM info create_rom_info_block() # Set entry program_start = get_dword_at(li, 4) idaapi.add_entry(program_start, program_start, '_start', 1) return 1
def load_file(li, neflags, format): ''' Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok ''' idaapi.set_processor_type('cLEMENCy', idaapi.SETPROC_USER | idaapi.SETPROC_FATAL) li.seek(0) fileLen = li.size() data = convert(li.read(fileLen)) if len(data) > 0x4000000: # program too large return 0 idaname = "ida64" if __EA64__ else "ida" if sys.platform == "win32": _mod = ctypes.windll[idaname + ".wll"] elif sys.platform == "linux2": _mod = ctypes.cdll["lib" + idaname + ".so"] elif sys.platform == "darwin": _mod = ctypes.cdll["lib" + idaname + ".dylib"] create_bytearray_linput = _mod.create_bytearray_linput create_bytearray_linput.argtypes = (idaapi.POINTER(ctypes.c_ubyte), ctypes.c_int) create_bytearray_linput.restype = ctypes.c_int bufPointer = idaapi.cast(data, idaapi.POINTER(ctypes.c_ubyte)) retlinput = create_bytearray_linput(bufPointer, int(fileLen * 8 / 9 * 16 / 8)) file2base = _mod.file2base file2base.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int) file2base.restype = ctypes.c_int file2base(retlinput, 0, 0, int(fileLen * 8 / 9), idaapi.FILEREG_PATCHABLE) seg = idaapi.segment_t() seg.startEA = 0 seg.endEA = 0x4000000 # seg.bitness = 1 idaapi.add_segm_ex(seg, "PROGRAM", "CODE", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x4000000 seg.endEA = 0x400001e idaapi.add_segm_ex(seg, "CLOCKIO", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x4010000 seg.endEA = 0x4011000 idaapi.add_segm_ex(seg, "FLAGIO", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x5000000 seg.endEA = 0x5002000 idaapi.add_segm_ex(seg, "RDATA", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x5002000 seg.endEA = 0x5002003 idaapi.add_segm_ex(seg, "RDATASZ", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x5010000 seg.endEA = 0x5012000 idaapi.add_segm_ex(seg, "SDATA", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x5012000 seg.endEA = 0x5012003 idaapi.add_segm_ex(seg, "SDATASZ", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x6000000 seg.endEA = 0x6800000 idaapi.add_segm_ex(seg, "SHMEM", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x6800000 seg.endEA = 0x7000000 idaapi.add_segm_ex(seg, "NVRAM", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x7FFFF00 seg.endEA = 0x7FFFF1C idaapi.add_segm_ex(seg, "IVEC", "RAM", idaapi.ADDSEG_SPARSE) seg = idaapi.segment_t() seg.startEA = 0x7FFFF80 seg.endEA = 0x8000000 idaapi.add_segm_ex(seg, "PROCID", "RAM", idaapi.ADDSEG_SPARSE) idaapi.add_entry(0, 0, "_start", True) # idc.AutoMark( 0, AU_CODE ) idaapi.cvar.inf.tribyte_order = idaapi.tbo_213 return 1
def load_file(li, neflags, format): idaapi.set_processor_type('xap2csr', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) li.seek(0) lines = li.read(li.size()).split('\n') segs = {} for seg in ('code', 'data'): segs[seg] = {'chunks': [], 'syms': []} def handle_line(line): raise ValueError('got non-commented line before title: %r' % (line,)) for line in lines: #print repr(line) line = line.strip() if not line: continue if not line.startswith('// '): line = re.sub('\s*//.*', '', line) handle_line(line) continue m = re.match('^// Title +: "(Code|Constant|Symbol) Table"', line) if not m: continue kind = m.group(1) if kind in ('Code', 'Constant'): chunks = segs['code' if kind == 'Code' else 'data']['chunks'] if chunks != []: raise ValueError('more than one %s table in file' % (kind,)) cur_addr_box = [None] cur_chunk_box = [None] def handle_line(line): m = re.match('^@([0-9A-Fa-f]+)\s+([0-9A-Fa-f]{4})$', line) if not m: raise ValueError('unrecognized seg line: %r' % (line,)) addr, word = [int(x, 16) for x in m.groups()] cur_addr, cur_chunk = cur_addr_box[0], cur_chunk_box[0] if cur_addr is None or addr > cur_addr: cur_chunk = cur_chunk_box[0] = [] chunks.append((addr, cur_chunk)) elif addr < cur_addr: raise ValueError('going backwards with addresses (cur_addr=0x%x): %r' % (cur_addr, line,)) cur_chunk.append(word) cur_addr_box[0] = addr + 1 else: assert kind == 'Symbol' cur_syms_box = [None] def handle_line(line): if line in ('.CODE', '.DATA'): cur_syms_box[0] = segs[line[1:].lower()]['syms'] else: m = re.match('^([^,]+), ([0-9a-fA-F]+)*$', line) if not m: raise ValueError('unknown symbol line: %r' % (line,)) cur_syms = cur_syms_box[0] if cur_syms is None: raise ValueError('symbols without a segment: %r' % (line,)) cur_syms.append((int(m.group(2), 16), m.group(1))) # (addr, name) for (segname, info) in segs.iteritems(): kind = {'code': 0, 'data': 1}[segname] base_addr = (0, 0x1000000)[kind] if segname == 'code' and info['chunks'] == [] and info['syms'] == []: continue if not idaapi.set_selector(kind + 1, base_addr >> 4): raise Exception("couldn't set selector for segment %s" % (name,)) for addr, chunk in info['chunks']: seg = idaapi.segment_t() seg.startEA = base_addr + addr seg.endEA = base_addr + addr + len(chunk) seg.bitness = 1 # 32-bit (we can have more than 16 bits of code, so just use for both) seg.sel = kind + 1 name = '%s_%x' % (segname, addr) klass = segname.upper() #print '%s from %x to %x' % (name, seg.startEA, seg.endEA) if not idaapi.add_segm_ex(seg, name, klass, ADDSEG_NOSREG): raise Exception("couldn't add segment %s" % (name,)) ea = seg.startEA for word in chunk: idaapi.put_byte(ea, word) ea += 1 if segname == 'code': idaapi.autoMark(seg.startEA, AU_CODE) if segname == 'data': # fill in the remaining area with BSS spaces = zip([0] + [addr+len(chunk) for (addr, chunk) in info['chunks']], [addr for (addr, chunk) in info['chunks']] + [0x10000]) for start, end in spaces: if end - start < 0x10: continue assert end > start seg = idaapi.segment_t() seg.startEA = base_addr + start seg.endEA = base_addr + end seg.bitness = 1 seg.sel = kind + 1 name = 'bss_%x' % (start,) #print '%s from %x to %x' % (name, seg.startEA, seg.endEA) if not idaapi.add_segm_ex(seg, name, 'BSS', idaapi.ADDSEG_SPARSE | ADDSEG_NOSREG): raise Exception("couldn't add segment %s" % (name,)) return 1
def new(offset, size, name, **kwds): """Create a segment at `offset` with `size` and name it according to `name`. The keyword `bits` can be used to specify the bit size of the segment The keyword `comb` can be used to specify any flags (idaapi.sc*) The keyword `align` can be used to specify paragraph alignment (idaapi.sa*) The keyword `org` specifies the origin of the segment (must be paragraph aligned due to ida) """ res = utils.string.to(name) # find the segment according to the name specified by the user seg = idaapi.get_segm_by_name(res) if seg is not None: raise E.DuplicateItemError( u"{:s}.new({:#x}, {:+#x}, \"{:s}\"{:s}) : A segment with the specified name (\"{:s}\") already exists." .format( __name__, offset, size, utils.string.escape(name, '"'), u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', utils.string.escape(name, '"'))) # FIXME: use disassembler default bit length instead of 32 bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits()) ## create a selector with the requested origin if bits == 16: org = kwds.get('org', 0) if org & 0xf > 0: raise E.InvalidTypeOrValueError( u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : The specified origin ({:#x}) is not aligned to the size of a paragraph (0x10)." .format( __name__, offset, size, name, u", {:s}".format( utils.string.kwargs(kwds)) if kwds else '', org)) para = offset // 16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para - kwds.get('org', 0) // 16) & 0xffffffff) ## if the user specified a selector, then use it elif 'sel' in kwds or 'selector' in kwds: sel = kwds.get('sel', kwds.get('selector', idaapi.find_free_selector())) ## choose the paragraph size defined by the user elif 'para' in kwds or 'paragraphs' in kwds: para = kwds.get('paragraph', kwds.get('para', 1)) sel = idaapi.setup_selector(para) ## find a selector that is 1 paragraph size, elif idaapi.get_selector_qty(): sel = idaapi.find_selector(1) # otherwise find a free one and set it. else: sel = idaapi.find_free_selector() idaapi.set_selector(sel, 1) # populate the segment_t for versions of IDA prior to 7.0 if idaapi.__version__ < 7.0: seg = idaapi.segment_t() seg.startEA, seg.endEA = offset, offset + size # now for versions of IDA 7.0 and newer else: seg = idaapi.segment_t() seg.start_ea, seg.end_ea = offset, offset + size # assign the rest of the necessary attributes seg.sel = sel seg.bitness = {16: 0, 32: 1, 64: 2}[bits] seg.comb = kwds.get('comb', idaapi.scPub) # public seg.align = kwds.get('align', idaapi.saRelByte) # paragraphs # now we can add our segment_t to the database res = utils.string.to(name) ok = idaapi.add_segm_ex(seg, res, "", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_SPARSE) if not ok: ok = idaapi.del_selector(sel) if not ok: logging.warning( u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to delete the created selector ({:#x}) for the new segment." .format( __name__, offset, size, name, u", {:s}".format( utils.string.kwargs(kwds)) if kwds else '', sel)) raise E.DisassemblerError( u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to add a new segment." .format( __name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '')) return seg
def findAllKEXT(): """ findAllKEXT: Finds all KEXT contained in the kernelcache file. The mach-o headers will be converted into the appropiate structs, the new sections will be defined and the name and version number of the KEXT are extracted. In the end a window is shown that shows all contained KEXT. """ # Ask the user if he wants to add all the KEXT sections # to the IDA database. answer = idc.AskYN(0, """Do you want to add all the KEXT sections to the IDA database? If this was already done before or there was already code or data in the same place in the IDA database, IDA might react very slow, crash or just stop to work.""") # KEXT cache starts behind the __LINKEDIT segment # NOTE: IDA calls the segment __LINKEDIT_hidden linkedit = idaapi.get_segm_by_name("__LINKEDIT_hidden") if not linkedit: print "[-] cannot find KEXTCACHE: __LINKEDIT segment not found" return kextcache = idaapi.get_next_seg(linkedit.endEA) if not kextcache: print "[-] cannot find KEXTCACHE: __LINKEDIT not followed by any segment" return dummyName = idaapi.get_segm_name(kextcache) if dummyName != "__text": print "[-] cannot find KEXTCACHE: __LINKEDIT not followed by __text segment" return if answer == 1: # Destroy everything in the kextcache area idaapi.do_unknown_range(kextcache.startEA, kextcache.endEA-kextcache.startEA, DOUNK_DELNAMES) startEA = kextcache.startEA kextlist = [] while True: sig = idc.Dword(startEA) if sig != 0xfeedface: "[-] expected the next KEXT but did not find correct signature" break seg_lc = None sections = [] added = 0 next = forceStruct(startEA, "mach_header") ncmds = get_member_from_struct(startEA, "mach_header", "ncmds") for i in range(ncmds): lc_addr = next cmd = get_member_from_struct(next, "load_command", "cmd") if cmd == 1: seg_lc = next next = forceStruct(seg_lc, "segment_command") nsecs = get_member_from_struct(seg_lc, "segment_command", "nsects") for j in range(nsecs): section = next next = forceStruct(section, "section") # Get basic information about segment (needed for ALL the code below) secStart = get_member_from_struct(section, "section", "addr") secEnd = secStart + get_member_from_struct(section, "section", "size") secname = idc.GetString(section) # We should tell IDA about what this section is s = idaapi.segment_t() s.startEA = secStart s.endEA = secEnd s.sel = idaapi.setup_selector(0) if secname == "__text": s.bitness = 0 else: s.bitness = 1 s.align = get_member_from_struct(section, "section", "align") s.comb = 0 # ??? if secname == "__text" or secname == "stubs": sclass = "CODE" elif secname == "__bss": sclass = "BSS" else: sclass = "DATA" if len(sections) == 0: sec = {} sec["name"] = "MACH-O HEADER" sec["start"] = "%08X" % (startEA) sec["end"] = "%08X" % (secStart-1) sections.append(sec) sec = {} sec["name"] = secname sec["start"] = "%08X" % (secStart) sec["end"] = "%08X" % (secEnd-1) sections.append(sec) if answer == 1: # Destroy everything inside the segment idaapi.do_unknown_range(secStart, secEnd-secStart, DOUNK_DELNAMES) # Ensure that the whole section is undefined idaapi.add_segm_ex(s, secname, sclass, idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_QUIET) if secname == "__text": idc.SetRegEx(secStart, "T", 1, 0) # special handling of constructor and destructor if secname == "__constructor" or secname == "__destructor": for z in range(secStart, secEnd, 4): idc.OpOffEx(z, -1, REF_OFF32, 0xFFFFFFFF, 0, 0) # We have to check for __data section because we want # to find the kmod_info structure if secname != "__data": continue kextName = None for z in range(secStart, secEnd, 4): k = z # We assume that all KEXT name start with "com." kextNameSig = idc.Dword(k) if kextNameSig == 0x2e6d6f63: forceStruct(k-12, "kmod_info") kextName = idc.GetString(k) kextVersion = idc.GetString(k+64) #print "-> %s - version: %s" % (kextName, kextVersion) dic = {} dic["addr"] = "%08X" % (startEA) dic["name"] = kextName dic["version"] = kextVersion kextlist.append(dic) added = 1 break if kextName == None: print "ERROR COULD NOT FIND NAME" elif cmd == 0x1b: next = forceStruct(lc_addr, "uuid_command") elif cmd == 0x2: next = forceStruct(lc_addr, "symtab_command") #print "Found symbol table KEXT at %08x" % (startEA) else: print "Unknown load command %08x" % (cmd) if added: kextlist[len(kextlist)-1]["sections"] = sections next = lc_addr + get_member_from_struct(lc_addr, "load_command", "cmdsize") if seg_lc == None: startEA += 4 while idc.Dword(startEA) != 0xfeedface: startEA += 4 continue startEA = get_member_from_struct(seg_lc, "segment_command", "vmaddr") startEA += get_member_from_struct(seg_lc, "segment_command", "vmsize") c = MySelectionDialog("Retrieved KEXT", [ ["Address", 10], [ "Name", 65 ], ["Version", 65] ], formatKEXTresults(kextlist)) selected_row = c.Show(True) if selected_row >= 0: sel = kextlist[selected_row] c = MySelectionDialog("Sections inside " + sel["name"], [ ["Name", 16], [ "Start", 10 ], ["End", 10] ], formatSECTIONresults(sel["sections"])) selected_row = c.Show(True) if selected_row >= 0: sel = sel["sections"][selected_row] idc.Jump(int(sel["start"], 16))