Example #1
0
def windows_read_paged_file(pgd, addr, size, page_file_offset, page_file_number):
    import api
    # Step 1: Select the page file
    pagefile_filename = "pagefile.sys"
    # Step 2: Read the page file at the given offset
    f = None
    for fs in api.get_filesystems():
        try:
            f = api.open_guest_path(fs["index"], pagefile_filename)
            break
        except:
            # The file cannot be open on such filesystem
            pass
    if not f:
        raise RuntimeError("Could not read memory from pagefile: file not found")

    f.seek(page_file_offset)
    data = f.read(size = size)
    f.close()
    # Step 3: Return the data
    return data
Example #2
0
def windows_read_memory_mapped(pgd, addr, size, pte, is_pae, bitness):
    # Step 1: Traverse the VAD tree for the process with PGD,
    #         and get the VAD that overlaps addr (if any)
    # Step 2: Check if the VAD has a ControlArea and a FilePointer,
    #         and get the file path.
    # Step 3: Get Segment (pointed to by ControlArea), and get the pointer
    #         to the first PrototypePTE.
    # Step 4: Compute offset of address with respect to the beginning
    #         of the VAD, and compute which PrototypePTE corresponds to the address
    #         No need to consider if the PTE points to the Prototype PTE here.
    # Step 6: Compute the offset in file for such PrototypePTE by looking at the
    #         subsections pointed by the ControlArea.
    # Step 7: Finally, open the file, read the contents, and return them.
    import volatility.obj as obj
    import volatility.win32.tasks as tasks
    import volatility.plugins.vadinfo as vadinfo
    from utils import get_addr_space

    addr_space = get_addr_space(pgd)

    eprocs = [
        t for t in tasks.pslist(addr_space)
        if t.Pcb.DirectoryTableBase.v() == pgd
    ]

    if len(eprocs) != 1:
        return None

    task = eprocs[0]
    vad = None
    # File name and offset
    for vad in task.VadRoot.traverse():
        if addr >= vad.Start and addr < vad.End:
            break
    if vad is None:
        return None

    filename = None
    if vad.ControlArea is not None and vad.FileObject is not None:
        filename = str(vad.ControlArea.FileObject.FileName)

    if vad.ControlArea.Segment is None:
        return None

    # Compute page offset with respect to Start of the VAD,
    # and the corresponding prototype Page Table Entry pointed
    # by the Segment
    offset_on_vad = addr - vad.Start
    page_offset_on_vad = (offset_on_vad - (offset_on_vad & 0xFFF))
    # Consider 4 KiB pages
    ppte_index = page_offset_on_vad / 0x1000

    if ppte_index >= vad.ControlArea.Segment.TotalNumberOfPtes.v():
        return None

    if bitness == 32 and is_pae:
        ppte_addr = vad.ControlArea.Segment.PrototypePte.v() + (ppte_index * 8)
    else:
        ppte_addr = vad.ControlArea.Segment.PrototypePte.v() + (
            ppte_index * addr_space.profile.vtypes["_MMPTE_PROTOTYPE"][0])

    # Read Subsections pointed by ControlArea
    visited_subsections = {}
    if "Subsection" in vad.members:
        subsect = vad.Subsection
    # There is no Subsection pointer in VAD
    # structure, so we just read after the ControlArea
    else:
        subsect = obj.Object(
            "_SUBSECTION",
            offset=(vad.ControlArea.v() +
                    addr_space.profile.vtypes["_CONTROL_AREA"][0]),
            vm=addr_space)

    file_offset_to_read = None
    while file_offset_to_read is None and subsect is not None or subsect.v(
    ) != 0 and subsect.v() not in visited_subsections:
        visited_subsections.append(subsect.v())
        # Get the PPTE address where the Subsection starts,
        # and compute the virtual address that it corresponds
        # to.
        ppte_addr = subsect.SubsectionBase.v()
        if bitness == 32 and is_pae:
            ppte_index = (subsect.SubsectionBase.v() -
                          vad.ControlArea.Segment.PrototypePte.v()) / 8
        else:
            ppte_index = (subsect.SubsectionBase.v() -
                          vad.ControlArea.Segment.PrototypePte.v()
                          ) / addr_space.profile.vtypes["_MMPTE_PROTOTYPE"][0]

        subsection_base = vad.Start + (ppte_index * 0x1000)
        subsection_size = subsect.PtesInSubsection.v() * 0x1000
        subsection_file_offset = subsect.StartingSector.v() * 512
        subsection_file_size = vad.Subsection.NumberOfFullSectors.v() * 512

        visited_subsections[subsect.v()] = (subsection_base, subsection_size,
                                            subsection_file_offset,
                                            subsection_file_size)

        if (addr >= subsection_base) and (addr <
                                          (subsection_base + subsection_size)):
            file_offset_to_read = (addr -
                                   subsection_base) + subsection_file_offset

        subsect = subsect.NextSubsection

    f = None
    for fs in api.get_filesystems():
        try:
            f = api.open_guest_path(fs["index"], filename)
            break
        except:
            # The file cannot be open on such filesystem
            pass
    if not f:
        raise RuntimeError(
            "Could not read memory from pagefile: file not found")

    print("Reading file %s at offset %x - Size: %x" %
          (filename, file_offset_to_read, size))
    f.seek(file_offset_to_read)
    data = f.read(size=size)
    f.close()
Example #3
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)
Example #4
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()