예제 #1
0
def clean_non_present_modules(pid, pgd):
    from api_internal import dispatch_module_remove_callback

    mods_to_remove = []
    if pid is not None:
        if (pid, pgd) in modules:
            for base, mod in modules[(pid, pgd)].iteritems():
                if not mod.is_present():
                    mods_to_remove.append((pid, pgd, base))
    else:
        for pid, _pgd in modules.keys():
            if _pgd == pgd:
                if (pid, _pgd) in modules:
                    for base, mod in modules[(pid, _pgd)].iteritems():
                        if not mod.is_present():
                            mods_to_remove.append((pid, pgd, base))

    for pid, pgd, base in mods_to_remove:
        # Callback notification
        dispatch_module_remove_callback(
            pid, pgd, base, modules[(pid, pgd)][base].get_size(),
            modules[(pid, pgd)][base].get_name(),
            modules[(pid, pgd)][base].get_fullname())

        # Remove module
        del modules[(pid, pgd)][base]
예제 #2
0
파일: vmi.py 프로젝트: CRYP706URU/pyrebox
def clean_non_present_modules(pid, pgd):
    from api_internal import dispatch_module_remove_callback

    mods_to_remove = []
    if pid is not None:
        if (pid, pgd) in modules:
            for base, mod in modules[(pid, pgd)].iteritems():
                if not mod.is_present():
                    mods_to_remove.append((pid, pgd, base))
    else:
        for pid, _pgd in modules.keys():
            if _pgd == pgd:
                if (pid, _pgd) in modules:
                    for base, mod in modules[(pid, _pgd)].iteritems():
                        if not mod.is_present():
                            mods_to_remove.append((pid, pgd, base))

    for pid, pgd, base in mods_to_remove:
        # Callback notification
        dispatch_module_remove_callback(pid, pgd, base, 
                                        modules[(pid, pgd)][base].get_size(),
                                        modules[(pid, pgd)][base].get_name(),
                                        modules[(pid, pgd)][base].get_fullname())

        # Remove module
        del modules[(pid, pgd)][base]
