def process_strings(segm): # If you jump to the bottom of the file and search upwards for this hex, you'll get the string section start string_addr = find_probable_string_start(segm) if string_addr == BADADDR: print( "[-] Failed to find string information. Not much info can be pulled." ) return BADADDR, ida_search.find_binary(0x0, segm.end_ea, "41 70 70 6C 65 20 49", 16, ida_search.SEARCH_DOWN) strend = ida_search.find_binary(string_addr, segm.end_ea, "41 70 70 6C 65 20 49", 16, ida_search.SEARCH_DOWN) # 'Apple, I' ea = string_addr if strend == BADADDR: strend = string_addr + 0xFF # Best we can do here is just tell ida to make every single byte, individually, a string; it figures it out. for i in range(ea, strend): idc.create_strlit(i, BADADDR) idc.create_strlit(strend, BADADDR) # Create the "Apple, Inc." String return string_addr, strend
def fix_ascii(self, address): string_table_start_address = self.get_string_table_start_address(address) string_address = string_table_start_address while True: if string_address: print("Start Make string at address: %s" % hex(string_address)) if idaapi.IDA_SDK_VERSION >= 700: idc.create_strlit(string_address, idc.BADADDR) else: idc.MakeStr(string_address, idc.BADADDR) string_address = self.get_next_ascii_string_address(string_address) else: break
def defineAsciiString(self, ea): r"""Define an ascii string at the given address. Args: ea (int): effective start address of the wanted ascii string Return Value: The length of the defined string + 1 for the '\0' terminator """ content = idc.get_strlit_contents(ea, -1, -1) if not sark.Line(ea).is_string: self._analyzer.logger.debug( "Defined a unique ascii string at: 0x%x (Length of %d)", ea, len(content) + 1) ida_bytes.del_items(ea, 0, len(content) + 1) idc.create_strlit(ea, ea + len(content) + 1) return len(content) + 1
def fix_vxworks_idb(load_address, vx_version, symbol_table_start, symbol_table_end): current_image_base = idaapi.get_imagebase() symbol_interval = 16 if vx_version == 6: symbol_interval = 20 symbol_table_start += load_address symbol_table_end += load_address ea = symbol_table_start shift_address = load_address - current_image_base while shift_address >= 0x70000000: idaapi.rebase_program(0x70000000, 0x0008) shift_address -= 0x70000000 idaapi.rebase_program(shift_address, 0x0008) while ea < symbol_table_end: # for VxWorks 6 unknown symbol format if idc.Byte(ea + symbol_table_end - 2) == 3: ea += symbol_interval continue offset = 4 if idaapi.IDA_SDK_VERSION >= 700: idc.create_strlit(idc.Dword(ea + offset), idc.BADADDR) else: idc.MakeStr(idc.Dword(ea + offset), idc.BADADDR) sName = idc.GetString(idc.Dword(ea + offset), -1, idc.ASCSTR_C) print("Found %s in symbol table" % sName) if sName: sName_dst = idc.Dword(ea + offset + 4) if vx_version == 6: sName_type = idc.Dword(ea + offset + 12) else: sName_type = idc.Dword(ea + offset + 8) idc.MakeName(sName_dst, sName) if sName_type in need_create_function: # flags = idc.GetFlags(ea) print("Start fix Function %s at %s" % (sName, hex(sName_dst))) idc.MakeCode(sName_dst) # might not need idc.MakeFunction(sName_dst, idc.BADADDR) ea += symbol_interval print("Fix function by symbol table finish.") print( "Start IDA auto analysis, depending on the size of the firmware this might take a few minutes." ) idaapi.autoWait()
def visit_expr(self, e): if e.op == idaapi.cot_call and \ e.x.op == idaapi.cot_obj and \ e.x.obj_ea == self.ea: arg = e.a[0] # print(f"arg={arg}, arg.op={arg.op}") t = idaapi.tinfo_t.get_stock(idaapi.STI_PCHAR) if arg.op == idaapi.cot_obj: prefix = idaapi.get_bytes(arg.obj_ea, 2) # print(prefix) if prefix[0] == 1: log_level = chr(prefix[1]) idaapi.del_items(arg.obj_ea) arg.obj_ea += 2 idc.create_strlit(arg.obj_ea, idaapi.BADADDR) arg.type = t arg.exflags = idaapi.EXFL_CSTR return 0
def load_file(f, neflags, format): print('# PS4 Module Loader') ps = Binary(f) # PS4 Processor, Compiler, Library bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL, 'gnulnx_x64') # Load Aerolib... nids = load_nids(idc.idadir() + '/loaders/aerolib.csv') # Segment Loading... for segm in ps.E_SEGMENTS: # Process Loadable Segments... if segm.name() in [ 'CODE', 'DATA', 'SCE_RELRO', 'DYNAMIC', 'GNU_EH_FRAME', 'SCE_DYNLIBDATA' ]: address = segm.MEM_ADDR if segm.name() not in [ 'DYNAMIC', 'SCE_DYNLIBDATA' ] else segm.OFFSET + 0x1000000 size = segm.MEM_SIZE if segm.name() not in [ 'DYNAMIC', 'SCE_DYNLIBDATA' ] else segm.FILE_SIZE print('# Processing %s Segment...' % segm.name()) f.file2base(segm.OFFSET, address, address + segm.FILE_SIZE, FILEREG_PATCHABLE) if segm.name() not in ['DYNAMIC', 'GNU_EH_FRAME']: idaapi.add_segm(0, address, address + size, segm.name(), segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP) # Processor Specific Segment Details idc.set_segm_addressing(address, bitness) idc.set_segm_alignment(address, segm.alignment()) idc.set_segm_attr(address, SEGATTR_PERM, segm.flags()) # Process Dynamic Segment.... elif segm.name() == 'DYNAMIC': stubs = {} modules = {} libraries = {} f.seek(segm.OFFSET) offset = segm.OFFSET dynamic = address dynamicsize = size for entry in xrange(size / 0x10): idc.set_cmt(address + (entry * 0x10), Dynamic(f).process(stubs, modules, libraries), False) ''' # Process Exception Handling Segment... elif segm.name() == 'GNU_EH_FRAME': # Exception Handling Frame Header Structure members = [('version', 'Version', 0x1), ('eh_frame_ptr_enc', 'Encoding of Exception Handling Frame Pointer', 0x1), ('fde_count_enc', 'Encoding of Frame Description Entry Count', 0x1), ('table_enc', 'Encoding of Table Entries', 0x1)] struct = segm.struct('EHFrame', members) idaapi.create_struct(address, 0x4, struct) # Exception Handling Structure members = [('exception', 'value', 0x8)] struct = segm.struct('Exception', members) for entry in xrange(size / 0x8): idaapi.create_struct(address + (entry * 0x8), 0x8, struct) ''' # Process SCE 'Special' Shared Object Segment... if segm.name() == 'SCE_DYNLIBDATA': # SCE Fingerprint idc.make_array(address, 0x14) idc.set_name(address, 'SCE_FINGERPRINT', SN_NOCHECK | SN_NOWARN | SN_FORCE) idc.set_cmt( address, ' '.join( x.encode('hex') for x in idc.get_bytes(address, 0x14)).upper(), False) # Dynamic Symbol Table try: # -------------------------------------------------------------------------------------------------------- # Dynamic Symbol Entry Structure members = [('name', 'Name (String Index)', 0x4), ('info', 'Info (Binding : Type)', 0x1), ('other', 'Other', 0x1), ('shtndx', 'Section Index', 0x2), ('value', 'Value', 0x8), ('size', 'Size', 0x8)] struct = segm.struct('Symbol', members) # Dynamic Symbol Table location = address + Dynamic.SYMTAB f.seek(segm.OFFSET + Dynamic.SYMTAB) symbols = {} for entry in xrange(Dynamic.SYMTABSZ / 0x18): idaapi.create_struct(location + (entry * 0x18), 0x18, struct) idc.set_cmt(location + (entry * 0x18), Symbol(f).process(symbols), False) except: pass # Dynamic String Table try: # -------------------------------------------------------------------------------------------------------- # Dynamic String Table location = address + Dynamic.STRTAB f.seek(segm.OFFSET + Dynamic.STRTAB) # Stubs for key in stubs: idc.create_strlit(location + key, BADADDR) stubs[key] = idc.get_strlit_contents( location + key, BADADDR) idc.set_cmt(location + key, 'Stub', False) #print('Stubs: %s' % stubs) # Modules for key in modules: idc.create_strlit(location + key, BADADDR) modules[key] = idc.get_strlit_contents( location + key, BADADDR) idc.set_cmt(location + key, 'Module', False) #print('Modules: %s' % modules) # Libraries and LIDs lids = {} for key, value in libraries.iteritems(): idc.create_strlit(location + key, BADADDR) lids[value] = idc.get_strlit_contents( location + key, BADADDR) libraries[key] = idc.get_strlit_contents( location + key, BADADDR) idc.set_cmt(location + key, 'Library', False) #print('LIDs: %s' % lids) # Symbols for key in symbols: idc.create_strlit(location + key, BADADDR) symbols[key] = idc.get_strlit_contents( location + key, BADADDR) idc.set_cmt(location + key, 'Symbol', False) #print('Symbols: %s' % symbols) except: pass # Resolve Export Symbols try: symbols = sorted(symbols.iteritems()) location = address + Dynamic.SYMTAB + 0x30 f.seek(segm.OFFSET + Dynamic.SYMTAB + 0x30) for entry in xrange((Dynamic.SYMTABSZ - 0x30) / 0x18): Symbol(f).resolve(location + (entry * 0x18), nids, symbols[entry][1]) except: pass # Jump Table try: # -------------------------------------------------------------------------------------------------------- # Jump Entry Structure members = [('offset', 'Offset (String Index)', 0x8), ('info', 'Info (Symbol Index : Relocation Code)', 0x8), ('addend', 'AddEnd', 0x8)] struct = segm.struct('Jump', members) # PS4 Base64 Alphabet base64 = list( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-' ) alphabet = { character: index for index, character in enumerate(base64) } #print('Base64 Table: %s' % alphabet) # Jump Table location = address + Dynamic.JMPTAB f.seek(segm.OFFSET + Dynamic.JMPTAB) for entry in xrange(Dynamic.JMPTABSZ / 0x18): idaapi.create_struct(location + (entry * 0x18), 0x18, struct) idc.set_cmt( location + (entry * 0x18), Relocation(f).resolve(alphabet, nids, symbols, lids), False) except: pass # Relocation Table try: # -------------------------------------------------------------------------------------------------------- # Relocation Entry Structure (with specific addends) members = [('offset', 'Offset (String Index)', 0x8), ('info', 'Info (Symbol Index : Relocation Code)', 0x8), ('addend', 'AddEnd', 0x8)] struct = segm.struct('Relocation', members) # Relocation Table (with specific addends) location = address + Dynamic.RELATAB f.seek(segm.OFFSET + Dynamic.RELATAB) for entry in xrange(Dynamic.RELATABSZ / 0x18): idaapi.create_struct(location + (entry * 0x18), 0x18, struct) idc.set_cmt(location + (entry * 0x18), Relocation(f).process(nids, symbols), False) except: pass # Hash Table try: # -------------------------------------------------------------------------------------------------------- # Hash Entry Structure members = [('bucket', 'Bucket', 0x2), ('chain', 'Chain', 0x2), ('buckets', 'Buckets', 0x2), ('chains', 'Chains', 0x2)] struct = segm.struct('Hash', members) # Hash Table location = address + Dynamic.HASHTAB f.seek(segm.OFFSET + Dynamic.HASHTAB) for entry in xrange(Dynamic.HASHTABSZ / 0x8): idaapi.create_struct(location + (entry * 0x8), 0x8, struct) except: pass # Dynamic Tag Table try: # -------------------------------------------------------------------------------------------------------- # Dynamic Tag Entry Structure members = [('tag', 'Tag', 0x8), ('value', 'Value', 0x8)] struct = segm.struct('Tag', members) f.seek(offset) for entry in xrange(dynamicsize / 0x10): idaapi.create_struct(dynamic + (entry * 0x10), 0x10, struct) idc.set_cmt( dynamic + (entry * 0x10), Dynamic(f).comment(address, stubs, modules, libraries), False) except: pass # Start Function idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True) print('# Waiting for the AutoAnalyzer to Complete...') idaapi.auto_wait() # Set No Return for __stack_chk_fail... try: function = idc.get_name_ea_simple('__stack_chk_fail') function = idaapi.get_func(function) function.flags |= FUNC_NORET idaapi.update_func(function) except: pass # Missed Function Creation... try: code = idaapi.get_segm_by_name('CODE') address = code.start_ea end = code.end_ea # Final Pass print('# Performing Final Pass...') while address < end: address = idaapi.find_not_func(address, SEARCH_DOWN) if idaapi.is_unknown(idaapi.get_flags(address)): idaapi.create_insn(address) else: idc.add_func(address) address += 4 except: pass print('# Done!') return 1
def make_string(self, offset, size): """Convert range to byte string in IDB""" self.ret = idc.create_strlit(offset, offset + size) return self.ret
def create_string(ea, length=idc.BADADDR): s = get_string(ea, length) if s: idc.create_strlit(ea, ea + len(s)) return s
def load_file(f, neflags, format): print('# PS4 Kernel Loader') ps = Binary(f) # PS4 Processor, Compiler, Library bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL, 'gnulnx_x64') # Segment Loading... for segm in ps.E_SEGMENTS: if segm.name() == 'PHDR': kASLR = False if segm.FILE_SIZE == 0x118 else True # Process Loadable Segments... if segm.name() in ['CODE', 'DATA', 'SCE_RELRO']: address = segm.MEM_ADDR size = segm.MEM_SIZE # Dumped Kernel Fix-ups if segm.name() in ['DATA', 'SCE_RELRO'] and (idaapi.get_segm_by_name('CODE').start_ea != 0xFFFFFFFF82200000 or not kASLR): offset = address - idaapi.get_segm_by_name('CODE').start_ea dumped = segm.MEM_SIZE else: offset = segm.OFFSET dumped = segm.FILE_SIZE print('# Creating %s Segment...' % segm.name()) f.file2base(offset, address, address + dumped, FILEREG_PATCHABLE) idaapi.add_segm(0, address, address + size, segm.name(), segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP) # Processor Specific Segment Details idc.set_segm_addressing(address, bitness) idc.set_segm_alignment(address, segm.alignment()) idc.set_segm_attr(address, SEGATTR_PERM, segm.flags()) # Process Dynamic Segment... elif segm.name() == 'DYNAMIC': code = idaapi.get_segm_by_name('CODE') data = idaapi.get_segm_by_name('DATA') relro = idaapi.get_segm_by_name('SCE_RELRO') # ------------------------------------------------------------------------------------------------------------ # Dynamic Tag Entry Structure members = [('tag', 'Tag', 0x8), ('value', 'Value', 0x8)] struct = segm.struct('Tag', members) # Dynamic Tag Table stubs = {} modules = {} location = segm.MEM_ADDR # Dumps are offset by a small amount if code.start_ea != 0xFFFFFFFF82200000: dumped = code.start_ea - 0xFFFFFFFF82200000 else: dumped = 0 f.seek(location - code.start_ea) for entry in xrange(segm.MEM_SIZE / 0x10): idaapi.create_struct(location + (entry * 0x10), 0x10, struct) idc.set_cmt(location + (entry * 0x10), Dynamic(f).process(dumped, stubs, modules), False) # ------------------------------------------------------------------------------------------------------------ # Hash Entry Structure members = [('bucket', 'Bucket', 0x2), ('chain', 'Chain', 0x2), ('buckets', 'Buckets', 0x2), ('chains', 'Chains', 0x2)] struct = segm.struct('Hash', members) # Hash Table try: location = Dynamic.HASHTAB size = Dynamic.HASHTABSZ except: location = Dynamic.HASH size = Dynamic.SYMTAB - location f.seek(location - code.start_ea) for entry in xrange(size / 0x8): idaapi.create_struct(location + (entry * 0x8), 0x8, struct) if kASLR: # -------------------------------------------------------------------------------------------------------- # Relocation Entry Structure (with specific addends) members = [('offset', 'Offset (String Index)', 0x8), ('info', 'Info (Symbol Index : Relocation Code)', 0x8), ('addend', 'AddEnd', 0x8)] struct = segm.struct('Relocation', members) # Relocation Table (with specific addends) location = Dynamic.RELATAB f.seek(location - code.start_ea) for entry in xrange(Dynamic.RELATABSZ / 0x18): idaapi.create_struct(location + (entry * 0x18), 0x18, struct) idc.set_cmt(location + (entry * 0x18), Relocation(f).process(dumped, code.end_ea), False) # Initialization Function idc.add_entry(Dynamic.INIT, Dynamic.INIT, '.init', True) else: # -------------------------------------------------------------------------------------------------------- # Symbol Entry Structure members = [('name', 'Name (String Index)', 0x4), ('info', 'Info (Binding : Type)', 0x1), ('other', 'Other', 0x1), ('shtndx', 'Section Index', 0x2), ('offset', 'Value', 0x8), ('size', 'Size', 0x8)] struct = segm.struct('Symbol', members) # Symbol Table location = Dynamic.SYMTAB f.seek(location - code.start_ea) functions = {} # .symtab idc.add_entry(location, location, '.symtab', False) for entry in xrange((Dynamic.STRTAB - location) / 0x18): idaapi.create_struct(location + (entry * 0x18), 0x18, struct) idc.set_cmt(location + (entry * 0x18), Symbol(f).process(functions), False) # -------------------------------------------------------------------------------------------------------- # Dynamic String Table location = Dynamic.STRTAB # .strtab idc.add_entry(location, location, '.strtab', False) # Functions for key in functions: idc.create_strlit(location + key, BADADDR) functions[key] = idc.get_strlit_contents(location + key, BADADDR) idc.set_cmt(location + key, 'Function', False) functions = sorted(functions.iteritems(), key = operator.itemgetter(0)) #print('Functions: %s' % functions) # Resolve Functions location = Dynamic.SYMTAB f.seek(location - code.start_ea + 0x18) for entry in xrange((Dynamic.STRTAB - location - 0x18) / 0x18): Symbol(f).resolve(functions[entry][1]) # Fix-up if kASLR: address = relro.start_ea del_items(address, DELIT_SIMPLE, relro.end_ea - address) while address < relro.end_ea: create_data(address, FF_QWORD, 0x8, BADNODE) address += 0x8 address = code.start_ea # ELF Header Structure members = [('File format', 0x4), ('File class', 0x1), ('Data encoding', 0x1), ('File version', 0x1), ('OS/ABI', 0x1), ('ABI version', 0x1), ('Padding', 0x7), ('File type', 0x2), ('Machine', 0x2), ('File version', 0x4), ('Entry point', 0x8), ('PHT file offset', 0x8), ('SHT file offset', 0x8), ('Processor-specific flags', 0x4), ('ELF header size', 0x2), ('PHT entry size', 0x2), ('Number of entries in PHT', 0x2), ('SHT entry size', 0x2), ('Number of entries in SHT', 0x2), ('SHT entry index for string table\n', 0x2)] for (comment, size) in members: flags = idaapi.get_flags_by_size(size) idc.create_data(address, flags if flags != 0 else FF_STRLIT, size, BADNODE) idc.set_cmt(address, comment, False) address += size for index, entry in enumerate(ps.E_SEGMENTS): # ELF Program Header Structure members = [('Type: %s' % entry.name(), 0x4), ('Flags', 0x4), ('File offset', 0x8), ('Virtual address', 0x8), ('Physical address', 0x8), ('Size in file image', 0x8), ('Size in memory image', 0x8), ('Alignment\n', 0x8)] for (comment, size) in members: flags = idaapi.get_flags_by_size(size) idc.create_data(address, flags if flags != 0 else FF_STRLIT, size, BADNODE) idc.set_cmt(address, comment, False) address += size # Wait for the AutoAnalyzer to Complete... print('# Waiting for the AutoAnalyzer to Complete...') idaapi.auto_wait() if kASLR: # Start Function idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True) # Xfast_syscall address = idaapi.find_binary(code.start_ea, code.end_ea, '0F 01 F8 65 48 89 24 25 A8 02 00 00 65 48 8B 24', 0x10, SEARCH_DOWN) idaapi.do_unknown(address, 0) idaapi.create_insn(address) idaapi.add_func(address, BADADDR) idaapi.set_name(address, 'Xfast_syscall', SN_NOCHECK | SN_NOWARN) # -------------------------------------------------------------------------------------------------------- # Znullptr's syscalls print('# Processing Znullptr\'s Syscalls...') # Syscall Entry Structure members = [('narg', 'Number of Arguments', 0x4), ('_pad', 'Padding', 0x4), ('function', 'Function', 0x8), ('auevent', 'Augmented Event?', 0x2), ('_pad1', 'Padding', 0x2), ('_pad2', 'Padding', 0x4), ('trace_args_func', 'Trace Arguments Function', 0x8), ('entry', 'Entry', 0x4), ('return', 'Return', 0x4), ('flags', 'Flags', 0x4), ('thrcnt', 'Thread Count?', 0x4)] struct = segm.struct('Syscall', members) znullptr(code.start_ea, code.end_ea, '4F 52 42 49 53 20 6B 65 72 6E 65 6C 20 53 45 4C 46', struct) # -------------------------------------------------------------------------------------------------------- # Chendo's cdevsw con-struct-or print('# Processing Chendo\'s cdevsw structs...') # cdevsw Entry Structure members = [('d_version', 'Version', 0x4), ('d_flags', 'Flags', 0x4), ('d_name', 'Name', 0x8), ('d_open', 'Open', 0x8), ('d_fdopen', 'File Descriptor Open', 0x8), ('d_close', 'Close', 0x8), ('d_read', 'Read', 0x8), ('d_write', 'Write', 0x8), ('d_ioctl', 'Input/Ouput Control', 0x8), ('d_poll', 'Poll', 0x8), ('d_mmap', 'Memory Mapping', 0x8), ('d_strategy', 'Strategy', 0x8), ('d_dump', 'Dump', 0x8), ('d_kqfilter', 'KQFilter', 0x8), ('d_purge', 'Purge', 0x8), ('d_mmap_single', 'Single Memory Mapping', 0x8), ('d_spare0', 'Spare0', 0x8), ('d_spare1', 'Spare1', 0x8), ('d_spare2', 'Spare2', 0x8), ('d_spare3', 'Spare3', 0x8), ('d_spare4', 'Spare4', 0x8), ('d_spare5', 'Spare5', 0x8), ('d_spare6', 'Spare6', 0x4), ('d_spare7', 'Spare7', 0x4)] struct = segm.struct('cdevsw', members) chendo(data.start_ea, data.end_ea, '09 20 12 17', struct) # -------------------------------------------------------------------------------------------------------- # Pablo's IDC try: print('# Processing Pablo\'s Push IDC...') # Script 1) Push it real good... pablo(code.start_ea, code.end_ea, 'C5 FA 5A C0 C5 F2 5A C9 C5 EA 5A D2 C5 FB 59 C1') pablo(code.start_ea, code.end_ea, 'C5 F9 7E C0 31 C9') pablo(code.start_ea, code.end_ea, '48 89 E0 55 53') pablo(code.start_ea, code.end_ea, 'B8 2D 00 00 00 C3') pablo(code.start_ea, code.end_ea, '31 C0 C3') pablo(code.start_ea, code.end_ea, '55 48 89') pablo(code.start_ea, code.end_ea, '48 81 EC A0 00 00 00 C7') pablo(code.start_ea, code.end_ea, '48 81 EC A8 00 00 00') # Script 2) Fix-up Dumped Data Pointers... if dumped or not kASLR: print('# Processing Pablo\'s Dumped Data Pointers IDC...') pablo(data.start_ea, data.end_ea, '?? FF FF FF FF') except: pass # -------------------------------------------------------------------------------------------------------- # Kiwidog's __stack_chk_fail if kASLR: print('# Processing Kiwidog\'s Stack Functions...') kiwidog(code.start_ea, code.end_ea, '73 74 61 63 6B 20 6F 76 65 72 66 6C 6F 77 20 64 65 74 65 63 74 65 64 3B') # -------------------------------------------------------------------------------------------------------- # Final Pass print('# Performing Final Pass...') address = code.start_ea while address < code.end_ea: address = idaapi.find_not_func(address, SEARCH_DOWN) if idaapi.isUnknown(idaapi.getFlags(address)): idaapi.create_insn(address) else: idc.add_func(address) address += 4 print('# Done!') return 1
def make_literal(addresses): for ea in addresses: idc.create_strlit(ea, idc.BADADDR) return addresses
def load_file(li, neflags, format): if format != "NeoGeo 68k loader": return 0 idaapi.set_processor_type("68000", SETPROC_ALL | SETPROC_FATAL) idaapi.add_segm(0, 0x000000, 0x0FFFFF, "ROM", "CODE") idaapi.add_segm(0, 0x100000, 0x10F2FF, "WRAM", "DATA") idaapi.add_segm(0, 0x10F300, 0x10FFFF, "BIOSRAM", "DATA") idaapi.add_segm(0, 0x200000, 0x2FFFFF, "PORT", "DATA") idaapi.add_segm(0, 0x300000, 0x3FFFFF, "IO", "DATA") idaapi.add_segm(0, 0x400000, 0x401FFF, "PALETTES", "DATA") idaapi.add_segm(0, 0x800000, 0xBFFFFF, "MEMCARD", "DATA") idaapi.add_segm(0, 0xC00000, 0xC1FFFF, "SYSROM", "DATA") idaapi.add_segm(0, 0xD00000, 0xD0FFFF, "BRAM", "DATA") map_io_registers() li.seek(0, 2) file_size = li.tell() li.seek(0) # read p1 rom file_data = li.read(0x100000) file_remain = file_size - 0x100000 idaapi.mem2base(file_data, 0, 0x100000) # read p2 rom bank2_seg_offset = 0x01000000 bank2_seg_index = 0 while file_remain > 0: bank2_seg_start = bank2_seg_offset + 0x200000 bank2_seg_end = bank2_seg_start + 0x2FFFFF idaapi.add_segm(0, bank2_seg_start, bank2_seg_end, "BANK2_%d" % bank2_seg_index, "DATA") bytes_to_read = file_remain if bytes_to_read > 0x100000: bytes_to_read = 0x100000 file_data = li.read(bytes_to_read) idaapi.mem2base(file_data, bank2_seg_start, bank2_seg_start + len(file_data)) bank2_seg_offset += 0x01000000 bank2_seg_index += 1 file_remain -= bytes_to_read # http://ajworld.net/neogeodev/beginner/ name_long(0x000000, "InitSP") name_long(0x000004, "InitPC") name_long(0x000008, "BusError") name_long(0x00000C, "AddressError") name_long(0x000010, "IllegalInstruction") name_long(0x000014, "DivByZero") name_long(0x000018, "CHK") name_long(0x00001C, "TRAPV") name_long(0x000020, "PrivilegeViolation") name_long(0x000024, "Trace") name_long(0x000028, "Line1010Emu") name_long(0x00002C, "Line1111Emu") name_array(0x000030, "Reserved0", 0xC) name_long(0x000003C, "UnintializedInterruptVec") name_array(0x000040, "Reserved1", 0x20) name_long(0x000060, "VirtualInterrupt") name_long(0x000064, "Interrupt1") name_long(0x000068, "Interrupt2") name_long(0x00006C, "Interrupt3") name_long(0x000070, "Interrupt4") name_long(0x000074, "Interrupt5") name_long(0x000078, "Interrupt6") name_long(0x00007C, "Interrupt7") name_dword_array(0x000080, "Traps", 0x10) name_array(0x0000C0, "Reserved2", 0x40) # Neo-Geo header # https://wiki.neogeodev.org/index.php?title=68k_program_header idc.create_strlit(0x000100, 0x000107) idaapi.set_name(0x000100, "Magic") name_byte(0x000107, "SysVersion") name_word(0x000108, "GameID") name_long(0x00010A, "ProgramSize") name_long(0x00010E, "BackupRAMPtr") name_word(0x000112, "BackupRAMSize") name_byte(0x000114, "EyecatchFlag") name_byte(0x000115, "EyecatchSpriteBank") name_long(0x000116, "MenuJP") name_long(0x00011A, "MenuUS") name_long(0x00011E, "MenuEU") name_code(0x000122, "Routine_USER", 6) name_code(0x000128, "Routine_PLAYER_START", 6) name_code(0x00012E, "Routine_DEMO_END", 6) name_code(0x000134, "Routine_COIN_SOUND", 6) name_array(0x00013A, "Unknown0", 0x48) name_long(0x000182, "CartridgeRecognitionCodePtr") name_long(0x000186, "Unknown1") name_long(0x00018A, "Unknown2") name_long(0x00018E, "MenuES") # Spanish # BIOS RAM set_name_with_comment(0x10FD80, "BIOS_SYSTEM_MODE", "0x00 : System" "0x80 : Game") set_name_with_comment(0x10FD82, "BIOS_MVS_FLAG", "0 : HOME/AES\n" "1 : MVS") set_name_with_comment( 0x10FDAE, "BIOS_USER_REQUEST", "0 : Startup initialization\n" "1 : Eye-catcher\n" "2 : Demo Game / Game\n" "3 : Title Display") set_name_with_comment( 0x10FDAF, "BIOS_USER_MODE", "Current game status.\n" "0 : init/boot\n" "1 : title/demo\n" "2 : game") set_name_with_comment( 0x10FEC5, "BIOS_TITLE_MODE", "Newer games set this to 1 in their command 3 USER subroutine.\n" "It prevents the system ROM from calling command 3 twice after game over if credits are already in the system.\n" ) #idaapi.del_items(0x3C0000) # VRAM set_name_with_comment( 0x3C0000, "REG_VRAMADDR", "sets the VRAM address for the next read/write operation.") set_name_with_comment(0x3C0002, "REG_VRAMRW", "the data read or to write.") set_name_with_comment( 0x3C0004, "REG_VRAMMOD", "the signed value automatically added to the VRAM address after a write." ) set_name_with_comment( 0x3C000C, "LSPC_IRQ_ACK", "IRQ acknowledgement register.\nbit2 : Ack.VBlank | bit 1 : Ack.HBlank | bit 0 : IRQ3" ) idaapi.set_name(0xC00444, "SYSTEM_RETURN") idaapi.set_name(0xC0044A, "SYSTEM_IO") idaapi.set_name(0xD00100, "BOARD_CORRUPTED") #idaapi.set_cmt(0x3C0000, "Pouet.", 1) return 1