示例#1
0
    def resolve_symbols(self, dll):
        tmpdir = tempfile.gettempdir().replace('\\', '/') + '/'
        # File who will first contain ordinals then symbols
        tmpfile = tmpdir + "dotNIETsymbols.txt"
        tmplog = tmpdir + "dotNIETlogs.txt"
        # Destination path for a copy of SharedLibrary.dll
        tmpdll = tmpdir + os.path.basename(dll)
        # Path to the idat binary, needed to parse a remote idb
        idat = idc.idadir().replace('\\','/') + '/' + 'idat' + \
               ['64' if utils.is_x64(dll) else ''][0]

        if os.getenv("windir") is not None:
            idat += '.exe'
        # script called along with idat in order to parse SharedLibrary.idb
        parsing_script_path = '"' + os.path.dirname(os.path.realpath(__file__)).replace('\\','/')\
                              + '/dotNIET/resolve.py"'

        # we first copy SharedLibrary.dll to tmp to be sure we are in a
        # writable location
        shutil.copyfile(dll, tmpdll)

        # we have to use temporary files because of the ida headless stuff...
        # pretty dirty
        ordinals = []
        with open(tmpfile, 'w') as f:
            for i in range(self.nb_symbols):
                ordinals.append((idaapi.get_qword(self.ordinals + i * 8)
                                 & ~0x8000000000000000) * 4)
            f.write(",".join([str(x) for x in ordinals]))

        # be prepared to wait as this will load the binary + pdb
        idaapi.msg("Starting parsing of %d symbols...\n" % self.nb_symbols)
        subprocess.run([idat, "-L" + tmplog, "-c", "-A", "-S" + \
                        parsing_script_path + " " + tmpfile, tmpdll],
                        creationflags=subprocess.CREATE_NO_WINDOW,
                        check=True)

        # we read back tmpfile which now contains symbols
        symbols = []
        with open(tmpfile, 'r') as f:
            symbolsArray = f.read()
            symbols = symbolsArray.split(',')

        # we first have to undef structure as it is an array and ida will
        # refuse to set names within it
        idc.del_items(self.ordinals)
        idc.set_cmt(self.ordinals - 8, "Custom imports from SharedLibrary.dll",
                    0)
        # we then apply the symbols at this very same location (start of .idata)
        for i in range(self.nb_symbols):
            idc.set_name(self.ordinals + i * 8, symbols[i],
                         SN_NOCHECK | SN_FORCE | SN_NODUMMY)

        # finally we remove our temp files
        os.remove(tmpfile)
        os.remove(tmpdll)
        # ida generate a db
        os.remove(tmpdll + '.i64')
        # if everything went smoothly, we should not need this anymore
        os.remove(tmplog)
def load_nids(directory, library):

    try:
        path = '%s/%s/%s' % (idc.idadir(), directory, library)

        with open(path) as database:
            if library == AEROLIB:
                NIDS = dict(row for row in csv.reader(database, delimiter=' '))
            else:
                NIDS = [row.strip() for row in database]

    except IOError:
        retry = idaapi.ask_file(0, '%s|*.csv|All files (*.*)|*.*',
                                'Please gimme your %s file' % (library))

        if retry != None:
            try:
                with open(retry) as database:
                    if library == AEROLIB:
                        NIDS = dict(
                            row for row in csv.reader(database, delimiter=' '))
                    else:
                        NIDS = [row.strip() for row in database]
                        shutil.copy2(retry, path)
            except:
                print('Ok, no NIDs for you!')
        else:
            print('Ok, no NIDs for you!')

    return NIDS
示例#3
0
 def __init__(self, wrapper, utilsJar, config_file):
     self.packageName = None
     self.launchActivity = None
     self.android_server = None
     self.device = None
     self.adb = wrapper
     self.utilsJar = utilsJar
     self.config_file = config_file
     if hasattr(idc, "idadir"):
         # ida 7.0
         self.bindir = os.path.abspath(idc.idadir() + "/dbgsrv")
     else:
         import idaapi
         self.bindir = os.path.abspath(idaapi.get_idcpath() + "/../dbgsrv")
