def process_dump( cls, context: interfaces.context.ContextInterface, kernel_table_name: str, pe_table_name: str, proc: interfaces.objects.ObjectInterface ) -> interfaces.plugins.FileInterface: """Extracts the complete data for a process as a FileInterface Args: context: the context to operate upon kernel_table_name: the name for the symbol table containing the kernel's symbols pe_table_name: the name for the symbol table containing the PE format symbols proc: the process object whose memory should be output Returns: A FileInterface object containing the complete data for the process """ proc_id = proc.UniqueProcessId proc_layer_name = proc.add_process_layer() peb = context.object(kernel_table_name + constants.BANG + "_PEB", layer_name=proc_layer_name, offset=proc.Peb) dos_header = context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER", offset=peb.ImageBaseAddress, layer_name=proc_layer_name) filedata = interfaces.plugins.FileInterface( "pid.{0}.{1:#x}.dmp".format(proc.UniqueProcessId, peb.ImageBaseAddress)) for offset, data in dos_header.reconstruct(): filedata.data.seek(offset) filedata.data.write(data) return filedata
def process_dump( cls, context: interfaces.context.ContextInterface, kernel_table_name: str, pe_table_name: str, proc: interfaces.objects.ObjectInterface, open_method: Type[interfaces.plugins.FileHandlerInterface]) -> interfaces.plugins.FileHandlerInterface: """Extracts the complete data for a process as a FileHandlerInterface Args: context: the context to operate upon kernel_table_name: the name for the symbol table containing the kernel's symbols pe_table_name: the name for the symbol table containing the PE format symbols proc: the process object whose memory should be output open_method: class to provide context manager for opening the file Returns: An open FileHandlerInterface object containing the complete data for the process or None in the case of failure """ file_handle = None try: proc_layer_name = proc.add_process_layer() peb = context.object(kernel_table_name + constants.BANG + "_PEB", layer_name = proc_layer_name, offset = proc.Peb) dos_header = context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER", offset = peb.ImageBaseAddress, layer_name = proc_layer_name) file_handle = open_method("pid.{0}.{1:#x}.dmp".format(proc.UniqueProcessId, peb.ImageBaseAddress)) for offset, data in dos_header.reconstruct(): file_handle.seek(offset) file_handle.write(data) except Exception as excp: vollog.debug("Unable to dump PE with pid {}: {}".format(proc.UniqueProcessId, excp)) return file_handle
def vad_dump(cls, context: interfaces.context.ContextInterface, proc: interfaces.objects.ObjectInterface, vad: interfaces.objects.ObjectInterface, open_method: Type[ interfaces.plugins.FileHandlerInterface], maxsize: int = MAXSIZE_DEFAULT) -> Optional[interfaces.plugins.FileHandlerInterface]: """Extracts the complete data for Vad as a FileInterface. Args: context: The context to retrieve required elements (layers, symbol tables) from proc: an _EPROCESS instance vad: The suspected VAD to extract (ObjectInterface) open_method: class to provide context manager for opening the file maxsize: Max size of VAD section (default MAXSIZE_DEFAULT) Returns: An open FileInterface object containing the complete data for the process or None in the case of failure """ try: vad_start = vad.get_start() vad_end = vad.get_end() except AttributeError: vollog.debug("Unable to find the starting/ending VPN member") return if maxsize > 0 and (vad_end - vad_start) > maxsize: vollog.debug("Skip VAD dump {0:#x}-{1:#x} due to maxsize limit".format(vad_start, vad_end)) return proc_id = "Unknown" try: proc_id = proc.UniqueProcessId proc_layer_name = proc.add_process_layer() except exceptions.InvalidAddressException as excp: vollog.debug("Process {}: invalid address {} in layer {}".format(proc_id, excp.invalid_address, excp.layer_name)) return None proc_layer = context.layers[proc_layer_name] file_name = "pid.{0}.vad.{1:#x}-{2:#x}.dmp".format(proc_id, vad_start, vad_end) try: file_handle = open_method(file_name) chunk_size = 1024 * 1024 * 10 offset = vad_start while offset < vad_end: to_read = min(chunk_size, vad_end - offset) data = proc_layer.read(offset, to_read, pad = True) if not data: break file_handle.write(data) offset += to_read except Exception as excp: vollog.debug("Unable to dump VAD {}: {}".format(file_name, excp)) return return file_handle
def list_injections( cls, context: interfaces.context.ContextInterface, kernel_layer_name: str, symbol_table: str, proc: interfaces.objects.ObjectInterface ) -> Iterable[Tuple[interfaces.objects.ObjectInterface, bytes]]: """Generate memory regions for a process that may contain injected code. Args: context: The context to retrieve required elements (layers, symbol tables) from kernel_layer_name: The name of the kernel layer from which to read the VAD protections symbol_table: The name of the table containing the kernel symbols proc: an _EPROCESS instance Returns: An iterable of VAD instances and the first 64 bytes of data containing in that region """ proc_id = "Unknown" try: proc_id = proc.UniqueProcessId proc_layer_name = proc.add_process_layer() except exceptions.InvalidAddressException as excp: vollog.debug("Process {}: invalid address {} in layer {}".format( proc_id, excp.invalid_address, excp.layer_name)) return proc_layer = context.layers[proc_layer_name] for vad in proc.get_vad_root().traverse(): protection_string = vad.get_protection( vadinfo.VadInfo.protect_values(context, kernel_layer_name, symbol_table), vadinfo.winnt_protections) write_exec = "EXECUTE" in protection_string and "WRITE" in protection_string # the write/exec check applies to everything if not write_exec: continue if (vad.get_private_memory() == 1 and vad.get_tag() == "VadS") or ( vad.get_private_memory() == 0 and protection_string != "PAGE_EXECUTE_WRITECOPY"): if cls.is_vad_empty(proc_layer, vad): continue data = proc_layer.read(vad.get_start(), 64, pad=True) yield vad, data