예제 #3
0
def windows_insert_module_internal(p_pid, p_pgd, base, size, fullname,
                                   basename, checksum, nt_header,
                                   update_symbols):

    from utils import get_addr_space
    from vmi import modules
    from vmi import symbols
    from vmi import Module
    from vmi import PseudoLDRDATA
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback

    mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname)

    if p_pgd != 0:
        addr_space = get_addr_space(p_pgd)
    else:
        addr_space = get_addr_space()

    # First, we try to get the symbols from the cache
    if (checksum, fullname) in symbols:
        mod.set_symbols(symbols[(checksum, fullname)])

    # If we are updating symbols (a simple module retrieval would
    # not require symbol extraction), and, either we dont have any
    # symbols on the cache, or we have an empty list (symbols could
    # not be retrieved for some reason, such as a missing memory page,
    # we try symbol resolution
    if update_symbols and ((checksum, fullname) not in symbols
                           or len(symbols[(checksum, fullname)]) == 0):
        syms = {}
        export_dir = nt_header.OptionalHeader.DataDirectory[0]

        if export_dir:
            expdir = obj.Object('_IMAGE_EXPORT_DIRECTORY',
                                offset=base + export_dir.VirtualAddress,
                                vm=addr_space,
                                parent=PseudoLDRDATA(base, basename,
                                                     export_dir))
            if expdir.valid(nt_header):
                # Ordinal, Function RVA, and Name Object
                for o, f, n in expdir._exported_functions():
                    if not isinstance(o, obj.NoneObject) and \
                       not isinstance(f, obj.NoneObject) and \
                       not isinstance(n, obj.NoneObject):
                        syms[str(n)] = f.v()

                # If we managed to parse export table, update symbols,
                # no matter if it is empty
                if (checksum, fullname) not in symbols or len(syms) > len(
                        symbols[(checksum, fullname)]):
                    symbols[(checksum, fullname)] = syms
                    # Even if it is empty, the module symbols are set
                    # to an empty list, and thus are 'resolved'.
                    # Anyway, in future updates, they could be resolved,
                    # as we allow this in the first condition.
                    mod.set_symbols(symbols[(checksum, fullname)])
                    # Add module to mods_pending, or
                    # Update modules that may we might not have been
                    # able to resolve symbols in the past
                    if len(syms) == 0:
                        if (checksum, fullname) not in mods_pending:
                            mods_pending[(checksum, fullname)] = []
                        mods_pending[(checksum, fullname)].append(mod)
                    else:
                        if (checksum, fullname) in mods_pending and len(
                                mods_pending[(checksum, fullname)]) > 0:
                            for mod in mods_pending[(checksum, fullname)]:
                                mod.set_symbols(syms)
                            del mods_pending[(checksum, fullname)]

        else:
            # Since there is no export dir, we assume that it does
            # not have any symbols
            if (checksum, fullname) not in symbols:
                symbols[(checksum, fullname)] = []
                # Even if it is empty, the module symbols are set
                # to an empty list, and thus are 'resolved'.
                # Anyway, in future updates, they could be resolved,
                # as we allow this in the first condition.
                mod.set_symbols(symbols[(checksum, fullname)])
                # Add module to mods_pending, or
                if (checksum, fullname) not in mods_pending:
                    mods_pending[(checksum, fullname)] = []
                mods_pending[(checksum, fullname)].append(mod)

    #Module load/del notification
    if base in modules[(p_pid, p_pgd)]:
        if modules[(p_pid, p_pgd)][base].get_size() != size or \
           modules[(p_pid, p_pgd)][base].get_checksum() != checksum or \
           modules[(p_pid, p_pgd)][base].get_name() != basename or \
           modules[(p_pid, p_pgd)][base].get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(
                p_pid, p_pgd, base, modules[(p_pid, p_pgd)][base].get_size(),
                modules[(p_pid, p_pgd)][base].get_name(),
                modules[(p_pid, p_pgd)][base].get_fullname())
            del modules[(p_pid, p_pgd)][base]
            modules[(p_pid, p_pgd)][base] = mod
            dispatch_module_load_callback(p_pid, p_pgd, base, size, basename,
                                          fullname)
        # If we updated the symbols and have a bigger list now, dont substitute the module
        # but update its symbols instead
        elif len(mod.get_symbols()) > len(
                modules[(p_pid, p_pgd)][base].get_symbols()):
            modules[(p_pid, p_pgd)][base].set_symbols(mod.get_symbols())
    else:
        # Just notify of module load
        modules[(p_pid, p_pgd)][base] = mod
        dispatch_module_load_callback(p_pid, p_pgd, base, size, basename,
                                      fullname)

    # Mark the module as present
    modules[(p_pid, p_pgd)][base].set_present()
