Beispiel #1
0
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
Beispiel #3
0
    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
Beispiel #4
0
 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()
Beispiel #5
0
 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
Beispiel #6
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
Beispiel #7
0
 def make_string(self, offset, size):
     """Convert range to byte string in IDB"""
     self.ret = idc.create_strlit(offset, offset + size)
     return self.ret
Beispiel #8
0
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
Beispiel #10
0
def make_literal(addresses):
    for ea in addresses:
        idc.create_strlit(ea, idc.BADADDR)
    return addresses
Beispiel #11
0
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