Ejemplo n.º 1
0
def make_vector(addr, name):
    ida_bytes.create_dword(addr, 4)
    idaapi.create_insn(addr)
    idaapi.ida_funcs.add_func(addr, idaapi.ida_idaapi.BADADDR)
    idaapi.add_cref(addr, addr, idaapi.fl_CF)
    if len(name) > 0:
        idc.set_name(addr, name)
    return 1
Ejemplo n.º 2
0
def create_68k_jump_table(idiom_ea):
    """ Create a jump table at the current address in the database.

        This function sets the switch idiom attributes for the current address
        in the database.  If switch_base is none, find_switch_attributes() was
        not successful.
    """
    switch_base, max_offset, value_base, value_width, defjump = _find_switch_attributes(idiom_ea)

    if switch_base != None:
        jump_table_size = max_offset + 1
        total_switch_size = 2 * (max_offset + 1)
        switch_base_ea = idc.GetOperandValue(idiom_ea, 0)
        _make_offset_table(switch_base, jump_table_size)
        # create the switch info object
        si = idaapi.switch_info_ex_t()
        si.set_jtable_element_size(2)
        si.startea = idiom_ea
        si.jumps = switch_base
        si.elbase = switch_base
        si.ncases = jump_table_size
        si.regnum = 1 # 1 is IDA's representation of d1
        
        # added by gph
        Message("default jump: %08X\n" % defjump)
        si.flags |= idaapi.SWI_DEFAULT
        si.defjump = defjump
        
        # if we found a value table...
        if value_base != None and value_width != None:
            si.values = value_base
            si.set_vtable_element_size(value_width)
            total_switch_size = jump_table_size * (2 + value_width)
            
        si.flags |= idaapi.SWI_ELBASE | idaapi.SWI_SPARSE
        idaapi.set_switch_info_ex(idiom_ea, si)
        idaapi.create_switch_table(idiom_ea, si)
        idaapi.setFlags(idiom_ea, idaapi.getFlags(idiom_ea) | idaapi.FF_JUMP)
        # go to the end of the switch statement and make an instruction
        idaapi.create_insn(switch_base + total_switch_size)
        return True
    else:
        print "Error: Could not get jump table size."
        return False
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
def pablo(address, end, search):
    
    while address < end:
        address = idaapi.find_binary(address, end, search, 0x10, SEARCH_DOWN)
        
        if address > idaapi.get_segm_by_name('CODE').end_ea:
            offset = address - 0x3
            
            if idaapi.isUnknown(idaapi.getFlags(offset)):
                if idaapi.get_qword(offset) <= end:
                    idaapi.create_data(offset, FF_QWORD, 0x8, BADNODE)
            
            address = offset + 4
        
        else:
            idaapi.do_unknown(address, 0)
            idaapi.create_insn(address)
            idaapi.add_func(address, BADADDR)
            address += 4
Ejemplo n.º 5
0
    def __init__(self, ea, info, cs):
        """Initialization function."""
        # Init the node structure
        node_t.__init__(self)

        # Check if it's a code instruction
        try:
            is_c = is_code(get_flags(ea))
        except:
            is_c = isCode(GetFlags(ea))
        if not is_c:
            raise CodeException

        #
        # fill node_t struct
        #

        # NodeInfo
        self.info = NodeInfo()
        inst_elements = []

        try:
            size = create_insn(ea)
            bytes = get_bytes(ea, size)
        except:
            size = MakeCode(ea)
            bytes = GetManyBytes(ea, size)

        (address, size, mnemonic, op_str) = cs.disasm_lite(bytes, ea, count=1).next()
        self.info.opcode = mnemonic.encode("ascii", "ignore")

        op_str_ascci = op_str.encode("ascii", "ignore")
        self.info.inst_str = self.info.opcode + " " + op_str_ascci

        splitted = op_str_ascci.split(", ")
        self.info.nargs = 0

        if len(splitted) >= 1:
            self.info.arg1 = splitted[0]
            self.info.nargs += 1
            if len(splitted) >= 2:
                self.info.arg2 = splitted[1]
                self.info.nargs += 1
                if len(splitted) >= 3:
                    self.info.arg3 = splitted[2]
                    self.info.nargs += 1

        # No node will be root but this is acceptable for CFGs
        self.info.is_root = False

        self.info.address = ea
        self.info.has_address = True

        # node_t
        self.node_id = self._genid()
Ejemplo n.º 6
0
def define_func(addr, name):

    if addr & 1:
        addr -= 1
        idaapi.split_sreg_range(addr, idaapi.str2reg("T"), 1, idaapi.SR_user)
    else:
        idaapi.split_sreg_range(addr, idaapi.str2reg("T"), 0, idaapi.SR_user)

    if idaapi.create_insn(addr):
        idc.add_func(addr)
        idaapi.set_name(addr, name, idaapi.SN_FORCE)
Ejemplo n.º 7
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.º 8
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
Ejemplo n.º 9
0
Archivo: Node.py Proyecto: yaps8/grap
    def __init__(self, ea, cs, IDA_inst, IDA_inst_size, IDA_inst_string):
        """Initialization function, to disassemble with Capstone"""
        # Init the node structure
        node_t.__init__(self)

        # Check if it's a code instruction
        try:
            is_c = is_code(get_flags(ea))
        except:
            is_c = isCode(GetFlags(ea))
        if not is_c:
            raise CodeException

        #
        # fill node_t struct
        #

        # NodeInfo
        self.info = NodeInfo()
        inst_elements = []

        if cs is not None:
            try:
                size = create_insn(ea)
                bytes = get_bytes(ea, size)
            except:
                size = MakeCode(ea)
                bytes = GetManyBytes(ea, size)

            (address, size, mnemonic,
             op_str) = next(cs.disasm_lite(bytes, ea, count=1))
        else:
            address = ea
            size = IDA_inst_size
            splitted = IDA_inst_string.split(" ")
            mnemonic = splitted[0]
            op_str = " ".join(splitted[1:])

        self.info.opcode = mnemonic
        self.info.inst_str = self.info.opcode + " " + op_str

        splitted = op_str.split(", ")
        self.info.nargs = 0

        if len(splitted) >= 1:
            self.info.arg1 = splitted[0]
            self.info.nargs += 1
            if len(splitted) >= 2:
                self.info.arg2 = splitted[1]
                self.info.nargs += 1
                if len(splitted) >= 3:
                    self.info.arg3 = splitted[2]
                    self.info.nargs += 1

        # No node will be root but this is acceptable for CFGs
        self.info.is_root = False

        self.info.address = ea
        self.info.has_address = True

        # node_t
        self.node_id = self._genid()
