Ejemplo n.º 1
0
    def comment(self, address, stubs, modules, libraries):

        if self.TAG in [Dynamic.DT_NEEDED, Dynamic.DT_SONAME]:
            return '%s | %s' % (self.tag(), stubs[self.VALUE])
        elif self.TAG == Dynamic.DT_SCE_HASH:
            return '%s | %#x' % (self.tag(), address + Dynamic.HASHTAB)
        elif self.TAG == Dynamic.DT_SCE_STRTAB:
            address += Dynamic.STRTAB
            idc.add_entry(address, address, '.dynstr', False)
            return '%s | %#x' % (self.tag(), address)
        elif self.TAG == Dynamic.DT_SCE_SYMTAB:
            address += Dynamic.SYMTAB
            idc.add_entry(address, address, '.dynsym', False)
            return '%s | %#x' % (self.tag(), address)
        elif self.TAG == Dynamic.DT_SCE_JMPREL:
            return '%s | %#x' % (self.tag(), address + Dynamic.JMPTAB)
        elif self.TAG == Dynamic.DT_SCE_RELA:
            return '%s | %#x' % (self.tag(), address + Dynamic.RELATAB)
        elif self.TAG in [
                Dynamic.DT_SCE_NEEDED_MODULE, Dynamic.DT_SCE_IMPORT_LIB,
                Dynamic.DT_SCE_IMPORT_LIB_ATTR, Dynamic.DT_SCE_EXPORT_LIB,
                Dynamic.DT_SCE_EXPORT_LIB_ATTR, Dynamic.DT_SCE_MODULE_INFO,
                Dynamic.DT_SCE_MODULE_ATTR, Dynamic.DT_SCE_ORIGINAL_FILENAME
        ]:
            self.ID = self.VALUE >> 48
            self.VERSION_MINOR = (self.VALUE >> 40) & 0xF
            self.VERSION_MAJOR = (self.VALUE >> 32) & 0xF
            self.INDEX = self.VALUE & 0xFFF

            if self.TAG in [
                    Dynamic.DT_SCE_NEEDED_MODULE, Dynamic.DT_SCE_MODULE_INFO
            ]:
                return '%s | MID:%#x Version:%i.%i Name:%s' % \
                       (self.tag(), self.ID, self.VERSION_MAJOR, self.VERSION_MINOR, modules[self.INDEX])
            elif self.TAG in [
                    Dynamic.DT_SCE_IMPORT_LIB, Dynamic.DT_SCE_EXPORT_LIB
            ]:
                return '%s | LID:%#x Version:%i Name:%s' % \
                       (self.tag(), self.ID, self.VERSION_MAJOR, libraries[self.INDEX])
            elif self.TAG == Dynamic.DT_SCE_MODULE_ATTR:
                return '%s | %s' % (self.tag(), self.mod_attribute())
            elif self.TAG in [
                    Dynamic.DT_SCE_IMPORT_LIB_ATTR,
                    Dynamic.DT_SCE_EXPORT_LIB_ATTR
            ]:
                return '%s | LID:%#x Attributes:%s' % \
                       (self.tag(), self.ID, self.lib_attribute())
            elif self.TAG == Dynamic.DT_SCE_ORIGINAL_FILENAME:
                return '%s | %s' % (self.tag(), stubs[self.VALUE])

        return '%s | %#x' % (self.tag(), self.VALUE)
Ejemplo n.º 2
0
    def resolve(self, address, nids, symbol):

        # Resolve the NID...
        idc.set_cmt(self.VALUE, 'NID: ' + symbol, False)
        function = nids.get(symbol[:11], symbol)

        #print('Function: %s | number: %s' % (function, idaapi.get_func_num(self.VALUE)))
        if idaapi.get_func_num(self.VALUE) > 0:
            idc.del_func(self.VALUE)

        if self.VALUE > 0:
            idc.add_func(self.VALUE)
            idc.add_entry(self.VALUE, self.VALUE, function, True)
            idc.set_name(self.VALUE, function, SN_NOCHECK | SN_NOWARN)
            idc.set_cmt(address, '%s | %s' % (function, self.info()), False)