예제 #4
0
def linux_insert_module(task,
                        pid,
                        pgd,
                        base,
                        size,
                        basename,
                        fullname,
                        update_symbols=False):
    from utils import ConfigurationManager as conf_m
    import volatility.obj as obj
    from vmi import add_symbols
    from vmi import get_symbols
    from vmi import has_symbols
    from vmi import add_module
    from vmi import has_module
    from vmi import get_module
    from vmi import Module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback
    import api
    import hashlib

    pgd_for_memory_read = conf_m.addr_space.vtop(task.mm.pgd) or task.mm.pgd

    # Create module, use 0 as checksum as it is irrelevant here
    mod = Module(base, size, pid, pgd, 0, basename, fullname)

    #Module load/del notification
    if has_module(pid, pgd, base):
        ex_mod = get_module(pid, pgd, base)
        if ex_mod.get_size() != size or \
           ex_mod.get_checksum() != checksum or \
           ex_mod.get_name() != basename or \
           ex_mod.get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(pid, pgd, base, ex_mod.get_size(),
                                            ex_mod.get_name(),
                                            ex_mod.get_fullname())
            add_module(pid, pgd, base, mod)
            dispatch_module_load_callback(pid, pgd, base, size, basename,
                                          fullname)
    else:
        # Just notify of module load
        dispatch_module_load_callback(pid, pgd, base, size, basename, fullname)
        add_module(pid, pgd, base, mod)

    # Mark the module as present
    get_module(pid, pgd, base).set_present()

    if update_symbols:
        # Compute the checksum of the ELF Header, as a way to avoid name
        # collisions on the symbol cache. May extend this hash to other parts
        # of the binary if necessary in the future.
        elf_hdr = obj.Object("elf_hdr",
                             offset=base,
                             vm=task.get_process_address_space())

        if elf_hdr.is_valid():
            elf_hdr_size = elf_hdr.elf_obj.size()
            buf = ""

            try:
                buf = api.r_va(pgd_for_memory_read, base, elf_hdr_size)
            except:
                pp_warning("Could not read ELF header at address %x" % base)

            if not has_symbols(fullname):
                syms = {}
                # Fetch symbols
                for sym in elf_hdr.symbols():
                    if sym.st_value == 0 or (sym.st_info & 0xf) != 2:
                        continue

                    sym_name = elf_hdr.symbol_name(sym)
                    sym_offset = sym.st_value
                    if sym_name in syms:
                        if syms[sym_name] != sym_offset:
                            # There are cases in which the same import is present twice, such as in this case:
                            # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np"
                            # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3
                            # 00000000000113a0 T
                            # pthread_getaffinity_np@@GLIBC_2.3.4
                            sym_name = sym_name + "_"
                            while sym_name in syms and syms[
                                    sym_name] != sym_offset:
                                sym_name = sym_name + "_"
                            if sym_name not in syms:
                                syms[sym_name] = sym_offset
                    else:
                        syms[sym_name] = sym_offset

                add_symbols(fullname, syms)

            mod.set_symbols(get_symbols(fullname))

    return None
예제 #5
0
def linux_insert_kernel_module(module,
                               base,
                               size,
                               basename,
                               fullname,
                               update_symbols=False):
    from vmi import add_module
    from vmi import has_module
    from vmi import get_module
    from vmi import has_symbols
    from vmi import get_symbols
    from vmi import add_symbols
    from vmi import Module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback

    # Create module, use 0 as checksum as it is irrelevant here
    mod = Module(base, size, 0, 0, 0, basename, fullname)

    #Module load/del notification
    if has_module(0, 0, base):
        ex_mod = get_module(0, 0, base)
        if ex_mod.get_size() != size or \
           ex_mod.get_checksum() != checksum or \
           ex_mod.get_name() != basename or \
           ex_mod.get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(0, 0, base, ex_mod.get_size(),
                                            ex_mod.get_name(),
                                            ex_mod.get_fullname())
            dispatch_module_load_callback(0, 0, base, size, basename, fullname)
            add_module(0, 0, base, mod)
    else:
        # Just notify of module load
        dispatch_module_load_callback(0, 0, base, size, basename, fullname)
        add_module(0, 0, base, mod)

    # Mark the module as present
    get_module(0, 0, base).set_present()

    if update_symbols:
        if not has_symbols(fullname):
            syms = {}
            try:
                '''
                pp_debug("Processing symbols for module %s\n" % basename)
                '''
                for sym_name, sym_offset in module.get_symbols():
                    if sym_name in syms:
                        if syms[sym_name] != sym_offset:
                            # There are cases in which the same import is present twice, such as in this case:
                            # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np"
                            # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3
                            # 00000000000113a0 T
                            # pthread_getaffinity_np@@GLIBC_2.3.4
                            sym_name = sym_name + "_"
                            while sym_name in syms and syms[
                                    sym_name] != sym_offset:
                                sym_name = sym_name + "_"
                            if sym_name not in syms:
                                syms[sym_name] = sym_offset
                    else:
                        syms[sym_name] = sym_offset

                add_symbols(fullname, syms)
            except Exception as e:
                # Probably could not fetch the symbols for this module
                pp_error("%s" % str(e))
                pass

        mod.set_symbols(get_symbols(fullname))

    return None