def save_nids(directory, library, NIDS):

    try:
        path = '%s/%s/%s' % (idc.idadir(), directory, library)
        mode = 'a' if library == AEROLIB else 'w'

        with open(path, mode) as database:
            if library == AEROLIB:
                for nid, name in sorted(NIDS.items(), key=lambda x: x[1]):
                    database.write('%s %s\n' % (nid, name))
            else:
                for nid in NIDS:
                    database.write('%s\n' % nid)
    except:
        idc.error('Error saving the %s :(' % library)
示例#5
0
def find_pdb(dll_path):
    # we first check if the pdb is available
    symbol_paths = []
    cfg_known_locations = [
        ida_diskio.get_user_idadir() + "/cfg/pdb.cfg",
        idc.idadir() + "/cfg/pdb.cfg"
    ]

    for cfg in cfg_known_locations:
        if os.path.exists(cfg):
            symbol_paths = _parse_cfg_file(cfg)
            # ida first check IDAUSR dir and if ok ignore IDADIR cfg
            if symbol_paths is not None and len(symbol_paths):
                break

    nt_symbol_path_env = os.getenv("_NT_SYMBOL_PATH")
    # assume Windows + it overrides values of ida cfg file
    if nt_symbol_path_env is not None and nt_symbol_path_env != "":
        symbol_paths = _parse_symbol_path(os.getenv("_NT_SYMBOL_PATH"))

    if symbol_paths is None or not len(symbol_paths):
        idaapi.msg("Error: \'_NT_SYMBOL_PATH\' could not be found. One must" +\
                    " set for .NIET to work.\n")
        return False
    else:
        # we then compute pdb guid of SharedLibrary.dll
        pdbguid = pdbg.get_guid(dll_path)
        if pdbguid is None:
            return False
        # we can have multiple paths, we check all of them
        for paths in symbol_paths:
            pdb_path = paths.replace('\\','/') + "/SharedLibrary.pdb/" + \
                       pdbguid + "/SharedLibrary.pdb"
            if not os.path.exists(pdb_path):
                idaapi.msg("Error: %s could not be found\n" % pdb_path)
                return False
            else:
                return True
