def pe_add_section(section): global base_address # Segment permissions seg_perms = 0 if section.Characteristics & IMAGE_SCN_MEM_EXECUTE: seg_perms |= ida_segment.SEGPERM_EXEC if section.Characteristics & IMAGE_SCN_MEM_READ: seg_perms |= ida_segment.SEGPERM_READ if section.Characteristics & IMAGE_SCN_MEM_WRITE: seg_perms |= ida_segment.SEGPERM_WRITE # Segment type seg_class = "DATA" if section.Characteristics & IMAGE_SCN_CNT_CODE: seg_class = "CODE" seg_addr = base_address + section.VirtualAddress idaapi.add_segm(0, seg_addr, seg_addr + section.VirtualSize, section.Name, seg_class) idc.set_segm_alignment(seg_addr, idc.saRelPara) idc.set_segm_attr(seg_addr, idc.SEGATTR_PERM, seg_perms) idc.set_default_sreg_value( seg_addr, "DS", 0) # how is DS meant to be set? prolly don't matter but still idc.set_default_sreg_value(seg_addr, "VLE", 0)
def segment(f, start, end, name, type='DATA', perm=SEGPERM_MAXVAL): f.file2base(start, start, end, FILEREG_PATCHABLE) flags = 0x0 if name in ['PA1', 'BFA', 'MIRROR'] else ADDSEG_NOAA ida.add_segm(0x0, start, end, name, type, flags) # Processor Specific Segment Details idc.set_segm_addressing(start, 0x1) idc.set_segm_alignment(start, saAbs) idc.set_segm_combination(start, scPriv) idc.set_segm_attr(start, SEGATTR_PERM, perm)
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 load_file(f, neflags, format): print('# PS3 Syscon Loader') # PS3 Syscon Processor and Library processor('arm', 'gnulnx_arm') print('# Creating ROM Segment...') address = 0x0 end = address + f.size() f.file2base(address, address, end, FILEREG_PATCHABLE) idaapi.add_segm(0x0, address, end, 'ROM', 'CODE', 0x0) # Processor Specific Segment Details idc.set_segm_addressing(address, 0x1) idc.set_segm_alignment(address, saAbs) idc.set_segm_combination(address, scPriv) idc.set_segm_attr(address, SEGATTR_PERM, SEGPERM_MAXVAL) idc.set_default_sreg_value(address, 'T', 0x0) idc.set_default_sreg_value(address, 'DS', 0x1) print('# Waiting for the AutoAnalyzer to Complete...') idaapi.auto_wait() # Create some missing functions... while address < end: address = idaapi.find_binary(address, end, '?? B5', 0x10, SEARCH_DOWN) idaapi.create_insn(address) # Pablo escobar if idc.print_insn_mnem(address + 2) in ['LDR', 'MOVS', 'SUB']: idc.add_func(address) else: idaapi.do_unknown(address) address += 4 print('# Done!') return 1 # PROGRAM END
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 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 load_file(f, neflags, format): print('# PS4 Kernel Loader') ps4 = Binary(f) # PS4 Processor, Compiler, Library bitness = ps4.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL, 'gnulnx_x64') # Segment Loading... for segm in ps4.E_SEGMENTS: # 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: 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) # -------------------------------------------------------------------------------------------------------- # 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) 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(ps4.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 # Start Function idc.add_entry(ps4.E_START_ADDR, ps4.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 | SN_FORCE) # -------------------------------------------------------------------------------------------------------- # 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 Structures...') # 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... # Default patterns set pablo(0, code.start_ea, 0x10, '55 48 89') pablo(2, code.start_ea, code.end_ea, '90 90 55 48 ??') pablo(2, code.start_ea, code.end_ea, 'C3 90 55 48 ??') pablo(2, code.start_ea, code.end_ea, '66 90 55 48 ??') pablo(2, code.start_ea, code.end_ea, 'C9 C3 55 48 ??') pablo(2, code.start_ea, code.end_ea, '0F 0B 55 48 ??') pablo(2, code.start_ea, code.end_ea, 'EB ?? 55 48 ??') pablo(2, code.start_ea, code.end_ea, '5D C3 55 48 ??') pablo(2, code.start_ea, code.end_ea, '5B C3 55 48 ??') pablo(2, code.start_ea, code.end_ea, '90 90 55 41 ?? 41 ??') pablo(2, code.start_ea, code.end_ea, '66 90 48 81 EC ?? 00 00 00') pablo(2, code.start_ea, code.end_ea, '0F 0B 48 89 9D ?? ?? FF FF 49 89') pablo(2, code.start_ea, code.end_ea, '90 90 53 4C 8B 54 24 20') pablo(2, code.start_ea, code.end_ea, '90 90 55 41 56 53') pablo(2, code.start_ea, code.end_ea, '90 90 53 48 89') pablo(2, code.start_ea, code.end_ea, '90 90 41 ?? 41 ??') pablo(3, code.start_ea, code.end_ea, '0F 0B 90 55 48 ??') pablo(3, code.start_ea, code.end_ea, 'EB ?? 90 55 48 ??') pablo(3, code.start_ea, code.end_ea, '41 5F C3 55 48 ??') pablo(3, code.start_ea, code.end_ea, '41 5C C3 55 48 ??') pablo(3, code.start_ea, code.end_ea, '31 C0 C3 55 48 ??') pablo(3, code.start_ea, code.end_ea, '41 5D C3 55 48 ??') pablo(3, code.start_ea, code.end_ea, '41 5E C3 55 48 ??') pablo(3, code.start_ea, code.end_ea, '66 66 90 55 48 ??') pablo(3, code.start_ea, code.end_ea, '0F 1F 00 55 48 ??') pablo(3, code.start_ea, code.end_ea, '41 ?? C3 53 48') pablo(3, code.start_ea, code.end_ea, '0F 1F 00 48 81 EC ?? 00 00 00') pablo(4, code.start_ea, code.end_ea, '0F 1F 40 00 55 48 ??') pablo(4, code.start_ea, code.end_ea, '0F 1F 40 00 48 81 EC ?? 00 00 00') pablo(5, code.start_ea, code.end_ea, 'E9 ?? ?? ?? ?? 55 48 ??') pablo(5, code.start_ea, code.end_ea, 'E8 ?? ?? ?? ?? 55 48 ??') pablo(5, code.start_ea, code.end_ea, '48 83 C4 ?? C3 55 48 ??') pablo(5, code.start_ea, code.end_ea, '0F 1F 44 00 00 55 48 ??') pablo(5, code.start_ea, code.end_ea, '0F 1F 44 00 00 48 81 EC ?? 00 00 00') pablo(6, code.start_ea, code.end_ea, 'E9 ?? ?? ?? ?? 90 55 48 ??') pablo(6, code.start_ea, code.end_ea, 'E8 ?? ?? ?? ?? 90 55 48 ??') pablo(6, code.start_ea, code.end_ea, '66 0F 1F 44 00 00 55 48 ??') pablo(7, code.start_ea, code.end_ea, '0F 1F 80 00 00 00 00 55 48 ??') pablo(8, code.start_ea, code.end_ea, '0F 1F 84 00 00 00 00 00 55 48 ??') pablo(8, code.start_ea, code.end_ea, 'C3 0F 1F 80 00 00 00 00 48') pablo(8, code.start_ea, code.end_ea, '0F 1F 84 00 00 00 00 00 53 48 83 EC') # Special cases patterns set pablo(13, code.start_ea, code.end_ea, 'C3 90 90 90 90 90 90 90 90 90 90 90 90 48') pablo(13, code.start_ea, code.end_ea, 'C3 90 90 90 90 90 90 90 90 90 90 90 90 55') pablo(17, code.start_ea, code.end_ea, 'E9 ?? ?? ?? ?? 90 90 90 90 90 90 90 90 90 90 90 90 48') pablo(19, code.start_ea, code.end_ea, 'E9 ?? ?? ?? ?? 90 90 90 90 90 90 90 90 90 90 90 90 90 90 48') pablo(19, code.start_ea, code.end_ea, 'E8 ?? ?? ?? ?? 90 90 90 90 90 90 90 90 90 90 90 90 90 90 48') pablo( 20, code.start_ea, code.end_ea, 'E9 ?? ?? ?? ?? 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 48') pablo( 20, code.start_ea, code.end_ea, 'E9 ?? ?? ?? ?? 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 48') # Script 2) Fix-up Dumped Data Pointers... if dumped: print('# Processing Pablo\'s Dumped Data Pointers IDC...') pablo(0, data.start_ea, data.end_ea, '?? FF FF FF FF') except: pass # -------------------------------------------------------------------------------------------------------- # Kiwidog's __stack_chk_fail 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' ) print('# Done!') return 1