예제 #6
0
def linux_insert_kernel_module(module,
                               base,
                               size,
                               basename,
                               fullname,
                               update_symbols=False):
    from vmi import modules
    from vmi import symbols
    from vmi import Module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback

    # Create module, use 0 as checksum as it is irrelevant here
    mod = Module(base, size, 0, 0, 0, basename, fullname)

    # Add an entry in the module list, if necessary
    if (0, 0) not in modules:
        modules[(0, 0)] = {}

    #Module load/del notification
    if base in modules[(0, 0)]:
        if modules[(0, 0)][base].get_size() != size or \
           modules[(0, 0)][base].get_checksum() != checksum or \
           modules[(0, 0)][base].get_name() != basename or \
           modules[(0, 0)][base].get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(
                0, 0, base, modules[(0, 0)][base].get_size(),
                modules[(0, 0)][base].get_name(),
                modules[(0, 0)][base].get_fullname())
            del modules[(0, 0)][base]
            dispatch_module_load_callback(0, 0, base, size, basename, fullname)
            modules[(0, 0)][base] = mod
    else:
        # Just notify of module load
        dispatch_module_load_callback(0, 0, base, size, basename, fullname)
        modules[(0, 0)][base] = mod

    # Mark the module as present
    modules[(0, 0)][base].set_present()

    if update_symbols:
        # Use 0 as a checksum, here we should not have name collision
        checksum = 0
        if (checksum, fullname) not in symbols:
            symbols[(checksum, fullname)] = {}
            syms = symbols[(checksum, fullname)]
            try:
                '''
                pp_debug("Processing symbols for module %s\n" % basename)
                '''
                for sym_name, sym_offset in module.get_symbols():
                    if sym_name in syms:
                        if syms[sym_name] != sym_offset:
                            # There are cases in which the same import is present twice, such as in this case:
                            # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np"
                            # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3
                            # 00000000000113a0 T
                            # pthread_getaffinity_np@@GLIBC_2.3.4
                            sym_name = sym_name + "_"
                            while sym_name in syms and syms[
                                    sym_name] != sym_offset:
                                sym_name = sym_name + "_"
                            if sym_name not in syms:
                                syms[sym_name] = sym_offset
                    else:
                        syms[sym_name] = sym_offset
            except Exception as e:
                # Probably could not fetch the symbols for this module
                pp_error("%s" % str(e))
                pass

        mod.set_symbols(symbols[(checksum, fullname)])

    return None