示例#6
0
def load_file(f, neflags, format):

    print('# PS4 Module Loader')
    ps = Binary(f)

    # PS4 Processor, Compiler, Library
    bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL,
                         'gnulnx_x64')

    # Load Aerolib...
    nids = load_nids(idc.idadir() + '/loaders/aerolib.csv')

    # Segment Loading...
    for segm in ps.E_SEGMENTS:

        # Process Loadable Segments...
        if segm.name() in [
                'CODE', 'DATA', 'SCE_RELRO', 'DYNAMIC', 'GNU_EH_FRAME',
                'SCE_DYNLIBDATA'
        ]:

            address = segm.MEM_ADDR if segm.name() not in [
                'DYNAMIC', 'SCE_DYNLIBDATA'
            ] else segm.OFFSET + 0x1000000
            size = segm.MEM_SIZE if segm.name() not in [
                'DYNAMIC', 'SCE_DYNLIBDATA'
            ] else segm.FILE_SIZE

            print('# Processing %s Segment...' % segm.name())
            f.file2base(segm.OFFSET, address, address + segm.FILE_SIZE,
                        FILEREG_PATCHABLE)

            if segm.name() not in ['DYNAMIC', 'GNU_EH_FRAME']:

                idaapi.add_segm(0, address, address + size, segm.name(),
                                segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP)

                # Processor Specific Segment Details
                idc.set_segm_addressing(address, bitness)
                idc.set_segm_alignment(address, segm.alignment())
                idc.set_segm_attr(address, SEGATTR_PERM, segm.flags())

            # Process Dynamic Segment....
            elif segm.name() == 'DYNAMIC':

                stubs = {}
                modules = {}
                libraries = {}
                f.seek(segm.OFFSET)

                offset = segm.OFFSET
                dynamic = address
                dynamicsize = size

                for entry in xrange(size / 0x10):
                    idc.set_cmt(address + (entry * 0x10),
                                Dynamic(f).process(stubs, modules, libraries),
                                False)
            '''
            # Process Exception Handling Segment...
            elif segm.name() == 'GNU_EH_FRAME':
                
                # Exception Handling Frame Header Structure
                members = [('version', 'Version', 0x1),
                           ('eh_frame_ptr_enc', 'Encoding of Exception Handling Frame Pointer', 0x1),
                           ('fde_count_enc', 'Encoding of Frame Description Entry Count', 0x1),
                           ('table_enc', 'Encoding of Table Entries', 0x1)]
                struct = segm.struct('EHFrame', members)
                
                idaapi.create_struct(address, 0x4, struct)
                
                # Exception Handling Structure
                members = [('exception', 'value', 0x8)]
                struct = segm.struct('Exception', members)
                
                for entry in xrange(size / 0x8):
                    idaapi.create_struct(address + (entry * 0x8), 0x8, struct)
            '''

        # Process SCE 'Special' Shared Object Segment...
        if segm.name() == 'SCE_DYNLIBDATA':

            # SCE Fingerprint
            idc.make_array(address, 0x14)
            idc.set_name(address, 'SCE_FINGERPRINT',
                         SN_NOCHECK | SN_NOWARN | SN_FORCE)
            idc.set_cmt(
                address, ' '.join(
                    x.encode('hex')
                    for x in idc.get_bytes(address, 0x14)).upper(), False)

            # Dynamic Symbol Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic Symbol Entry Structure
                members = [('name', 'Name (String Index)', 0x4),
                           ('info', 'Info (Binding : Type)', 0x1),
                           ('other', 'Other', 0x1),
                           ('shtndx', 'Section Index', 0x2),
                           ('value', 'Value', 0x8), ('size', 'Size', 0x8)]
                struct = segm.struct('Symbol', members)

                # Dynamic Symbol Table
                location = address + Dynamic.SYMTAB
                f.seek(segm.OFFSET + Dynamic.SYMTAB)
                symbols = {}

                for entry in xrange(Dynamic.SYMTABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Symbol(f).process(symbols), False)

            except:
                pass

            # Dynamic String Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic String Table
                location = address + Dynamic.STRTAB
                f.seek(segm.OFFSET + Dynamic.STRTAB)

                # Stubs
                for key in stubs:
                    idc.create_strlit(location + key, BADADDR)
                    stubs[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Stub', False)

                #print('Stubs: %s' % stubs)

                # Modules
                for key in modules:
                    idc.create_strlit(location + key, BADADDR)
                    modules[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Module', False)

                #print('Modules: %s' % modules)

                # Libraries and LIDs
                lids = {}
                for key, value in libraries.iteritems():
                    idc.create_strlit(location + key, BADADDR)
                    lids[value] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    libraries[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Library', False)

                #print('LIDs: %s' % lids)

                # Symbols
                for key in symbols:
                    idc.create_strlit(location + key, BADADDR)
                    symbols[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Symbol', False)

                #print('Symbols: %s' % symbols)

            except:
                pass

            # Resolve Export Symbols
            try:
                symbols = sorted(symbols.iteritems())
                location = address + Dynamic.SYMTAB + 0x30
                f.seek(segm.OFFSET + Dynamic.SYMTAB + 0x30)

                for entry in xrange((Dynamic.SYMTABSZ - 0x30) / 0x18):
                    Symbol(f).resolve(location + (entry * 0x18), nids,
                                      symbols[entry][1])

            except:
                pass

            # Jump Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Jump Entry Structure
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Jump', members)

                # PS4 Base64 Alphabet
                base64 = list(
                    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-'
                )
                alphabet = {
                    character: index
                    for index, character in enumerate(base64)
                }
                #print('Base64 Table: %s' % alphabet)

                # Jump Table
                location = address + Dynamic.JMPTAB
                f.seek(segm.OFFSET + Dynamic.JMPTAB)

                for entry in xrange(Dynamic.JMPTABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(
                        location + (entry * 0x18),
                        Relocation(f).resolve(alphabet, nids, symbols, lids),
                        False)

            except:
                pass

            # Relocation Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Relocation Entry Structure (with specific addends)
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Relocation', members)

                # Relocation Table (with specific addends)
                location = address + Dynamic.RELATAB
                f.seek(segm.OFFSET + Dynamic.RELATAB)

                for entry in xrange(Dynamic.RELATABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Relocation(f).process(nids, symbols), False)

            except:
                pass

            # Hash Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Hash Entry Structure
                members = [('bucket', 'Bucket', 0x2), ('chain', 'Chain', 0x2),
                           ('buckets', 'Buckets', 0x2),
                           ('chains', 'Chains', 0x2)]
                struct = segm.struct('Hash', members)

                # Hash Table
                location = address + Dynamic.HASHTAB
                f.seek(segm.OFFSET + Dynamic.HASHTAB)

                for entry in xrange(Dynamic.HASHTABSZ / 0x8):
                    idaapi.create_struct(location + (entry * 0x8), 0x8, struct)

            except:
                pass

            # Dynamic Tag Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic Tag Entry Structure
                members = [('tag', 'Tag', 0x8), ('value', 'Value', 0x8)]
                struct = segm.struct('Tag', members)

                f.seek(offset)

                for entry in xrange(dynamicsize / 0x10):
                    idaapi.create_struct(dynamic + (entry * 0x10), 0x10,
                                         struct)
                    idc.set_cmt(
                        dynamic + (entry * 0x10),
                        Dynamic(f).comment(address, stubs, modules, libraries),
                        False)

            except:
                pass

    # Start Function
    idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True)

    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()

    # Set No Return for __stack_chk_fail...
    try:
        function = idc.get_name_ea_simple('__stack_chk_fail')
        function = idaapi.get_func(function)
        function.flags |= FUNC_NORET
        idaapi.update_func(function)

    except:
        pass

    # Missed Function Creation...
    try:
        code = idaapi.get_segm_by_name('CODE')

        address = code.start_ea
        end = code.end_ea

        # Final Pass
        print('# Performing Final Pass...')
        while address < end:
            address = idaapi.find_not_func(address, SEARCH_DOWN)

            if idaapi.is_unknown(idaapi.get_flags(address)):
                idaapi.create_insn(address)
            else:
                idc.add_func(address)

            address += 4

    except:
        pass

    print('# Done!')
    return 1
示例#7
0
import os
import logging
import idc

try:
    import configparser
except ImportError:
    # for python 2
    import ConfigParser as configparser

CONFIG_FILE_PATH = os.path.join(idc.idadir(), 'cfg', 'HexRaysPyTools.cfg')

DEBUG_MESSAGE_LEVEL = logging.INFO
# Whether propagate names (Propagate name feature) through all names or only defaults like v11, a3, this, field_4
PROPAGATE_THROUGH_ALL_NAMES = False
# Store Xref information in database. I don't know how much size it consumes yet
STORE_XREFS = True
# There're some types that can be pointers to structures like int, PVOID etc and by default plugin scans only them
# Full list can be found in `Const.LEGAL_TYPES`.
# But if set this option to True than variable of every type could be possible to scan
SCAN_ANY_TYPE = False


def add_default_settings(config):
    updated = False
    if not config.has_option("DEFAULT", "DEBUG_MESSAGE_LEVEL"):
        config.set(None, 'DEBUG_MESSAGE_LEVEL', str(DEBUG_MESSAGE_LEVEL))
        updated = True
    if not config.has_option("DEFAULT", "PROPAGATE_THROUGH_ALL_NAMES"):
        config.set(None, 'PROPAGATE_THROUGH_ALL_NAMES',
                   str(PROPAGATE_THROUGH_ALL_NAMES))