Ejemplo n.º 3
0
def xex_load_exports(li):
    global export_table_va

    export_table = HvImageExportTable()
    slen = ctypes.sizeof(export_table)
    bytes = ida_bytes.get_bytes(export_table_va, slen)
    fit = min(len(bytes), slen)
    ctypes.memmove(ctypes.addressof(export_table), bytes, fit)

    if export_table.Magic[0] != XEX_EXPORT_MAGIC_0 or export_table.Magic[
            1] != XEX_EXPORT_MAGIC_1 or export_table.Magic[
                2] != XEX_EXPORT_MAGIC_2:
        print("[+] Export table magic is invalid! (0x%X 0x%X 0x%X)" %
              (export_table.Magic[0], export_table.Magic[1],
               export_table.Magic[2]))
        return 0

    print("[+] Loading module exports...")
    print(export_table)

    ordinal_addrs_va = export_table_va + slen
    for i in range(0, export_table.Count):
        func_ord = export_table.Base + i
        func_va = ida_bytes.get_dword(ordinal_addrs_va + (i * 4))
        if func_va == 0:
            continue

        func_va = func_va + (export_table.ImageBaseAddress << 16)
        func_name = x360_imports.DoNameGen(idc.get_root_filename(), 0,
                                           func_ord)

        # Add to exports list & mark as func if inside a code section
        func_segmclass = ida_segment.get_segm_class(
            ida_segment.getseg(func_va))
        idc.add_entry(func_ord, func_va, func_name,
                      1 if func_segmclass == "CODE" else 0)

        if func_segmclass == "CODE":
            idc.add_func(func_va)

    return 1
Ejemplo n.º 4
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
Ejemplo n.º 5
0
    def process(self, stubs, modules, libraries):

        if self.TAG == Dynamic.DT_INIT:
            Dynamic.INIT = self.VALUE
            idc.add_entry(Dynamic.INIT, Dynamic.INIT, '.init', True)
        elif self.TAG == Dynamic.DT_FINI:
            Dynamic.FINI = self.VALUE
            idc.add_entry(Dynamic.FINI, Dynamic.FINI, '.fini', True)
        elif self.TAG in [Dynamic.DT_NEEDED, Dynamic.DT_SONAME]:
            stubs[self.VALUE] = 0
        elif self.TAG == Dynamic.DT_SCE_STRTAB:
            Dynamic.STRTAB = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_STRSZ:
            Dynamic.STRTABSZ = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_SYMTAB:
            Dynamic.SYMTAB = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_SYMTABSZ:
            Dynamic.SYMTABSZ = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_JMPREL:
            Dynamic.JMPTAB = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_PLTRELSZ:
            Dynamic.JMPTABSZ = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_PLTREL:
            if self.VALUE == 0x7:
                return '%s | %#x | DT_RELA' % (self.tag(), self.VALUE)
        elif self.TAG == Dynamic.DT_SCE_RELA:
            Dynamic.RELATAB = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_RELASZ:
            Dynamic.RELATABSZ = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_HASH:
            Dynamic.HASHTAB = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_HASHSZ:
            Dynamic.HASHTABSZ = self.VALUE
        elif self.TAG == Dynamic.DT_SCE_PLTGOT:
            Dynamic.GOT = self.VALUE
            idc.add_entry(Dynamic.GOT, Dynamic.GOT, '.got.plt', False)
        elif self.TAG in [
                Dynamic.DT_SCE_NEEDED_MODULE, Dynamic.DT_SCE_IMPORT_LIB,
                Dynamic.DT_SCE_IMPORT_LIB_ATTR, Dynamic.DT_SCE_EXPORT_LIB,
                Dynamic.DT_SCE_EXPORT_LIB_ATTR, Dynamic.DT_SCE_MODULE_INFO,
                Dynamic.DT_SCE_MODULE_ATTR, Dynamic.DT_SCE_ORIGINAL_FILENAME
        ]:
            self.ID = self.VALUE >> 48
            self.VERSION_MINOR = (self.VALUE >> 40) & 0xF
            self.VERSION_MAJOR = (self.VALUE >> 32) & 0xF
            self.INDEX = self.VALUE & 0xFFF

            if self.TAG in [
                    Dynamic.DT_SCE_NEEDED_MODULE, Dynamic.DT_SCE_MODULE_INFO
            ]:
                if self.INDEX not in modules:
                    modules[self.INDEX] = 0
                return '%s | MID:%#x Version:%i.%i | %#x' % \
                       (self.tag(), self.ID, self.VERSION_MAJOR, self.VERSION_MINOR, self.INDEX)
            elif self.TAG in [
                    Dynamic.DT_SCE_IMPORT_LIB, Dynamic.DT_SCE_EXPORT_LIB
            ]:
                if self.INDEX not in libraries:
                    libraries[self.INDEX] = self.ID
                return '%s | LID:%#x Version:%i | %#x' % \
                       (self.tag(), self.ID, self.VERSION_MAJOR, self.INDEX)
            elif self.TAG == Dynamic.DT_SCE_MODULE_ATTR:
                return '%s | %s' % (self.tag(), self.mod_attribute())
            elif self.TAG in [
                    Dynamic.DT_SCE_IMPORT_LIB_ATTR,
                    Dynamic.DT_SCE_EXPORT_LIB_ATTR
            ]:
                return '%s | LID:%#x Attributes:%s' % \
                       (self.tag(), self.ID, self.lib_attribute())
            elif self.TAG == Dynamic.DT_SCE_ORIGINAL_FILENAME:
                stubs[self.INDEX] = 0

        return '%s | %#x' % (self.tag(), self.VALUE)