예제 #7
0
def windows_insert_module_internal(p_pid, p_pgd, base, size, fullname,
                                   basename, checksum, nt_header,
                                   update_symbols):

    from utils import get_addr_space
    from vmi import modules
    from vmi import symbols
    from vmi import Module
    from vmi import PseudoLDRDATA
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback

    mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname)
    if p_pgd != 0:
        addr_space = get_addr_space(p_pgd)
    else:
        addr_space = get_addr_space()

    # Getting symbols, from cache!
    if (checksum, fullname) in symbols:
        mod.set_symbols(symbols[(checksum, fullname)])
    elif update_symbols:
        syms = {}
        export_dir = nt_header.OptionalHeader.DataDirectory[0]
        if export_dir:
            expdir = obj.Object('_IMAGE_EXPORT_DIRECTORY',
                                offset=base + export_dir.VirtualAddress,
                                vm=addr_space,
                                parent=PseudoLDRDATA(base, basename,
                                                     export_dir))
            if expdir.valid(nt_header):
                # Ordinal, Function RVA, and Name Object
                for o, f, n in expdir._exported_functions():
                    if not isinstance(o, obj.NoneObject) and \
                       not isinstance(f, obj.NoneObject) and \
                       not isinstance(n, obj.NoneObject):
                        syms[str(n)] = f.v()
        if len(syms) > 0:
            symbols[(checksum, fullname)] = syms
            mod.set_symbols(syms)
            if (checksum, fullname) in mods_pending:
                for m in mods_pending[(checksum, fullname)]:
                    m.set_symbols(syms)
                del mods_pending[(checksum, fullname)]
        else:
            if (checksum, fullname) in mods_pending:
                mods_pending[(checksum, fullname)].append(mod)
            else:
                mods_pending[(checksum, fullname)] = [mod]

    #Module load/del notification
    if base in modules[(p_pid, p_pgd)]:
        if modules[(p_pid, p_pgd)][base].get_size() != size or \
           modules[(p_pid, p_pgd)][base].get_checksum() != checksum or \
           modules[(p_pid, p_pgd)][base].get_name() != basename or \
           modules[(p_pid, p_pgd)][base].get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(
                p_pid, p_pgd, base, modules[(p_pid, p_pgd)][base].get_size(),
                modules[(p_pid, p_pgd)][base].get_name(),
                modules[(p_pid, p_pgd)][base].get_fullname())
            del modules[(p_pid, p_pgd)][base]
            dispatch_module_load_callback(p_pid, p_pgd, base, size, basename,
                                          fullname)
            modules[(p_pid, p_pgd)][base] = mod
    else:
        # Just notify of module load
        dispatch_module_load_callback(p_pid, p_pgd, base, size, basename,
                                      fullname)
        modules[(p_pid, p_pgd)][base] = mod

    # Mark the module as present
    modules[(p_pid, p_pgd)][base].set_present()
예제 #8
0
def linux_insert_module(task, pid, pgd, base, size, basename, fullname, update_symbols=False):
    from utils import ConfigurationManager as conf_m
    import volatility.obj as obj
    from vmi import modules
    from vmi import symbols
    from vmi import Module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback
    import api
    import hashlib

    pgd_for_memory_read = conf_m.addr_space.vtop(task.mm.pgd) or task.mm.pgd

    # Create module, use 0 as checksum as it is irrelevant here
    mod = Module(base, size, pid, pgd, 0, basename, fullname)

    # Add an entry in the module list, if necessary
    if (pid, pgd) not in modules:
        modules[(pid, pgd)] = {}

    #Module load/del notification
    if base in modules[(pid, pgd)]:
        if modules[(pid, pgd)][base].get_size() != size or \
           modules[(pid, pgd)][base].get_checksum() != checksum or \
           modules[(pid, pgd)][base].get_name() != basename or \
           modules[(pid, pgd)][base].get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(pid, pgd, base,
                                            modules[(pid, pgd)][base].get_size(),
                                            modules[(pid, pgd)][base].get_name(),
                                            modules[(pid, pgd)][base].get_fullname())
            del modules[(pid, pgd)][base]
            dispatch_module_load_callback(pid, pgd, base, size, basename, fullname)
            modules[(pid, pgd)][base] = mod
    else:
        # Just notify of module load
        dispatch_module_load_callback(pid, pgd, base, size, basename, fullname)
        modules[(pid, pgd)][base] = mod

    # Mark the module as present
    modules[(pid, pgd)][base].set_present()

    if update_symbols:
        # Compute the checksum of the ELF Header, as a way to avoid name
        # collisions on the symbol cache. May extend this hash to other parts
        # of the binary if necessary in the future.
        elf_hdr = obj.Object(
            "elf_hdr", offset=base, vm=task.get_process_address_space())

        if elf_hdr.is_valid():
            elf_hdr_size = elf_hdr.elf_obj.size()
            buf = ""

            try:
                buf = api.r_va(pgd_for_memory_read, base, elf_hdr_size)
            except:
                pp_warning("Could not read ELF header at address %x" % base)

            h = hashlib.sha256()
            h.update(buf)
            checksum = h.hexdigest()

            if (checksum, fullname) not in symbols:
                symbols[(checksum, fullname)] = {}
                syms = symbols[(checksum, fullname)]
                # Fetch symbols
                for sym in elf_hdr.symbols():
                    if sym.st_value == 0 or (sym.st_info & 0xf) != 2:
                        continue

                    sym_name = elf_hdr.symbol_name(sym)
                    sym_offset = sym.st_value
                    if sym_name in syms:
                        if syms[sym_name] != sym_offset:
                            # There are cases in which the same import is present twice, such as in this case:
                            # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np"
                            # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3
                            # 00000000000113a0 T
                            # pthread_getaffinity_np@@GLIBC_2.3.4
                            sym_name = sym_name + "_"
                            while sym_name in syms and syms[sym_name] != sym_offset:
                                sym_name = sym_name + "_"
                            if sym_name not in syms:
                                syms[sym_name] = sym_offset
                    else:
                        syms[sym_name] = sym_offset

            mod.set_symbols(symbols[(checksum, fullname)])

    return None