Ejemplo n.º 10
0
def load_file(f, neflags, format):

    print('# PS Vita Syscon Loader')

    # PS Vita Syscon Processor
    processor('rl78')

    # 0x0 - 0x80
    print('# Creating Vector Table Area 0')
    segment(f, 0x0, 0x80, 'VTA0', 'CODE', SEGPERM_READ | SEGPERM_EXEC)

    # 0x80 - 0xC0
    print('# Creating CALLT Table Area 0')
    segment(f, 0x80, 0xC0, 'CALLTTA0')

    for callt in xrange(0x20):
        address = 0x80 + (callt * 2)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)

    # 0xC0 - 0xC4
    print('# Creating Option Byte Area 0')
    segment(f, 0xC0, 0xC4, 'OBA0')

    ida.create_data(0xC0, FF_BYTE, 0x4, BADNODE)

    # 0xC4 - 0xCE
    print('# Creating On-chip Debug Security 0')
    segment(f, 0xC4, 0xCE, 'ODS0')

    ida.create_data(0xC4, FF_BYTE, 0xA, BADNODE)

    # 0xCE - 0x1000
    print('# Creating Program Area 0')
    segment(f, 0xCE, 0x1000, 'PA0', 'CODE', SEGPERM_READ | SEGPERM_EXEC)

    # 0x1000 - 0x1080
    print('# Creating Vector Table Area 1')
    segment(f, 0x1000, 0x1080, 'VTA1')

    # 0x1080 - 0x10C0
    print('# Creating CALLT Table Area 1')
    segment(f, 0x1080, 0x10C0, 'CALLTTA1')

    for callt in xrange(0x20):
        address = 0x1080 + (callt * 2)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)

    # 0x10C0 - 0x10C4
    print('# Creating Option Byte Area 1')
    segment(f, 0x10C0, 0x10C4, 'OBA1')

    ida.create_data(0x10C0, FF_BYTE, 0x4, BADNODE)

    # 0x10C4 - 0x10CE
    print('# Creating On-chip Debug Security 1')
    segment(f, 0x10C4, 0x10CE, 'ODS1')

    ida.create_data(0x10C4, FF_BYTE, 0xA, BADNODE)

    # 0x10CE - 0x60000
    print('# Creating Program Area 1')
    segment(f, 0x10CE, 0x60000, 'PA1', 'CODE', SEGPERM_READ | SEGPERM_EXEC)

    VTA = [
        'RST',
        'INTDBG',
        'INTWDTI',
        'INTLVI',
        'INTP0',
        'INTP1',
        'INTP2',
        'INTP3',
        'INTP4',
        'INTP5',
        'INTST2',
        'INTSR2',
        'INTSRE2',
        'INTDMA0',
        'INTDMA1',
        'INTST0',
        'INTSR0',
        'INTSRE0',
        'INTST1',
        'INTSR1',
        'INTSRE1',
        'INTIICA0',
        'INTTM00',
        'INTTM01',
        'INTTM02',
        'INTTM03',
        'INTAD',
        'INTRTC',
        'INTIT',
        'INTKR',
        'INTST3',
        'INTSR3',
        'INTTM13',
        'INTTM04',
        'INTTM05',
        'INTTM06',
        'INTTM07',
        'INTP6',
        'INTP7',
        'INTP8',
        'INTP9',
        'INTP10',
        'INTP11',
        'INTTM10',
        'INTTM11',
        'INTTM12',
        'INTSRE3',
        'INTMD',
        'INTIICA1',
        'INTFL',
        'INTDMA2',
        'INTDMA3',
        'INTTM14',
        'INTTM15',
        'INTTM16',
        'INTTM17',
        '',  # 0x70
        '',  # 0x72
        '',  # 0x74
        '',  # 0x76
        '',  # 0x78
        '',  # 0x7A
        '',  # 0x7C
        'BRK_I',
    ]

    # Create Additional Functions from VTA0
    address = 0x0
    for vec in VTA:
        function = ida.get_word(address)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)

        if vec != '':
            ida.set_name(address, vec, SN_NOCHECK | SN_NOWARN | SN_FORCE)

        if function:
            ida.create_insn(function)
            ida.add_func(function, BADADDR)
            ida.op_plain_offset(address, 0, 0)

        address += 2

    # Create Additional Functions from VTA1
    address = 0x1000
    for vec in VTA:
        function = ida.get_word(address)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)

        if vec != '':
            ida.set_name(address, vec, SN_NOCHECK | SN_NOWARN | SN_FORCE)

        if function:
            ida.create_insn(function)
            ida.add_func(function, BADADDR)
            ida.op_plain_offset(address, 0, 0)

        address += 2
    '''
    # 0x60000 - 0xEF000
    print('# Creating Guarded')
    segment(f, 0x60000, 0xEF000, 'GUARD')
    
    # Compress the segment
    ida.create_data(0x60000, FF_BYTE, 0x8F000, BADNODE)
    '''

    # 0xEF000 - 0xF0000
    print('# Creating Bootloader Flash Area')
    segment(f, 0xEF000, 0xF0000, 'BFA', 'CODE', SEGPERM_READ | SEGPERM_EXEC)

    # Bootloader/Flash Programming Areas
    for entry in xrange(0xEFFF0, 0xF0000, 0x4):
        ida.create_insn(entry)
        ida.add_func(entry, BADADDR)
        if entry == 0xEFFF8:
            ida.set_name(entry, 'FalshFirm', SN_NOCHECK | SN_NOWARN | SN_FORCE)

    # 0xF0000 - 0xF0800
    print('# Creating Special Function Registers 2')
    segment(f, 0xF0000, 0xF0800, 'SFR2')

    SFR2 = [
        (0xF0001, 0x1, 'ADM2', 'A/D converter mode register 2'),
        (0xF0011, 0x1, 'ADUL',
         'Conversion result comparison upper limit setting register'),
        (0xF0012, 0x1, 'ADLL',
         'Conversion result comparison lower limit setting register'),
        (0xF0013, 0x1, 'ADTES', 'A/D test register'),
        (0xF0030, 0x1, 'PU0', 'Pull-up resistor option register 0'),
        (0xF0031, 0x1, 'PU1', 'Pull-up resistor option register 1'),
        (0xF0033, 0x1, 'PU3', 'Pull-up resistor option register 3'),
        (0xF0034, 0x1, 'PU4', 'Pull-up resistor option register 4'),
        (0xF0035, 0x1, 'PU5', 'Pull-up resistor option register 5'),
        (0xF0036, 0x1, 'PU6', 'Pull-up resistor option register 6'),
        (0xF0037, 0x1, 'PU7', 'Pull-up resistor option register 7'),
        (0xF0038, 0x1, 'PU8', 'Pull-up resistor option register 8'),
        (0xF0039, 0x1, 'PU9', 'Pull-up resistor option register 9'),
        (0xF003A, 0x1, 'PU10', 'Pull-up resistor option register 10'),
        (0xF003B, 0x1, 'PU11', 'Pull-up resistor option register 11'),
        (0xF003C, 0x1, 'PU12', 'Pull-up resistor option register 12'),
        (0xF003E, 0x1, 'PU14', 'Pull-up resistor option register 14'),
        (0xF0040, 0x1, 'PIM0', 'Port input mode register 0'),
        (0xF0041, 0x1, 'PIM1', 'Port input mode register 1'),
        (0xF0044, 0x1, 'PIM4', 'Port input mode register 4'),
        (0xF0045, 0x1, 'PIM5', 'Port input mode register 5'),
        (0xF0048, 0x1, 'PIM8', 'Port input mode register 8'),
        (0xF004E, 0x1, 'PIM14', 'Port input mode register 14'),
        (0xF0050, 0x1, 'POM0', 'Port output mode register 0'),
        (0xF0051, 0x1, 'POM1', 'Port output mode register 1'),
        (0xF0054, 0x1, 'POM4', 'Port output mode register 4'),
        (0xF0055, 0x1, 'POM5', 'Port output mode register 5'),
        (0xF0057, 0x1, 'POM7', 'Port output mode register 7'),
        (0xF0058, 0x1, 'POM8', 'Port output mode register 8'),
        (0xF0059, 0x1, 'POM9', 'Port output mode register 9'),
        (0xF005E, 0x1, 'POM14', 'Port output mode register 14'),
        (0xF0060, 0x1, 'PMC0', 'Port mode control register 0'),
        (0xF0063, 0x1, 'PMC3', 'Port mode control register 3'),
        (0xF006A, 0x1, 'PMC10', 'Port mode control register 10'),
        (0xF006B, 0x1, 'PMC11', 'Port mode control register 11'),
        (0xF006C, 0x1, 'PMC12', 'Port mode control register 12'),
        (0xF006E, 0x1, 'PMC14', 'Port mode control register 14'),
        (0xF0070, 0x1, 'NFEN0', 'Noise filter enable register 0'),
        (0xF0071, 0x1, 'NFEN1', 'Noise filter enable register 1'),
        (0xF0072, 0x1, 'NFEN2', 'Noise filter enable register 2'),
        (0xF0073, 0x1, 'ISC', 'Input switch control register'),
    ]

    for (address, size, name, comment) in SFR2:
        flags = ida.get_flags_by_size(size)
        ida.create_data(address, flags, size, BADNODE)
        ida.set_name(address, name, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.set_cmt(address, comment, False)

    # 0xF0800 - 0xF1000
    print('# Creating Bootloader RAM')
    segment(f, 0xF0800, 0xF1000, 'BRAM')

    # 0xF1000 - 0xF3000
    print('# Creating Data Flash Memory')
    segment(f, 0xF1000, 0xF3000, 'EEPROM')

    # 0xF3000 - 0xF9F00
    print('# Creating Mirror')
    segment(f, 0xF3000, 0xF9F00, 'MIRROR', 'CODE', SEGPERM_READ | SEGPERM_EXEC)

    # 0xF9F00 - 0xFFEE0
    print('# Creating RAM')
    segment(f, 0xF9F00, 0xFFEE0, 'RAM')

    # 0xFFEE0 - 0xFFF00
    print('# Creating General-purpose Registers')
    segment(f, 0xFFEE0, 0xFFF00, 'GPR')

    GPR = ['X', 'A', 'C', 'B', 'E', 'D', 'L', 'H']
    address = 0xFFEE0

    for gpr in xrange(0x4):
        for entry in GPR:
            ida.create_data(address, FF_BYTE, 0x1, BADNODE)
            ida.set_name(address, 'RB%i%s' % (gpr, entry),
                         SN_NOCHECK | SN_NOWARN | SN_FORCE)
            address += 1

    # 0xFFF00 - 0xFFFFF
    print('# Creating Special Function Registers')
    segment(f, 0xFFF00, 0xFFFFF, 'SFR')

    SFR = [
        (0xFFF00, 0x1, 'P0', 'Port register 0'),
        (0xFFF01, 0x1, 'P1', 'Port register 1'),
        (0xFFF02, 0x1, 'P2', 'Port register 2'),
        (0xFFF03, 0x1, 'P3', 'Port register 3'),
        (0xFFF04, 0x1, 'P4', 'Port register 4'),
        (0xFFF05, 0x1, 'P5', 'Port register 5'),
        (0xFFF06, 0x1, 'P6', 'Port register 6'),
        (0xFFF07, 0x1, 'P7', 'Port register 7'),
        (0xFFF08, 0x1, 'P8', 'Port register 8'),
        (0xFFF09, 0x1, 'P9', 'Port register 9'),
        (0xFFF0A, 0x1, 'P10', 'Port register 10'),
        (0xFFF0B, 0x1, 'P11', 'Port register 11'),
        (0xFFF0C, 0x1, 'P12', 'Port register 12'),
        (0xFFF0D, 0x1, 'P13', 'Port register 13'),
        (0xFFF0E, 0x1, 'P14', 'Port register 14'),
        (0xFFF0F, 0x1, 'P15', 'Port register 15'),
        (0xFFF10, 0x2, 'SDR00', 'Serial data register 00'),
        (0xFFF12, 0x2, 'SDR01', 'Serial data register 01'),
        (0xFFF14, 0x2, 'SDR12', 'Serial data register 12'),
        (0xFFF16, 0x2, 'SDR13', 'Serial data register 13'),
        (0xFFF18, 0x2, 'TDR00', 'Timer data register 00'),
        (0xFFF1A, 0x2, 'TDR01', 'Timer data register 01'),
        (0xFFF1E, 0x2, 'ADCR', '10-bit A/D conversion result register'),
        (0xFFF20, 0x1, 'PM0', 'Port mode register 0'),
        (0xFFF21, 0x1, 'PM1', 'Port mode register 1'),
        (0xFFF22, 0x1, 'PM2', 'Port mode register 2'),
        (0xFFF23, 0x1, 'PM3', 'Port mode register 3'),
        (0xFFF24, 0x1, 'PM4', 'Port mode register 4'),
        (0xFFF25, 0x1, 'PM5', 'Port mode register 5'),
        (0xFFF26, 0x1, 'PM6', 'Port mode register 6'),
        (0xFFF27, 0x1, 'PM7', 'Port mode register 7'),
        (0xFFF28, 0x1, 'PM8', 'Port mode register 8'),
        (0xFFF29, 0x1, 'PM9', 'Port mode register 9'),
        (0xFFF2A, 0x1, 'PM10', 'Port mode register 10'),
        (0xFFF2B, 0x1, 'PM11', 'Port mode register 11'),
        (0xFFF2C, 0x1, 'PM12', 'Port mode register 12'),
        (0xFFF2E, 0x1, 'PM14', 'Port mode register 14'),
        (0xFFF2F, 0x1, 'PM15', 'Port mode register 15'),
        (0xFFF30, 0x1, 'ADM0', 'A/D converter mode register 0'),
        (0xFFF31, 0x1, 'ADS', 'Analog input channel specification register'),
        (0xFFF32, 0x1, 'ADM1', 'A/D converter mode register 1'),
        (0xFFF37, 0x1, 'KRM', 'Key return mode register'),
        (0xFFF38, 0x1, 'EGP0',
         'External interrupt rising edge enable register 0'),
        (0xFFF39, 0x1, 'EGN0',
         'External interrupt falling edge enable register 0'),
        (0xFFF3A, 0x1, 'EGP1',
         'External interrupt rising edge enable register 1'),
        (0xFFF3B, 0x1, 'EGN1',
         'External interrupt falling edge enable register 1'),
        (0xFFF44, 0x2, 'SDR02', 'Serial data register 02'),
        (0xFFF46, 0x2, 'SDR03', 'Serial data register 03'),
        (0xFFF48, 0x2, 'SDR10', 'Serial data register 10'),
        (0xFFF4A, 0x2, 'SDR11', 'Serial data register 11'),
        (0xFFF50, 0x1, 'IICA0', 'IICA shift register 0'),
        (0xFFF51, 0x1, 'IICS0', 'IICA status register 0'),
        (0xFFF52, 0x1, 'IICF0', 'IICA flag register 0'),
        (0xFFF54, 0x1, 'IICA1', 'IICA shift register 1'),
        (0xFFF55, 0x1, 'IICS1', 'IICA status register 1'),
        (0xFFF56, 0x1, 'IICF1', 'IICA flag register 1'),
        (0xFFF64, 0x2, 'TDR02', 'Timer data register 02'),
        (0xFFF66, 0x2, 'TDR03', 'Timer data register 03'),
        (0xFFF68, 0x2, 'TDR04', 'Timer data register 04'),
        (0xFFF6A, 0x2, 'TDR05', 'Timer data register 05'),
        (0xFFF6C, 0x2, 'TDR06', 'Timer data register 06'),
        (0xFFF6E, 0x2, 'TDR07', 'Timer data register 07'),
        (0xFFF70, 0x2, 'TDR10', 'Timer data register 10'),
        (0xFFF72, 0x2, 'TDR11', 'Timer data register 11'),
        (0xFFF74, 0x2, 'TDR12', 'Timer data register 12'),
        (0xFFF76, 0x2, 'TDR13', 'Timer data register 13'),
        (0xFFF78, 0x2, 'TDR14', 'Timer data register 14'),
        (0xFFF7A, 0x2, 'TDR15', 'Timer data register 15'),
        (0xFFF7C, 0x2, 'TDR16', 'Timer data register 16'),
        (0xFFF7E, 0x2, 'TDR17', 'Timer data register 17'),
        (0xFFF90, 0x2, 'ITMC', 'Interval timer control register'),
        (0xFFF92, 0x1, 'SEC', 'Second count register'),
        (0xFFF93, 0x1, 'MIN', 'Minute count register'),
        (0xFFF94, 0x1, 'HOUR', 'Hour count register'),
        (0xFFF95, 0x1, 'WEEK', 'Week count register'),
        (0xFFF96, 0x1, 'DAY', 'Day count register'),
        (0xFFF97, 0x1, 'MONTH', 'Month count register'),
        (0xFFF98, 0x1, 'YEAR', 'Year count register'),
        (0xFFF99, 0x1, 'SUBCUD', 'Watch error correction register'),
        (0xFFF9A, 0x1, 'ALARMWM', 'Alarm minute register'),
        (0xFFF9B, 0x1, 'ALARMWH', 'Alarm hour register'),
        (0xFFF9C, 0x1, 'ALARMWW', 'Alarm week register'),
        (0xFFF9D, 0x1, 'RTCC0', 'Real-time clock control register 0'),
        (0xFFF9E, 0x1, 'RTCC1', 'Real-time clock control register 1'),
        (0xFFFA0, 0x1, 'CMC', 'Clock operation mode control register'),
        (0xFFFA1, 0x1, 'CSC', 'Clock operation status control register'),
        (0xFFFA2, 0x1, 'OSTC',
         'Oscillation stabilization time counter status register'),
        (0xFFFA3, 0x1, 'OSTS',
         'Oscillation stabilization time select register'),
        (0xFFFA4, 0x1, 'CKC', 'System clock control register'),
        (0xFFFA5, 0x1, 'CKS0', 'Clock output select register 0'),
        (0xFFFA6, 0x1, 'CKS1', 'Clock output select register 1'),
        (0xFFFA8, 0x1, 'RESF', 'Reset control flag register'),
        (0xFFFA9, 0x1, 'LVIM', 'Voltage detection register'),
        (0xFFFAA, 0x1, 'LVIS', 'Voltage detection level register'),
        (0xFFFAB, 0x1, 'WDTE', 'Watchdog timer enable register'),
        (0xFFFAC, 0x1, 'CRCIN', 'CRC input register'),
        (0xFFFB0, 0x1, 'DSA0', 'DMA SFR address register 0'),
        (0xFFFB1, 0x1, 'DSA1', 'DMA SFR address register 1'),
        (0xFFFB2, 0x2, 'DRA0', 'DMA RAM address register 0'),
        (0xFFFB4, 0x2, 'DRA1', 'DMA RAM address register 1'),
        (0xFFFB6, 0x2, 'DBC0', 'DMA byte count register 0'),
        (0xFFFB8, 0x2, 'DBC1', 'DMA byte count register 1'),
        (0xFFFBA, 0x1, 'DMC0', 'DMA mode control register 0'),
        (0xFFFBB, 0x1, 'DMC1', 'DMA mode control register 1'),
        (0xFFFBC, 0x1, 'DRC0', 'DMA operation control register 0'),
        (0xFFFBD, 0x1, 'DRC1', 'DMA operation control register 1'),
        (0xFFFD0, 0x2, 'IF2', 'Interrupt request flag register 2'),
        (0xFFFD2, 0x2, 'IF3', 'Interrupt request flag register 3'),
        (0xFFFD4, 0x2, 'MK2', 'Interrupt mask flag register 2'),
        (0xFFFD6, 0x2, 'MK3', 'Interrupt mask flag register 3'),
        (0xFFFD8, 0x2, 'PR02', 'Priority specification flag register 02'),
        (0xFFFDA, 0x2, 'PR03', 'Priority specification flag register 03'),
        (0xFFFDC, 0x2, 'PR12', 'Priority specification flag register 12'),
        (0xFFFDE, 0x2, 'PR13', 'Priority specification flag register 13'),
        (0xFFFE0, 0x2, 'IF0', 'Interrupt request flag register 0'),
        (0xFFFE2, 0x2, 'IF1', 'Interrupt request flag register 1'),
        (0xFFFE4, 0x2, 'MK0', 'Interrupt mask flag register 0'),
        (0xFFFE6, 0x2, 'MK1', 'Interrupt mask flag register 1'),
        (0xFFFE8, 0x2, 'PR00', 'Priority specification flag register 00'),
        (0xFFFEA, 0x2, 'PR01', 'Priority specification flag register 01'),
        (0xFFFEC, 0x2, 'PR10', 'Priority specification flag register 10'),
        (0xFFFEE, 0x2, 'PR11', 'Priority specification flag register 11'),
        (0xFFFF0, 0x2, 'MDAL', 'Multiplication/division data register A (L)'),
        (0xFFFF2, 0x2, 'MDAH', 'Multiplication/division data register A (H)'),
        (0xFFFF4, 0x2, 'MDBH', 'Multiplication/division data register B (H)'),
        (0xFFFF6, 0x2, 'MDBL', 'Multiplication/division data register B (L)'),
        (0xFFFFE, 0x1, 'PMC', 'Processor mode control register'),
    ]

    for (address, size, name, comment) in SFR:
        flags = ida.get_flags_by_size(size)
        ida.create_data(address, flags, size, BADNODE)
        ida.set_name(address, name, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.set_cmt(address, comment, False)

    # --------------------------------------------------------------------------------------------------------
    # Common

    pa1 = ida.get_segm_by_name('PA1')
    bfa = ida.get_segm_by_name('BFA')
    mirror = ida.get_segm_by_name('MIRROR')

    # --------------------------------------------------------------------------------------------------------
    # sc_cmd_entry - Find Command Table

    COMMANDS = {
        0x05: 'Get_Hardware_Info',
        0xD2: 'SNVS_Read_Write',
        0x1082: 'NVS_Read',
    }

    entry = idc.add_struc(BADADDR, 'sc_cmd_entry', False)
    idc.add_struc_member(entry, 'cmd', 0x0, 0x10000400, BADADDR, 0x2)
    idc.add_struc_member(entry, 'flag', 0x2, 0x10000400, BADADDR, 0x2)
    idc.add_struc_member(entry, 'func', 0x4, 0x20500400, 0x0, 0x4, BADADDR,
                         0x0, 0x2)

    # --------------------------------------------------------------------------------------------------------
    # PA1 sc_cmd_entry
    # USS1001 - 0x26BE
    # USS1002 - 0x3096

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              '00 00 00 00 ?? ?? 03 00 01 00', 0x10,
                              SEARCH_DOWN)
    #print('address: 0x%X' % address)

    while True:
        command = ida.get_word(address)
        flags = ida.get_word(address + 0x2)
        function = ida.get_dword(address + 0x4)

        command = COMMANDS.get(command,
                               'cmd_0x%X_flags_0x%X' % (command, flags))
        ida.set_name(function, command, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_struct(address, 0x8, entry)
        if ida.get_word(address) == 0x2085:
            break
        address += 0x8

    # --------------------------------------------------------------------------------------------------------
    # Mirror sc_cmd_entry
    # USS1001 - None
    # USS1002 - 0xF3096

    address = ida.find_binary(mirror.start_ea, mirror.end_ea,
                              '00 00 00 00 ?? ?? 03 00 01 00', 0x10,
                              SEARCH_DOWN)
    #print('address: 0x%X' % address)

    if address != BADADDR:
        while True:
            ida.create_struct(address, 0x8, entry)
            if ida.get_word(address) == 0x2085:
                break
            address += 0x8

    # --------------------------------------------------------------------------------------------------------
    # sc_ext_cmd_entry - Find External Command Table

    entry = idc.add_struc(BADADDR, 'sc_ext_cmd_entry', False)
    idc.add_struc_member(entry, 'id', 0x0, 0x10000400, BADADDR, 0x2)
    idc.add_struc_member(entry, 'func', 0x2, 0x20500400, 0x0, 0x4, BADADDR,
                         0x0, 0x2)
    idc.add_struc_member(entry, 'flags', 0x6, 0x10000400, BADADDR, 0x2)

    # --------------------------------------------------------------------------------------------------------
    # PA1 sc_ext_cmd_entry
    # USS1001 - 0x2D02
    # USS1002 - 0x3922

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              '00 01 ?? ?? 00 00 00 00 01 01', 0x10,
                              SEARCH_DOWN)
    #print('address: 0x%X' % address)

    while True:
        command = ida.get_word(address)
        function = ida.get_dword(address + 0x2)
        flags = ida.get_word(address + 0x6)

        ida.set_name(function, 'ext_cmd_0x%X_flags_0x%X' % (command, flags),
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_struct(address, 0x8, entry)
        if ida.get_word(address) == 0x301:
            break
        address += 0x8

    # -------------------------------------------------------------------------------------------------------
    # Mirror sc_ext_cmd_entry
    # USS1001 - None
    # USS1002 - 0xF3922

    address = ida.find_binary(mirror.start_ea, mirror.end_ea,
                              '00 01 ?? ?? 00 00 00 00 01 01', 0x10,
                              SEARCH_DOWN)
    #print('address: 0x%X' % address)

    if address != BADADDR:
        while True:
            ida.create_struct(address, 0x8, entry)
            if ida.get_word(address) == 0x301:
                break
            address += 0x8

    # --------------------------------------------------------------------------------------------------------
    # sc_ext_cmd_entry - Find External Command Table 2
    # USS1001 - 0xF99C
    # USS1002 - 0x10424

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              '97 D5 00 01 ?? ?? 01 00 00 00 01 01', 0x10,
                              SEARCH_DOWN) + 0x2
    #print('address: 0x%X' % address)

    while True:
        command = ida.get_word(address)
        function = ida.get_dword(address + 0x2)
        flags = ida.get_word(address + 0x6)

        if flags == 0x161:
            break
        ida.set_name(function, 'ext_cmd_0x%X_flags_0x%X' % (command, flags),
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_struct(address, 0x8, entry)
        address += 0x8

    # --------------------------------------------------------------------------------------------------------
    # sc_ext_cmd_entry - Find External Command Table 3
    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              '00 00 ?? ?? 01 00 00 00 01 00', 0x10,
                              SEARCH_DOWN)
    # USS1001 - 0xF49E
    # USS1001 - 0xF60E
    # USS1002 - 0x1000E
    # USS1002 - 0x1019E

    if address != BADADDR:
        while True:
            command = ida.get_word(address)
            function = ida.get_dword(address + 0x2)
            flags = ida.get_word(address + 0x6)

            if command == 0x5224 or flags == 0x181:
                break
            ida.set_name(function,
                         'ext_cmd_0x%X_flags_0x%X' % (command, flags),
                         SN_NOCHECK | SN_NOWARN | SN_FORCE)
            ida.create_struct(address, 0x8, entry)
            address += 0x8

    # --------------------------------------------------------------------------------------------------------
    # renesas_cmd_entry - Find Renesas Command Table

    COMMANDS = {
        0x00: 'Reset',
        0x13: 'Verify',
        0x14: 'OCD_Related',
        0x20: 'Chip_Erase',
        0x22: 'Block_Erase',
        0x32: 'Block_Blank_Check',
        0x40: 'Programming',
        0x9A: 'Baud_Rate_Set',
        0xA0: 'Security_Set',
        0xA1: 'Security_Get',
        0xA2: 'Security_Release',
        0xB0: 'Checksum',
        0xC0: 'Silicon_Signature',
        0xC5: 'Version_Get',
    }

    entry = idc.add_struc(BADADDR, 'renesas_cmd_entry', False)
    idc.add_struc_member(entry, 'version', 0x0, 0x10000400, BADADDR, 0x2)
    idc.add_struc_member(entry, 'ext_function_address', 0x2, 0x10000400,
                         BADADDR, 0x32)
    idc.add_struc_member(entry, 'ext_function_code', 0x34, 0x400, BADADDR, 0xC)
    idc.add_struc_member(entry, 'unknown', 0x40, 0x400, BADADDR, 0x20)
    idc.add_struc_member(entry, 'int_function_address', 0x60, 0x10000400,
                         BADADDR, 0x10)
    idc.add_struc_member(entry, 'int_function_code', 0x70, 0x400, BADADDR, 0x8)
    idc.add_struc_member(entry, 'unknown2', 0x78, 0x400, BADADDR, 0x1A)

    address = ida.find_binary(bfa.start_ea, bfa.end_ea, '03 03', 0x10,
                              SEARCH_DOWN) + 0x2
    #print('0x%X' % address)

    ida.create_struct(address - 0x2, 0x92, entry)

    # --------------------------------------------------------------------------------------------------------
    # External Functions

    ext_functions = []
    while ida.get_word(address) != 0x1300:
        ext_function = ida.get_word(address) + 0xE0000
        #print('ext_function: 0x%X' % ext_function)

        ida.create_insn(ext_function)
        if ida.print_insn_mnem(ext_function) != 'nop':
            ida.add_func(ext_function, BADADDR)
        '''
        print(ida.print_insn_mnem(ext_function + 0x3))
        if ida.print_insn_mnem(ext_function + 0x3) == 'br':
            ida.add_func(ext_function, ext_function + 0x5)
        else:
            ida.add_func(ext_function, BADADDR)
        '''

        ext_functions.append(ext_function)

        address += 2

    # --------------------------------------------------------------------------------------------------------
    # External Commands

    while ida.get_byte(address) != 0x3:
        command = ida.get_byte(address)
        #print('ext_function: 0x%X' % ext_functions[0])

        command = COMMANDS.get(command, 'renesas_ext_cmd_0x%X' % command)
        ida.set_name(ext_functions[0], command,
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)

        ext_functions.pop(0)

        address += 0x1

    address += 0x20
    #print('int_function_start: 0x%X' % address)

    # --------------------------------------------------------------------------------------------------------
    # Internal Functions

    int_functions = []
    while ida.get_word(address) != 0xCD0E:
        int_function = ida.get_word(address) + 0xE0000
        #print('int_function: 0x%X' % int_function)

        ida.create_insn(int_function)
        if ida.print_insn_mnem(int_function) != 'nop':
            ida.add_func(int_function, BADADDR)

        int_functions.append(int_function)

        address += 2

    # --------------------------------------------------------------------------------------------------------
    # Internal Commands

    while ida.get_byte(address) != 0x87:
        command = ida.get_byte(address)
        #print('int_function: 0x%X' % int_functions[0])

        command = COMMANDS.get(command, 'renesas_int_cmd_0x%X' % command)
        ida.set_name(int_functions[0], command,
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)

        int_functions.pop(0)

        address += 0x1

    # --------------------------------------------------------------------------------------------------------
    # Signature Data

    entry = idc.add_struc(BADADDR, 'signature_data', False)
    idc.add_struc_member(entry, 'device_code', 0x0, 0x400, BADADDR, 0x3)
    idc.add_struc_member(entry, 'device_name', 0x3, 0x5000c400, 0, 0xA)
    idc.add_struc_member(entry, 'code_flash_mem_area_last_address', 0xD,
                         0x9400, BADADDR, 0x3)
    idc.add_struc_member(entry, 'data_flash_mem_area_last_address', 0x10,
                         0x400, BADADDR, 0x3)
    idc.add_struc_member(entry, 'firmware_version', 0x13, 0x400, BADADDR, 0x3)

    address = ida.find_binary(bfa.start_ea, bfa.end_ea, '10 00 06', 0x10,
                              SEARCH_DOWN)
    #print('address: 0x%X' % address)

    ida.create_struct(address, 0x16, entry)

    # --------------------------------------------------------------------------------------------------------
    # SP1 Command Keys

    KEYS = [
        'SharedData_B',
        'SharedKey_B_A',
        'SharedKey_B_B',
        'SharedData_F_A',
        'SharedData_F_B',
        'SharedKey_F_A',
        'SharedKey_F_B',
        'SharedKey_F_C',
    ]

    entry = idc.add_struc(BADADDR, 'key', False)
    idc.add_struc_member(entry, 'key', 0, 0x400, BADADDR, 0x10)

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              'CF 2E 93 E9 F9 4E 28 CC', 0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    size = len(KEYS) * 0x10
    ida.del_items(address, 0, size)

    for key in KEYS:
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # SP1 Command Keys 2

    address = ida.find_binary(address, pa1.end_ea, 'CF 2E 93 E9 F9 4E 28 CC',
                              0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    if address != BADADDR:
        ida.del_items(address, 0, size)

        for key in KEYS:
            ida.create_data(address, FF_BYTE, 0x10, BADNODE)
            ida.create_struct(address, 0x10, entry)
            ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # SP1 Unknown Command Keys

    KEYS = [
        'SharedData_0',
        'SharedKey_0_A',
        'SharedKey_0_B',
        'SharedData_1',
        'SharedKey_1_A',
        'SharedKey_1_B',
        'SharedData_E',
        'SharedKey_E_A',
        'SharedKey_E_B',
    ]

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              '80 99 6F BB C8 B4 EB A3', 0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    size = len(KEYS) * 0x10
    ida.del_items(address, 0, size)

    for key in KEYS:
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        address += 0x10

    #print('address: 0x%X' % address)

    # --------------------------------------------------------------------------------------------------------
    # SP1 Unknown Command Keys 2

    set2 = ida.find_binary(address, pa1.end_ea, '80 99 6F BB C8 B4 EB A3',
                           0x10, SEARCH_DOWN)
    print('address: 0x%X' % set2)

    if set2 != BADADDR:
        ida.del_items(set2, 0, size)

        for key in KEYS:
            ida.create_data(set2, FF_BYTE, 0x10, BADNODE)
            ida.create_struct(set2, 0x10, entry)
            ida.set_name(set2, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            set2 += 0x10

    # --------------------------------------------------------------------------------------------------------
    # SP1 g_debug_challenge_key

    ida.del_items(address, 0, 0x20)
    ida.create_data(address, FF_BYTE, 0x20, BADNODE)
    ida.set_name(address, 'g_debug_challenge_key',
                 SN_NOCHECK | SN_NOWARN | SN_FORCE)
    address += 0x20

    # --------------------------------------------------------------------------------------------------------
    # SP1 g_debug_challenge_key 2

    set2 = ida.find_binary(address, pa1.end_ea, 'F4 77 16 E6 C5 64 9F D6',
                           0x10, SEARCH_DOWN)

    if set2 != BADADDR:
        ida.del_items(set2, 0, 0x20)
        ida.create_data(set2, FF_BYTE, 0x20, BADNODE)
        ida.set_name(set2, 'g_debug_challenge_key_0',
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)
        set2 += 0x20

    # --------------------------------------------------------------------------------------------------------
    # SP1 jigkick_expansion

    KEYS = [
        'jigkick_expansion_0',
        'jigkick_expansion_1',
        'jigkick_expansion_2',
        'jigkick_expansion_3',
        'jigkick_expansion_4',
        'jigkick_expansion_5',
        'jigkick_expansion_6',
        'jigkick_expansion_7',
        'jigkick_expansion_8',
        'jigkick_expansion_9',
        'jigkick_expansion_A',
        'jigkick_expansion_B',
        'jigkick_expansion_C',
    ]

    size = len(KEYS) * 0x10
    ida.del_items(address, 0, size)

    for key in KEYS:
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # SP1 jigkick_expansion 2

    if set2 != BADADDR:
        ida.del_items(set2, 0, size)

        for key in KEYS:
            ida.create_data(set2, FF_BYTE, 0x10, BADNODE)
            ida.create_struct(set2, 0x10, entry)
            ida.set_name(set2, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            set2 += 0x10

    # --------------------------------------------------------------------------------------------------------
    # SP1 Unknown Shared Keys

    KEYS = [
        'SharedKey_0',
        'SharedKey_1',
        'SharedKey_E',
    ]

    address = ida.find_binary(pa1.start_ea, pa1.end_ea, '55 55 55 00', 0x10,
                              SEARCH_DOWN) + 0x4
    #print('address: 0x%X' % address)

    size = len(KEYS) * 0xE
    ida.del_items(address, 0, size)

    for count, key in enumerate(KEYS):
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)
        ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)

        address += 0xE

    ida.del_items(address, 0, size)

    for count, key in enumerate(KEYS):
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)
        ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)

        address += 0xE

    # --------------------------------------------------------------------------------------------------------
    # SP1 Shared Keys

    KEYS = [
        'SharedKey_B',
        'SharedKey_F',
    ]

    extra = len(KEYS) * 0x16
    ida.del_items(address, 0, extra)

    for count, key in enumerate(KEYS):
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)
        ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0xE, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0x12, FF_DWORD, 0x4, BADNODE)

        address += 0x16

    ida.del_items(address, 0, size)

    for count, key in enumerate(KEYS):
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        ida.create_data(address, FF_WORD, 0x2, BADNODE)
        ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
        ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)

        address += 0xE

    # --------------------------------------------------------------------------------------------------------
    # SP1 MISC Keys/Data

    KEYS = [
        'AES_KEY',
        'AES_IV',
        'XOR_KEY',
    ]

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              'DB D9 45 0A CC A8 54 48', 0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    size = len(KEYS) * 0x10
    ida.del_items(address, 0, size)

    for key in KEYS:
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # PA1 SERVICE_0x900_DATA

    address = ida.find_binary(pa1.start_ea, pa1.end_ea,
                              '93 CE 8E BE DF 7F 69 A9', 0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    ida.del_items(address, 0, 0x10)
    ida.create_data(address, FF_BYTE, 0x10, BADNODE)
    ida.create_struct(address, 0x10, entry)
    ida.set_name(address, 'SERVICE_0x900_DATA',
                 SN_NOCHECK | SN_NOWARN | SN_FORCE)
    address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # PA1 SERVICE_0x900_DATA 2

    address = ida.find_binary(address, pa1.end_ea, '93 CE 8E BE DF 7F 69 A9',
                              0x10, SEARCH_DOWN)
    #print('key address: 0x%X' % address)

    ida.del_items(address, 0, 0x10)
    ida.create_data(address, FF_BYTE, 0x10, BADNODE)
    ida.create_struct(address, 0x10, entry)
    ida.set_name(address, 'SERVICE_0x900_DATA',
                 SN_NOCHECK | SN_NOWARN | SN_FORCE)

    # --------------------------------------------------------------------------------------------------------
    # Mirror Command Keys

    KEYS = [
        '_SharedData_B',
        '_SharedKey_B_A',
        '_SharedKey_B_B',
        '_SharedData_F_A',
        '_SharedData_F_B',
        '_SharedKey_F_A',
        '_SharedKey_F_B',
        '_SharedKey_F_C',
    ]

    address = ida.find_binary(mirror.start_ea, mirror.end_ea,
                              'CF 2E 93 E9 F9 4E 28 CC', 0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    if address != BADADDR:

        size = len(KEYS) * 0x10
        ida.del_items(address, 0, size)

        for key in KEYS:
            ida.create_data(address, FF_BYTE, 0x10, BADNODE)
            ida.create_struct(address, 0x10, entry)
            ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # Mirror Unknown Command Keys

    KEYS = [
        '_SharedData_0',
        '_SharedKey_0_A',
        '_SharedKey_0_B',
        '_SharedData_1',
        '_SharedKey_1_A',
        '_SharedKey_1_B',
        '_SharedData_E',
        '_SharedKey_E_A',
        '_SharedKey_E_B',
    ]

    address = ida.find_binary(mirror.start_ea, mirror.end_ea,
                              '80 99 6F BB C8 B4 EB A3', 0x10, SEARCH_DOWN)

    if address == BADADDR:
        del KEYS[:6]
        address = ida.find_binary(mirror.start_ea, mirror.end_ea,
                                  'AD 2F 32 2F 42 56 C4 9D', 0x10, SEARCH_DOWN)

    #print('address: 0x%X' % address)

    size = len(KEYS) * 0x10
    ida.del_items(address, 0, size)

    for key in KEYS:
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # Mirror g_debug_challenge_key

    #print('address: 0x%X' % address)

    ida.del_items(address, 0, 0x20)
    ida.create_data(address, FF_BYTE, 0x20, BADNODE)
    ida.set_name(address, '_g_debug_challenge_key',
                 SN_NOCHECK | SN_NOWARN | SN_FORCE)
    address += 0x20

    # --------------------------------------------------------------------------------------------------------
    # Mirror jigkick_expansion

    KEYS = [
        '_jigkick_expansion_0',
        '_jigkick_expansion_1',
        '_jigkick_expansion_2',
        '_jigkick_expansion_3',
        '_jigkick_expansion_4',
        '_jigkick_expansion_5',
        '_jigkick_expansion_6',
        '_jigkick_expansion_7',
        '_jigkick_expansion_8',
        '_jigkick_expansion_9',
        '_jigkick_expansion_A',
        '_jigkick_expansion_B',
        '_jigkick_expansion_C',
    ]

    #print('address: 0x%X' % address)

    size = len(KEYS) * 0x10
    ida.del_items(address, 0, size)

    for key in KEYS:
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
        address += 0x10

    # --------------------------------------------------------------------------------------------------------
    # Mirror Unknown Shared Keys

    KEYS = [
        '_SharedKey_0',
        '_SharedKey_1',
        '_SharedKey_E',
    ]

    address = ida.find_binary(mirror.start_ea, mirror.end_ea, '55 55 55 00',
                              0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    if address != BADADDR:
        address += 0x4

        size = len(KEYS) * 0xE
        ida.del_items(address, 0, size)

        for count, key in enumerate(KEYS):
            ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            ida.create_data(address, FF_WORD, 0x2, BADNODE)
            ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)

            address += 0xE

        ida.del_items(address, 0, size)

        for count, key in enumerate(KEYS):
            ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            ida.create_data(address, FF_WORD, 0x2, BADNODE)
            ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)

            address += 0xE

        # --------------------------------------------------------------------------------------------------------
        # Mirror Shared Keys

        KEYS = [
            '_SharedKey_B',
            '_SharedKey_F',
        ]

        extra = len(KEYS) * 0x16
        ida.del_items(address, 0, extra)

        for count, key in enumerate(KEYS):
            ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            ida.create_data(address, FF_WORD, 0x2, BADNODE)
            ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0xE, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0x12, FF_DWORD, 0x4, BADNODE)

            address += 0x16

        ida.del_items(address, 0, size)

        for count, key in enumerate(KEYS):
            ida.set_name(address, key, SN_NOCHECK | SN_NOWARN | SN_FORCE)
            ida.create_data(address, FF_WORD, 0x2, BADNODE)
            ida.create_data(address + 0x2, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0x6, FF_DWORD, 0x4, BADNODE)
            ida.create_data(address + 0xA, FF_DWORD, 0x4, BADNODE)

            address += 0xE

    # --------------------------------------------------------------------------------------------------------
    # Mirror SERVICE_0x900_DATA

    address = ida.find_binary(mirror.start_ea, mirror.end_ea,
                              '93 CE 8E BE DF 7F 69 A9', 0x10, SEARCH_DOWN)
    #print('address: 0x%X' % address)

    if address != BADADDR:
        ida.del_items(address, 0, 0x10)
        ida.create_data(address, FF_BYTE, 0x10, BADNODE)
        ida.create_struct(address, 0x10, entry)
        ida.set_name(address, '_SERVICE_0x900_DATA',
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)

    # --------------------------------------------------------------------------------------------------------

    print('# Finding Additional Functions...')
    function_search(1, 'D7 61 DD')
    function_search(1, 'FF C3 31 17')
    function_search(1, 'FB C3 31 17')
    function_search(1, 'FF 61 DD 8E FA')
    function_search(1, 'FF 61 DD C7')
    function_search(0, '61 DD C7')
    function_search(1, 'D7 C7 C3 C1')
    function_search(1, 'D7 C7 16')
    function_search(1, 'D7 30 02 00 C1')
    function_search(1, 'D7 C7 C1')
    function_search(1, 'D7 C7 88')
    function_search(1, 'D7 C7 20')
    function_search(1, 'D7 C7 41')
    function_search(1, 'D7 C7 36')
    function_search(1, '00 C7 C3 C1 FB')
    function_search(1, 'FF C7 57')
    function_search(2, '00 00 C7 C5 C1')

    # --------------------------------------------------------------------------------------------------------

    print('# Done!')
    return 1


# PROGRAM END
Ejemplo n.º 11
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