def create_section(start_ea, end_ea, perm, name, all_thumb=True): """ Create section in IDA Pro :param start_ea: start address of secion :type start_ea: str :param end_ea: end address of secion :type end_ea: str :param perm: Permissions of section (1:ex, 2:read, 4:write) :type perm: int :param name: name of section :type name: str :return: success :rtype: bool """ try: start, end = parse_range(start_ea, end_ea) except ValueError: return False if idc.add_segm_ex(start, end, 0, 1, 1, 0, 0): idc.set_segm_name(start, name) idc.set_segm_attr(start, idc.SEGATTR_PERM, perm) if all_thumb: idc.split_sreg_range(start, "T", 1, idc.SR_autostart) return True return False
def append_segment(segment_name): """ Add a new segment to the IDB file and return its starting address. Information about function arguments will be stored here. Only works if the segment name is not used yet. This does not affect the original binary. Arguments: segment_name -- the name of the segment to be added """ for segment in idautils.Segments(): if idc.get_segm_name(segment) == segment_name: g_logger.warning('Segment ' + segment_name + ' already exists') return idc.get_segm_start(segment) new_segment_start = get_end_of_last_segment() g_logger.debug('Adding new segment at 0x%08x' % new_segment_start) if not idc.AddSeg(new_segment_start, (new_segment_start + NEW_SEGMENT_SIZE), 0, 1, 0, idaapi.scPub) == 1: raise FailedToAppendSegmentException('Could not add segment') # set new segment's attributes if not idc.set_segm_name(new_segment_start, segment_name): raise FailedToAppendSegmentException('Could not rename segment') if not idc.set_segm_class(new_segment_start, 'DATA'): raise FailedToAppendSegmentException('Could not set segment class') if not idc.set_segm_alignment(new_segment_start, idc.saRelPara): raise FailedToAppendSegmentException('Could not align segment') if not idc.set_segm_addressing(new_segment_start, 1): # 1 -- 32 bit raise FailedToAppendSegmentException( 'Could not set segment addressing') return new_segment_start
def main(argv=None): if argv is None: argv = sys.argv[:] try: seg = prompt_for_segment() except BadInputError: logger.error('bad input, exiting...') return -1 with open(seg.path, 'rb') as f: buf = f.read() seglen = len(buf) if seglen % 0x1000 != 0: seglen = seglen + (0x1000 - (seglen % 0x1000)) if not idc.AddSeg(seg.addr, seg.addr + seglen, 0, 1, 0, idaapi.scPub): logger.error('failed to add segment: 0x%x', seg.addr) return -1 if not idc.set_segm_name(seg.addr, seg.name): logger.warning('failed to rename segment: %s', seg.name) if not idc.set_segm_class(seg.addr, 'CODE'): logger.warning('failed to set segment class CODE: %s', seg.name) if not idc.set_segm_attr(seg.addr, SEGATTR_ALIGN, idc.saRelPara): logger.warning('failed to align segment: %s', seg.name) ida_bytes.patch_bytes(seg.addr, buf)
def __create_load_data_segment(data, seg_addr, seg_name): # This function creates a data segment located in a pre-specified address # and fills this new segment with data seglen = len(data) if seglen % 0x1000 != 0: seglen = seglen + (0x1000 - (seglen % 0x1000)) if not idc.AddSeg(seg_addr, seg_addr + seglen, 0, 1, 0, idaapi.scPub): logger.error('failed to add segment: 0x%x', seg_addr) return False if not idc.set_segm_name(seg_addr, seg_name): logger.warning('failed to rename segment: %s', seg_name) return False if not idc.set_segm_class(seg_addr, 'DATA'): logger.warning('failed to set segment class DATA: %s', seg_name) return False if not idc.set_segm_attr(seg_addr, idc.SEGATTR_ALIGN, idc.saRelPara): logger.warning('failed to align segment: %s', seg_name) return False if data: idaapi.patch_bytes(seg_addr, data) return True
def set_text_segment_rwe(): """ Update name, class, permissions of CODE segment to resolve elimination of "dead" code. Also set compiler to VC++. """ for seg in Segments(): if get_segm_name(seg) == ".text": set_segm_name(seg, ".code") set_segm_class(seg, "DATA") set_segm_attr(seg, SEGATTR_PERM, 0b111) # RWE print("Updating segment at " + hex(seg) + ":\nsegment name .text -> .code" + "\nsegment class = DATA" + "\nsegment permissions = RWE") break set_compiler_id(1) # Visual C++
def process_region(segname, name, start, end): assert end >= start if segname in skip: _log(2, 'Skipping segment {}', segname) return newname = '{}.{}'.format(segname, name) if kext: newname = '{}:{}'.format(kext, newname) if start == end: _log(2, 'Skipping empty region {} at {:x}', newname, start) return ida_segstart = idc.get_segm_start(start) if ida_segstart == idc.BADADDR: _log(0, "IDA doesn't think this is a real segment: {:x} - {:x}", start, end) return ida_segend = idc.get_segm_end(ida_segstart) if start != ida_segstart or end != ida_segend: _log(0, 'IDA thinks segment {} {:x} - {:x} should be {:x} - {:x}', newname, start, end, ida_segstart, ida_segend) return _log(2, 'Rename {:x} - {:x}: {} -> {}', start, end, idc.get_segm_name(start), newname) idc.set_segm_name(start, newname)
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 """ if format == AtariSTTOSImageName: idaapi.set_processor_type('68K', ida_idp.SETPROC_LOADER) li.seek(0) header = read_struct(li, tos_image_header) li.seek(0, idaapi.SEEK_END) filesize = li.tell() idc.add_segm_ex(header.os_beg, header.os_beg + filesize, 0, 1, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_NOSREG) idc.set_segm_name(header.os_beg, 'TOS') li.seek(0) li.file2base(0, header.os_beg, header.os_beg + filesize, 0) idaapi.add_entry(header.os_beg, header.os_beg, "ostext", 1) idc.set_cmt(header.os_beg, 'branch to reset handler', 0) idc.set_name(header.os_beg + 2, 'os_version') idc.create_word(header.os_beg + 2) idc.set_cmt(header.os_beg + 2, 'OS version number', 0) idc.set_cmt(header.os_beg + 4, '-> system reset handler', 0) reseth = ida_bytes.get_dword(header.os_beg + 4) idc.set_name(reseth, 'reseth') idc.set_name(header.os_beg + 8, 'os_beg') idc.set_cmt(header.os_beg + 8, '-> base of OS', 0) idc.set_name(header.os_beg + 12, 'os_end') idc.set_cmt(header.os_beg + 12, '-> end of OS memory usage', 0) os_end = ida_bytes.get_dword(header.os_beg + 12) idc.add_segm_ex(0x0, os_end, 0, 1, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_NOSREG) idc.set_segm_name(0x0, 'DOSRAM') idc.set_name(os_end, 'endos') idc.set_name(header.os_beg + 16, 'os_exec') idc.set_cmt(header.os_beg + 16, '-> default shell', 0) idc.set_name(header.os_beg + 20, 'os_magic') idc.set_cmt(header.os_beg + 20, '-> GEM magic (or NULL)', 0) idc.set_name(header.os_beg + 24, 'os_date') idc.create_dword(header.os_beg + 24) idc.set_cmt(header.os_beg + 24, 'date the system was built', 0) idc.set_name(header.os_beg + 28, 'os_conf') idc.create_word(header.os_beg + 28) idc.set_cmt(header.os_beg + 28, 'configuration bits', 0) idc.set_name(header.os_beg + 30, 'os_dosdate') idc.create_word(header.os_beg + 30) idc.set_cmt(header.os_beg + 30, 'DOS-format date the system was built', 0) addr = header.os_beg + 32 while addr < reseth: if addr == header.os_beg + 0x20: idc.set_cmt(addr, 'base of GEMDOS pool', 0) idc.set_name(ida_bytes.get_dword(addr), '_root') elif addr == header.os_beg + 0x24: idc.set_cmt(addr, '-> keyboard shift-state byte', 0) idc.set_name(ida_bytes.get_dword(addr), 'kbshift') elif addr == header.os_beg + 0x28: idc.set_cmt(addr, '-> current process', 0) idc.set_name(ida_bytes.get_dword(addr), '_run') elif addr == header.os_beg + 0x2c: idc.set_cmt(addr, 'reserved for future use', 0) idc.create_dword(addr) addr += 4 the_magic = ida_bytes.get_dword(header.os_beg + 20) gem_end = ida_bytes.get_dword(the_magic + 4) aes_init = ida_bytes.get_dword(the_magic + 8) idc.add_segm_ex(os_end, gem_end + 1, 0, 1, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_NOSREG) idc.set_segm_name(os_end, 'GEMRAM') idc.set_name(the_magic, 'the_magic') idc.create_dword(the_magic) idc.set_cmt(the_magic, '$87654321 if GEM present', 0) idc.create_dword(the_magic + 4) idc.set_cmt(the_magic + 4, 'End address of OS RAM usage', 0) idc.create_dword(the_magic + 8) idc.set_cmt(the_magic + 8, 'Execution address of GEM', 0) idaapi.add_entry(aes_init, aes_init, "gem_entry", 1) idc.set_name(gem_end, 'gem_end') idaapi.auto_wait() return 1 elif format == AtariSTProgramName: idaapi.set_processor_type('68K', ida_idp.SETPROC_LOADER) li.seek(0) header = read_struct(li, gemdos_executable_header) base_addr = AtariSTBaseAddress text_addr = base_addr data_addr = text_addr + header.PRG_tsize bss_addr = data_addr + header.PRG_dsize idc.add_segm_ex(text_addr, text_addr + header.PRG_tsize, 0, 1, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_NOSREG) idc.set_segm_name(text_addr, 'tseg') idc.add_segm_ex(data_addr, data_addr + header.PRG_dsize, 0, 1, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_NOSREG) idc.set_segm_name(data_addr, 'dseg') idc.add_segm_ex(bss_addr, bss_addr + header.PRG_bsize, 0, 1, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_SPARSE) idc.set_segm_name(bss_addr, 'bseg') li.file2base(ctypes.sizeof(gemdos_executable_header), text_addr, text_addr + header.PRG_tsize + header.PRG_dsize, 0) # relocate the application li.seek(0, idaapi.SEEK_END) filesize = li.tell() li.seek(0, idaapi.SEEK_SET) relocDataOffset = ctypes.sizeof( gemdos_executable_header ) + header.PRG_tsize + header.PRG_dsize + header.PRG_ssize li.seek(relocDataOffset) relocData = li.read(filesize - relocDataOffset) roffset = 4 rea = struct.unpack('>I', relocData[:roffset])[0] if rea != 0: rea = rea + base_addr idc.patch_dword(rea, ida_bytes.get_dword(rea) + base_addr) if rea >= data_addr: # in the DATA segment, make sure it is an actual pointer idc.create_dword(rea) while True: offset = ord(relocData[roffset]) roffset += 1 if offset == 0: # end of the relocation table break if offset == 1: # odd numbers are not valid, 1 is a special case to skip 254 bytes without relocating rea += 254 continue rea += offset idc.patch_dword(rea, ida_bytes.get_dword(rea) + base_addr) if rea >= data_addr: # in the DATA segment, make sure it is an actual pointer idc.create_dword(rea) # apply a symbol table, if part of the file if header.PRG_ssize: symboltableDataOffset = ctypes.sizeof( gemdos_executable_header) + header.PRG_tsize + header.PRG_dsize li.seek(symboltableDataOffset) symboltableData = li.read(header.PRG_ssize) soffset = 0 while soffset < header.PRG_ssize: entry = symboltableData[soffset:soffset + 14] soffset += 14 name = entry[:8] flags, value = struct.unpack('>HL', entry[8:]) if ( flags & 0x0048 ) and soffset + 14 < header.PRG_ssize: # GST extended DRI symbol format? entry = symboltableData[soffset:soffset + 14] soffset += 14 name += entry[:8] if ( flags & 0xf000 ) == 0xa000: # global defined symbol? (registers, etc are not supported) value += text_addr # relocate the value if (flags & 0xf00) == 0x0100: # BSS idc.set_name(value, name) elif (flags & 0xf00) == 0x0200: # TEXT idaapi.add_entry(value, value, name, 1) elif (flags & 0xf00) == 0x0400: # DATA idc.set_name(value, name) idaapi.add_entry(text_addr, text_addr, "start", 1) idaapi.plan_and_wait(text_addr, text_addr + header.PRG_tsize) idaapi.auto_wait() return 1 return 0
def load_file(li, neflags, format): if format != ROM_FORMAT_NAME: Warning("Unknown format name: '%s'" % format) return 0 jump = dwordAt(li, 0) # Test ARM branch if jump & 0xFF000000 != 0xEA000000: Warning("Unknown format name: '%s'" % format) return 0 idaapi.set_processor_type("arm", idc.SETPROC_LOADER_NON_FATAL|idc.SETPROC_LOADER) li.seek(0, idaapi.SEEK_END) size = li.tell() # Adding Header Section idc.AddSeg(ROM_START, ROM_START + SIZE_HEADER, 0, 1, idaapi.saRelPara, idaapi.scPub) idc.set_segm_name(ROM_START, "HEADER") idc.set_segm_type(ROM_START, idc.SEG_CODE) li.seek(0) li.file2base(0, ROM_START, ROM_START + SIZE_HEADER, 0) # Adding OEP idaapi.add_entry(ROM_START, ROM_START, "start", 1) idaapi.cvar.inf.startIP = ROM_START idaapi.cvar.inf.beginEA = ROM_START # Adding ROM Section idc.AddSeg(ROM_START + SIZE_HEADER, ROM_START + (ROM_SIZE - SIZE_HEADER), 0, 1, idaapi.saRelPara, idaapi.scPub) idc.set_segm_name(ROM_START + SIZE_HEADER, "ROM") idc.set_segm_type(ROM_START + SIZE_HEADER, idc.SEG_CODE) li.seek(SIZE_HEADER) li.file2base(0, ROM_START + SIZE_HEADER, ROM_START + size, 0) # Adding EWRAM idc.AddSeg(0x02000000, 0x02040000, 0, 1, idaapi.saRelPara, idaapi.scPub) idc.set_segm_name(0x02000000, "EWRAM") memset_seg(0x02000000, 0x40000) # Adding IWRAM idc.AddSeg(0x03000000, 0x03008000, 0, 1, idaapi.saRelPara, idaapi.scPub) idc.set_segm_name(0x03000000, "IWRAM") memset_seg(0x03000000, 0x8000) # Adding IO / Registers idc.AddSeg(0x04000000, 0x04000400, 0, 1, idaapi.saRelPara, idaapi.scPub) idc.set_segm_name(0x04000000, "IOregisters") memset_seg(0x04000000, 0x400) # Adding BIOS System ROM idc.AddSeg(0x00000000, 0x00004000, 0, 1, idaapi.saRelPara, idaapi.scPub) idc.set_segm_name(0x00000000, "BIOS") memset_seg(0x00000000, 0x4000) idc.set_segm_type(0x0000000, idc.SEG_CODE) idaapi.add_extra_cmt(ROM_START, True, "ROM HEADER") li.seek(0xA0) idc.update_extra_cmt(ROM_START, 1, "; Game Title : %s" % li.read(12)) idc.update_extra_cmt(ROM_START, 2, "; Game Code : %s" % li.read(4)) idc.update_extra_cmt(ROM_START, 3, "; Marker Code : %s" % li.read(2)) idc.update_extra_cmt(ROM_START, 4, "; Fixed value : %02X" % struct.unpack("<B", li.read(1))[0]) idc.update_extra_cmt(ROM_START, 5, "; Main unit code : %02X" % struct.unpack("<B", li.read(1))[0]) idc.update_extra_cmt(ROM_START, 6, "; Device type : %02X" % struct.unpack("<B", li.read(1))[0]) idc.update_extra_cmt(ROM_START, 7, "; Reserved Area : db 7 dup(0)") li.read(7) idc.update_extra_cmt(ROM_START, 8, "; Software version %02X" % struct.unpack("<B", li.read(1))[0]) idc.update_extra_cmt(ROM_START, 9, "; Complement Check %02X" % struct.unpack("<B", li.read(1))[0]) idc.update_extra_cmt(ROM_START, 10, "; Reserved Area : db 2 dup(0)") io_naming() print("[+] Load OK") return 1