예제 #9
0
def linux_insert_kernel_module(module, base, size, basename, fullname, update_symbols=False):
    from vmi import modules
    from vmi import symbols
    from vmi import Module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback

    # Create module, use 0 as checksum as it is irrelevant here
    mod = Module(base, size, 0, 0, 0, basename, fullname)

    # Add an entry in the module list, if necessary
    if (0, 0) not in modules:
        modules[(0, 0)] = {}

    #Module load/del notification
    if base in modules[(0, 0)]:
        if modules[(0, 0)][base].get_size() != size or \
           modules[(0, 0)][base].get_checksum() != checksum or \
           modules[(0, 0)][base].get_name() != basename or \
           modules[(0, 0)][base].get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(0, 0, base,
                                            modules[(0, 0)][base].get_size(),
                                            modules[(0, 0)][base].get_name(),
                                            modules[(0, 0)][base].get_fullname())
            del modules[(0, 0)][base]
            dispatch_module_load_callback(0, 0, base, size, basename, fullname)
            modules[(0, 0)][base] = mod
    else:
        # Just notify of module load
        dispatch_module_load_callback(0, 0, base, size, basename, fullname)
        modules[(0, 0)][base] = mod

    # Mark the module as present
    modules[(0, 0)][base].set_present()

    if update_symbols:
        # Use 0 as a checksum, here we should not have name collision
        checksum = 0
        if (checksum, fullname) not in symbols:
            symbols[(checksum, fullname)] = {}
            syms = symbols[(checksum, fullname)]
            try:
                '''
                pp_debug("Processing symbols for module %s\n" % basename)
                '''
                for sym_name, sym_offset in module.get_symbols():
                    if sym_name in syms:
                        if syms[sym_name] != sym_offset:
                            # There are cases in which the same import is present twice, such as in this case:
                            # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np"
                            # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3
                            # 00000000000113a0 T
                            # pthread_getaffinity_np@@GLIBC_2.3.4
                            sym_name = sym_name + "_"
                            while sym_name in syms and syms[sym_name] != sym_offset:
                                sym_name = sym_name + "_"
                            if sym_name not in syms:
                                syms[sym_name] = sym_offset
                    else:
                        syms[sym_name] = sym_offset
            except Exception as e:
                # Probably could not fetch the symbols for this module
                pp_error("%s" % str(e))
                pass

        mod.set_symbols(symbols[(checksum, fullname)])

    return None