Ejemplo n.º 6
0
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(li, neflags, format):
    # ensure we are not wrongly called
    if not format.startswith("Accessory Firmware Update"):
        return 0

    li.seek(0)
    data = li.read(0x14)
    (magic, xxx1, fw_type, fw_ver, fw_len, unk1, product_id,
     hw_rev_id) = struct.unpack("<HHHHIIHH", data)

    li.seek(0x20)
    AFU_signature_header_data = li.read(24)

    (sig_magic, unknown1, unknown2, digest_type, digest_len, digest_offset,
     sig_type, sig_len, sig_offset) = struct.unpack("<IHHHHIHHI",
                                                    AFU_signature_header_data)

    idaapi.set_processor_type("ARM:ARMv7-M", ida_idp.SETPROC_ALL)

    if product_id == 0x312:  # Apple Pencil
        fw_base = 0x8006080
        msp_base = fw_base
    elif product_id == 0x14c:  # Apple Pencil 2
        if fw_type == 1:
            fw_base = 0x08000980
            msp_base = fw_base + 0x180
        if fw_type == 0x20:
            fw_base = 0x0
            msp_base = fw_base
        if fw_type == 0x30:
            fw_base = 0x0
            msp_base = fw_base
        if fw_type == 0x50:
            fw_base = 0x08000000
            msp_base = fw_base
    elif product_id == 0x26d:  # Siri Remote 2
        if fw_type == 1:
            fw_base = 0x8008080
            msp_base = fw_base + 0x180
        if fw_type == 0xb0:
            fw_base = 0x280
            msp_base = fw_base + 0x180
    elif product_id == 0x268:  # Smart Keyboard 12.9"
        fw_base = 0x08002600
        msp_base = fw_base
    elif product_id == 0x26A:  # Smart Keyboard 9.7"
        fw_base = 0x08002600
        msp_base = fw_base
    elif product_id == 0x26B:  # Smart Keyboard 10.5"
        fw_base = 0x08002600  # don't really know, haven't seen an OTA so far
        msp_base = fw_base
    elif product_id == 0x292:  # Smart Keyboard Folio 11"
        fw_base = 0x08000980  # seems to work
        msp_base = fw_base + 0x180
    elif product_id == 0x293:  # Smart Keyboard Folio 12.9"
        fw_base = 0x08000980  # seems to work
        msp_base = fw_base + 0x180
    else:
        return 0

    # for now a heuristic
    show_header = True
    if fw_type != 1 or fw_base == 0:
        show_header = False

    if show_header:
        li.file2base(0, fw_base - 0x80, fw_base, 1)
    li.file2base(0x80, fw_base, fw_base + fw_len, 1)

    if show_header:
        idaapi.add_segm(0, fw_base - 0x80, fw_base, "HEADER", "DATA")
    idaapi.add_segm(0, fw_base, fw_base + fw_len, "__TEXT", "CODE")
    idaapi.add_segm(0, 0xE000E000, 0xE000F000, "__SYSREG", "DATA")
    idaapi.add_segm(0, SRAM_BASE, SRAM_BASE + SRAM_SIZE, "__SRAM", "DATA")

    if show_header:
        idc.split_sreg_range(fw_base - 0x80, "T", 1)
    idc.split_sreg_range(fw_base, "T", 1)

    # register the structures
    register_structs()

    # apply the structure
    if show_header:
        idc.set_name(fw_base - 0x80, "AFU_HEADER")
        idc.create_struct(fw_base - 0x80, -1, "afu_full_header")
        ida_nalt.unhide_item(fw_base - 0x80 + 1)

    # handle the digest and signature

    if sig_magic == 0x61E34724:

        # apply the structure
        if show_header:
            idc.set_name(fw_base - 0x80 + 0x20, "AFU_SIG_HEADER")
        #idc.create_struct(fw_base - 0x80 + 0x20, -1, "afu_sig_header")
        #ida_nalt.unhide_item(fw_base - 0x80 + 0x20 + 1)

        # first handle the digest
        base = fw_base + fw_len
        li.file2base(digest_offset, base, base + digest_len, 1)
        idaapi.add_segm(0, base, base + digest_len, "__DIGEST", "DATA")
        idc.create_byte(base)
        idc.make_array(base, digest_len)
        idc.set_name(base, "AFU_DIGEST")

        # now handle the signature
        base += digest_len
        li.file2base(sig_offset, base, base + sig_len, 1)
        idaapi.add_segm(0, base, base + sig_len, "__SIGNATURE", "DATA")
        idc.create_byte(base)
        idc.make_array(base, sig_len)
        idc.set_name(base, "AFU_SIGNATURE")

    # check if __TEXT starts with an SRAM address
    # this is the initial MSP that is followed by exception vectors
    initMSP = idc.Dword(msp_base)
    print "initMSP 0x%x" % initMSP
    if (initMSP >= SRAM_BASE) and initMSP <= (SRAM_BASE + SRAM_SIZE):

        idc.set_name(msp_base, "init_MSP")
        idc.create_dword(msp_base)
        idc.op_plain_offset(msp_base, -1, 0)
        idc.set_cmt(msp_base, "Initial MSP value", 0)

        # these are now the exception vectors

        # determine how many exception vectors there are
        cnt = 0
        handlers = {}
        last_multi = None
        multi = False

        while cnt < 255:
            ptr = idc.Dword(msp_base + 4 + 4 * cnt)
            if ptr != 0:

                # must be inside __TEXT
                if (ptr < fw_base) or (ptr > fw_base + fw_len):
                    break

                if (ptr & 1) == 0:  # must be thumb mode
                    break

            # convert into a dword + offset
            idc.create_dword(msp_base + 4 + 4 * cnt)
            if ptr != 0:
                idc.op_offset(msp_base + 4 + 4 * cnt, 0, idc.REF_OFF32, -1, 0,
                              0)
            idc.set_cmt(
                msp_base + 4 + 4 * cnt,
                "exception %d: %s" % (cnt + 1, exception_table[cnt + 1]), 0)

            # should only RESET vector be our entrypoint?
            idc.add_entry(ptr & ~1, ptr & ~1, "", 1)

            # remember how often we see each handler
            if ptr != 0:
                if handlers.has_key(ptr):
                    handlers[ptr] += 1
                    if last_multi != None:
                        if last_multi != ptr:
                            multi = True
                    last_multi = ptr
                else:
                    handlers[ptr] = 1

            cnt += 1

        print "cnt: %d" % cnt

        if cnt > 0:
            i = 1
            while i <= cnt:
                ptr = idc.Dword(msp_base + 4 * i)

                if ptr != 0:
                    # ensure this is
                    if handlers[ptr] == 1:
                        idc.set_name(
                            ptr & ~1,
                            "%s_%s" % (EXCEPTION_PREFIX, exception_table[i]))

                    elif not multi:
                        idc.set_name(ptr & ~1,
                                     "%s_%s" % (EXCEPTION_PREFIX, "UNIMPL"))

                i += 1

    return 1
Ejemplo n.º 8
0
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