예제 #10
0
def windows_insert_module_internal(
        p_pid,
        p_pgd,
        base,
        size,
        fullname,
        basename,
        checksum,
        update_symbols,
        do_stop = False):

    from utils import get_addr_space
    from vmi import add_symbols
    from vmi import get_symbols
    from vmi import has_symbols
    from vmi import Module
    from vmi import add_module
    from vmi import get_module
    from vmi import has_module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback
    import pefile
    import api

    global filesystem
    global symbol_cache_must_be_saved

    if fullname.startswith("\\??\\"):
        fullname = fullname[4:]
    if fullname.upper().startswith("C:\\"):
        fullname = fullname[3:]
    if fullname.upper().startswith("\\SYSTEMROOT"):
        fullname = "\WINDOWS" + fullname[11:]

    fullname = fullname.replace("\\", "/")

    if fullname[-4:].upper() == ".SYS" and not "/" in fullname:
        fullname = "/WINDOWS/system32/DRIVERS/" + fullname

    fullname = fullname.lower()

    mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname)

    # First, we try to get the symbols from the cache 
    if fullname != "" and has_symbols(fullname):
        mod.set_symbols(get_symbols(fullname))

    # If we are updating symbols (a simple module retrieval would
    # not require symbol extraction), and we don't have any
    # symbols on the cache:
    elif fullname != "" and update_symbols:
        pp_debug("Symbols not found in cache, extracting from %s...\n" % fullname)
        unnamed_function_counter = 0
        syms = {}
    
        # Here, fetch the file using the sleuthkit, and use 
        # PE file to process it
        
        # First select the file system if not selected already
        if filesystem is None:
            for fs in api.get_filesystems():
                file_list = api.open_guest_path(fs["index"], "")
                if isinstance(file_list, list) and len(file_list) > 0:
                    if "windows" in [f.lower() for f in file_list]:
                        filesystem = fs

        if filesystem is not None:
            # Try to read the file
            f = None
            try:
                f = api.open_guest_path(filesystem["index"], fullname)
            except Exception as e:
                pp_error("%s - %s\n" % (str(e), fullname))

            if f is not None:
                data = f.read()
        
                pe = pefile.PE(data=data)

                if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
                    for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
                        if exp.name is not None:
                            syms[exp.name] = exp.address
                        else:
                            syms["unnamed_funcion_%d" % unnamed_function_counter] = exp.address
                            unnamed_function_counter += 1

        add_symbols(fullname, syms)
        mod.set_symbols(syms)
        # Even if it is empty, the module symbols are set
        # to an empty list, and thus are 'resolved'.
        # Anyway, in future updates, they could be resolved,
        # as we allow this in the first condition.
        symbol_cache_must_be_saved = True
 
    #Module load/del notification
    if has_module(p_pid, p_pgd, base):
        ex_mod = get_module(p_pid, p_pgd, base)
        # Module replacement, only if it is a different module, and also
        # take into consideration wow64 redirection. Never substitute the
        # wow64 version by the system32 version of the same dll
        if (ex_mod.get_fullname().lower() != fullname.lower()) and not ((ex_mod.get_name().lower() == basename.lower()) and ("windows/syswow64".lower() in ex_mod.get_fullname().lower()) and ("windows/system32" in fullname.lower())):
            # Notify of module deletion and module load
            dispatch_module_remove_callback(p_pid, p_pgd, base,
                                            ex_mod.get_size(),
                                            ex_mod.get_name(),
                                            ex_mod.get_fullname())
            add_module(p_pid, p_pgd, base, mod)
            mod.set_present()
            dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname)

        # If we updated the symbols and have a bigger list now, dont substitute the module
        # but update its symbols instead
        elif len(mod.get_symbols()) > len(ex_mod.get_symbols()):
            ex_mod.set_symbols(mod.get_symbols())
        # In any case, mark as present 
        ex_mod.set_present()
    else:
        # Just notify of module load
        add_module(p_pid, p_pgd, base, mod)
        # Mark the module as present
        mod.set_present()
        dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname)
예제 #11
0
def windows_insert_module_internal(p_pid, p_pgd, base, size, fullname,
                                   basename, checksum, update_symbols):

    from utils import get_addr_space
    from vmi import modules
    from vmi import symbols
    from vmi import Module
    from api_internal import dispatch_module_load_callback
    from api_internal import dispatch_module_remove_callback
    import pefile
    import api

    global filesystem
    global symbol_cache_must_be_saved

    if fullname.startswith("\\??\\"):
        fullname = fullname[4:]
    if fullname.upper().startswith("C:\\"):
        fullname = fullname[3:]
    if fullname.upper().startswith("\\SYSTEMROOT"):
        fullname = "\WINDOWS" + fullname[11:]

    fullname = fullname.replace("\\", "/")

    if fullname[-4:].upper() == ".SYS" and not "/" in fullname:
        fullname = "/WINDOWS/system32/DRIVERS/" + fullname

    fullname = fullname.lower()

    mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname)

    # First, we try to get the symbols from the cache
    if fullname != "" and fullname in symbols.keys():
        mod.set_symbols(symbols[fullname])

    # If we are updating symbols (a simple module retrieval would
    # not require symbol extraction), and we don't have any
    # symbols on the cache:
    elif fullname != "" and update_symbols:
        unnamed_function_counter = 0
        syms = {}

        # Here, fetch the file using the sleuthkit, and use
        # PE file to process it

        # First select the file system if not selected already
        if filesystem is None:
            for fs in api.get_filesystems():
                file_list = api.open_guest_path(fs["index"], "")
                if isinstance(file_list, list) and len(file_list) > 0:
                    if "windows" in [f.lower() for f in file_list]:
                        filesystem = fs

        if filesystem is not None:
            # Try to read the file
            f = None
            try:
                f = api.open_guest_path(filesystem["index"], fullname)
            except Exception as e:
                pp_error("%s - %s\n" % (str(e), fullname))

            if f is not None:
                data = f.read()

                pe = pefile.PE(data=data)

                if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
                    for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
                        if exp.name is not None:
                            syms[exp.name] = exp.address
                        else:
                            syms["unnamed_funcion_%d" %
                                 unnamed_function_counter] = exp.address
                            unnamed_function_counter += 1

                # If we managed to parse the export table, update the symbols
                # except if it is empty
                if fullname not in symbols.keys():
                    symbols[fullname] = syms
                    # Even if it is empty, the module symbols are set
                    # to an empty list, and thus are 'resolved'.
                    # Anyway, in future updates, they could be resolved,
                    # as we allow this in the first condition.
                    mod.set_symbols(symbols[fullname])
                    symbol_cache_must_be_saved = True
            else:
                symbols[fullname] = {}
                mod.set_symbols(symbols[fullname])

    #Module load/del notification
    if base in modules[(p_pid, p_pgd)]:
        if modules[(p_pid, p_pgd)][base].get_size() != size or \
           modules[(p_pid, p_pgd)][base].get_checksum() != checksum or \
           modules[(p_pid, p_pgd)][base].get_name() != basename or \
           modules[(p_pid, p_pgd)][base].get_fullname() != fullname:
            # Notify of module deletion and module load
            dispatch_module_remove_callback(
                p_pid, p_pgd, base, modules[(p_pid, p_pgd)][base].get_size(),
                modules[(p_pid, p_pgd)][base].get_name(),
                modules[(p_pid, p_pgd)][base].get_fullname())
            del modules[(p_pid, p_pgd)][base]
            modules[(p_pid, p_pgd)][base] = mod
            dispatch_module_load_callback(p_pid, p_pgd, base, size, basename,
                                          fullname)
        # If we updated the symbols and have a bigger list now, dont substitute the module
        # but update its symbols instead
        elif len(mod.get_symbols()) > len(
                modules[(p_pid, p_pgd)][base].get_symbols()):
            modules[(p_pid, p_pgd)][base].set_symbols(mod.get_symbols())
    else:
        # Just notify of module load
        modules[(p_pid, p_pgd)][base] = mod
        dispatch_module_load_callback(p_pid, p_pgd, base, size, basename,
                                      fullname)

    # Mark the module as present
    modules[(p_pid, p_pgd)][base].set_present()