diff --git a/volatility/cli/volshell/windows.py b/volatility/cli/volshell/windows.py index 37931fa74..2005c5813 100644 --- a/volatility/cli/volshell/windows.py +++ b/volatility/cli/volshell/windows.py @@ -44,7 +44,7 @@ class Volshell(shellplugin.Volshell): ntkrnlmp = self.context.module(self.config['nt_symbols'], layer_name = layer_name, offset = kvo) ps_aph_offset = ntkrnlmp.get_symbol("PsActiveProcessHead").address - list_entry = ntkrnlmp.object(type_name = "_LIST_ENTRY", offset = kvo + ps_aph_offset) + list_entry = ntkrnlmp.object(symbol = "_LIST_ENTRY", offset = ps_aph_offset) # This is example code to demonstrate how to use symbol_space directly, rather than through a module: # @@ -58,7 +58,7 @@ class Volshell(shellplugin.Volshell): # having been present. Strictly, the value of the requirement should be joined with the BANG character # defined in the constants file reloff = ntkrnlmp.get_type("_EPROCESS").relative_child_offset("ActiveProcessLinks") - eproc = ntkrnlmp.object(type_name = "_EPROCESS", offset = list_entry.vol.offset - reloff) + eproc = ntkrnlmp.object(symbol = "_EPROCESS", offset = list_entry.vol.offset - reloff, absolute = True) for proc in eproc.ActiveProcessLinks: yield proc diff --git a/volatility/framework/automagic/linux.py b/volatility/framework/automagic/linux.py index 14e347127..a4594dfd1 100644 --- a/volatility/framework/automagic/linux.py +++ b/volatility/framework/automagic/linux.py @@ -303,7 +303,7 @@ class LinuxUtilities(object): progress_callback = progress_callback): task_symbol = module.get_type('task_struct') init_task_address = offset - task_symbol.relative_child_offset('comm') - init_task = module.object(type_name = 'task_struct', offset = init_task_address) + init_task = module.object(symbol = 'task_struct', offset = init_task_address, absolute = True) if init_task.pid != 0: continue elif init_task.has_member('state') and init_task.state.cast('unsigned int') != 0: diff --git a/volatility/framework/constants/__init__.py b/volatility/framework/constants/__init__.py index 3ce11b671..0d94e4868 100644 --- a/volatility/framework/constants/__init__.py +++ b/volatility/framework/constants/__init__.py @@ -21,6 +21,7 @@ Stores all the constant values that are generally fixed throughout volatility This includes default scanning block sizes, etc.""" +import enum import os.path import sys from typing import Optional, Callable @@ -61,3 +62,9 @@ PARALLELISM_THREADING = 1 PARALLELISM_MULTIPROCESSING = 2 PARALLELISM = PARALLELISM_OFF + + +class SymbolType(enum.Enum): + TYPE = 1 + SYMBOL = 2 + ENUM = 3 diff --git a/volatility/framework/contexts/__init__.py b/volatility/framework/contexts/__init__.py index 719837f8c..d52eca6e9 100644 --- a/volatility/framework/contexts/__init__.py +++ b/volatility/framework/contexts/__init__.py @@ -93,6 +93,7 @@ class Context(interfaces.context.ContextInterface): symbol: Union[str, interfaces.objects.Template], layer_name: str, offset: int, + symbol_type: Optional[constants.SymbolType] = None, native_layer_name: Optional[str] = None, **arguments) -> interfaces.objects.ObjectInterface: """Object factory, takes a context, symbol, offset and optional layername @@ -110,11 +111,20 @@ class Context(interfaces.context.ContextInterface): A fully constructed object """ if not isinstance(symbol, interfaces.objects.Template): - object_template = self._symbol_space.get_type(symbol) + if symbol_type == constants.SymbolType.SYMBOL: + symbol_obj = self._symbol_space.get_symbol(symbol) + if symbol_obj.type is None: + raise ValueError("Symbol {} has no associated type information".format(symbol_obj.name)) + object_template = symbol_obj.type + elif symbol_type == constants.SymbolType.ENUM: + object_template = self._symbol_space.get_enumeration(symbol) + else: + object_template = self._symbol_space.get_type(symbol) else: object_template = symbol # Ensure that if a pre-constructed type is provided we just instantiate it arguments.update(object_template.vol) + object_template = object_template.clone() object_template.update_vol(**arguments) return object_template( @@ -149,9 +159,11 @@ def get_module_wrapper(method: str) -> Callable: """Returns a symbol using the symbol_table_name of the Module""" def wrapper(self, name: str) -> Callable: - if constants.BANG in name: - raise ValueError("Name cannot reference another module") - return getattr(self._context.symbol_space, method)(self._module_name + constants.BANG + name) + if constants.BANG not in name: + name = self._module_name + constants.BANG + name + else: + raise ValueError("Cannot reference another module when calling {}".format(method)) + return getattr(self._context.symbol_space, method)(name) for entry in ['__annotations__', '__doc__', '__module__', '__name__', '__qualname__']: proxy_interface = getattr(interfaces.context.ModuleInterface, method) @@ -164,40 +176,45 @@ def get_module_wrapper(method: str) -> Callable: class Module(interfaces.context.ModuleInterface): def object(self, - symbol_name: Optional[str] = None, - type_name: Optional[str] = None, - offset: Optional[int] = None, + symbol: str, + symbol_type: Optional[constants.SymbolType] = None, + offset: int = None, native_layer_name: Optional[str] = None, - **kwargs) -> interfaces.objects.ObjectInterface: + absolute: bool = False, + **kwargs) -> 'interfaces.objects.ObjectInterface': """Returns an object created using the symbol_table_name and layer_name of the Module Args: - symbol_name: Name of the symbol (within the module) to construct, type_name and offset must not be specified - type_name: Name of the type (within the module) to construct, offset must be specified and symbol_name must not - offset: The location (absolute within memory), type_name must be specified and symbol_name must not + symbol: Name of the type/symbol/enumeration (within the module) to construct + symbol_type: One of the SymbolType enumeratino (Type/Symbol/Enum), defaults to Type + offset: The location of the object, ignored when symbol_type is SYMBOL native_layer_name: Name of the layer in which constructed objects are made (for pointers) """ - type_arg = None # type: Optional[Union[str, interfaces.objects.Template]] - if symbol_name is not None: - if constants.BANG in symbol_name: - raise ValueError("Symbol_name cannot reference another module") - symbol = self._context.symbol_space.get_symbol(self.symbol_table_name + constants.BANG + symbol_name) - if symbol.type is None: - raise ValueError("Symbol {} has no associated type information".format(symbol.name)) - type_arg = symbol.type - offset = symbol.address - if not self._absolute_symbol_addresses: - offset += self._offset - elif type_name is not None and offset is not None: - if constants.BANG in type_name: - raise ValueError("Type_name cannot reference another module") - type_arg = self.symbol_table_name + constants.BANG + type_name + if constants.BANG not in symbol: + symbol = self.symbol_table_name + constants.BANG + symbol else: - raise ValueError("One of symbol_name, or type_name & offset, must be specified to construct a module") + raise ValueError("Cannot reference another module when constructing an object") + + # Only set the offset if type is Symbol and we were given a name, not a template + if symbol_type == constants.SymbolType.SYMBOL: + offset = self._context.symbol_space.get_symbol(symbol).address + + if offset is None: + raise ValueError("Offset must not be None for non-symbol objects") + + if not absolute: + offset += self._offset + # Ensure we don't use a layer_name other than the module's, why would anyone do that? if 'layer_name' in kwargs: del kwargs['layer_name'] - return self._context.object(type_arg, self._layer_name, offset, native_layer_name, **kwargs) + return self._context.object( + symbol = symbol, + symbol_type = symbol_type, + layer_name = self._layer_name, + offset = offset, + native_layer_name = native_layer_name, + **kwargs) get_symbol = get_module_wrapper('get_symbol') get_type = get_module_wrapper('get_type') @@ -216,16 +233,14 @@ class SizedModule(Module): offset: int, size: int, symbol_table_name: Optional[str] = None, - native_layer_name: Optional[str] = None, - absolute_symbol_addresses: bool = False) -> None: + native_layer_name: Optional[str] = None) -> None: super().__init__( context, module_name = module_name, layer_name = layer_name, offset = offset, native_layer_name = native_layer_name, - symbol_table_name = symbol_table_name, - absolute_symbol_addresses = absolute_symbol_addresses) + symbol_table_name = symbol_table_name) self._size = size @property diff --git a/volatility/framework/interfaces/context.py b/volatility/framework/interfaces/context.py index 965bde39a..9f1399a9c 100644 --- a/volatility/framework/interfaces/context.py +++ b/volatility/framework/interfaces/context.py @@ -27,7 +27,7 @@ import copy from abc import ABCMeta, abstractmethod from typing import Optional, Union -from volatility.framework import interfaces +from volatility.framework import interfaces, constants class ContextInterface(object, metaclass = ABCMeta): @@ -115,8 +115,7 @@ class ModuleInterface(metaclass = ABCMeta): layer_name: str, offset: int, symbol_table_name: Optional[str] = None, - native_layer_name: Optional[str] = None, - absolute_symbol_addresses: bool = False) -> None: + native_layer_name: Optional[str] = None) -> None: self._context = context self._module_name = module_name self._layer_name = layer_name @@ -125,7 +124,6 @@ class ModuleInterface(metaclass = ABCMeta): if native_layer_name: self._native_layer_name = native_layer_name self.symbol_table_name = symbol_table_name or self._module_name - self._absolute_symbol_addresses = absolute_symbol_addresses super().__init__() @property @@ -148,7 +146,12 @@ class ModuleInterface(metaclass = ABCMeta): return self._context @abstractmethod - def object(self, symbol_name: str = None, type_name: str = None, offset: int = None, + def object(self, + symbol: Union[str, 'interfaces.objects.Template'], + symbol_type: Optional[constants.SymbolType] = None, + offset: int = None, + native_layer_name: Optional[str] = None, + absolute: bool = False, **kwargs) -> 'interfaces.objects.ObjectInterface': """Returns an object created using the symbol_table_name and layer_name of the Module""" diff --git a/volatility/framework/layers/msf.py b/volatility/framework/layers/msf.py index 1caad67b6..99e04ce27 100644 --- a/volatility/framework/layers/msf.py +++ b/volatility/framework/layers/msf.py @@ -63,8 +63,7 @@ class PdbMultiStreamFormat(interfaces.layers.TranslationLayerInterface): root_table_num_pages = math.ceil(self._header.StreamInfo.StreamInfoSize / self._header.PageSize) root_index_size = math.ceil((root_table_num_pages * entry_size) / self._header.PageSize) root_index = module.object( - type_name = "array", - layer_name = self._base_layer, + symbol = "array", offset = self._header.vol.size, count = root_index_size, subtype = module.get_type("unsigned long")) @@ -73,14 +72,14 @@ class PdbMultiStreamFormat(interfaces.layers.TranslationLayerInterface): module = self.context.module(self.pdb_symbol_table, root_index_layer_name, offset = 0) root_pages = module.object( - type_name = "array", offset = 0, count = root_table_num_pages, subtype = module.get_type("unsigned long")) + symbol = "array", offset = 0, count = root_table_num_pages, subtype = module.get_type("unsigned long")) root_layer_name = self.create_stream_from_pages("root", self._header.StreamInfo.StreamInfoSize, [x for x in root_pages]) module = self.context.module(self.pdb_symbol_table, root_layer_name, offset = 0) - num_streams = module.object(type_name = "unsigned long", offset = 0) + num_streams = module.object(symbol = "unsigned long", offset = 0) stream_sizes = module.object( - type_name = "array", offset = entry_size, count = num_streams, subtype = module.get_type("unsigned long")) + symbol = "array", offset = entry_size, count = num_streams, subtype = module.get_type("unsigned long")) current_offset = (num_streams + 1) * entry_size @@ -90,7 +89,7 @@ class PdbMultiStreamFormat(interfaces.layers.TranslationLayerInterface): self._streams[stream] = None else: stream_page_list = module.object( - type_name = "array", + symbol = "array", offset = current_offset, count = list_size, subtype = module.get_type("unsigned long")) diff --git a/volatility/framework/plugins/linux/check_afinfo.py b/volatility/framework/plugins/linux/check_afinfo.py index 014b4c2fb..946588556 100644 --- a/volatility/framework/plugins/linux/check_afinfo.py +++ b/volatility/framework/plugins/linux/check_afinfo.py @@ -98,7 +98,7 @@ class Check_afinfo(plugins.PluginInterface): except exceptions.SymbolError: continue - global_var = vmlinux.object(type_name = struct_type, offset = global_var.address) + global_var = vmlinux.object(symbol = struct_type, offset = global_var.address) for name, member, address in self._check_afinfo(global_var_name, global_var, op_members, seq_members): yield 0, (name, member, format_hints.Hex(address)) diff --git a/volatility/framework/plugins/linux/check_syscall.py b/volatility/framework/plugins/linux/check_syscall.py index 92ea98872..94ea1953f 100644 --- a/volatility/framework/plugins/linux/check_syscall.py +++ b/volatility/framework/plugins/linux/check_syscall.py @@ -176,7 +176,7 @@ class Check_syscall(plugins.PluginInterface): for (table_name, (tableaddr, tblsz)) in tables: table = vmlinux.object( - type_name = "array", subtype = vmlinux.get_type("pointer"), offset = tableaddr, count = tblsz) + symbol = "array", subtype = vmlinux.get_type("pointer"), offset = tableaddr, count = tblsz) for (i, call_addr) in enumerate(table): if not call_addr: diff --git a/volatility/framework/plugins/linux/lsmod.py b/volatility/framework/plugins/linux/lsmod.py index 9b0df9055..841506b4f 100644 --- a/volatility/framework/plugins/linux/lsmod.py +++ b/volatility/framework/plugins/linux/lsmod.py @@ -23,8 +23,8 @@ typically found in Linux's /proc file system. from typing import List +from volatility.framework import contexts from volatility.framework import renderers, constants, interfaces -from volatility.framework import exceptions, contexts from volatility.framework.automagic import linux from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins @@ -48,9 +48,9 @@ class Lsmod(plugins.PluginInterface): """Lists all the modules in the primary layer""" linux.LinuxUtilities.aslr_mask_symbol_table(context, vmlinux_symbols, layer_name) - vmlinux = contexts.Module(context, vmlinux_symbols, layer_name, 0, absolute_symbol_addresses = True) + vmlinux = contexts.Module(context, vmlinux_symbols, layer_name, 0) - modules = vmlinux.object(symbol_name = "modules").cast("list_head") + modules = vmlinux.object(symbol = "modules", symbol_type = constants.SymbolType.SYMBOL).cast("list_head") table_name = modules.vol.type_name.split(constants.BANG)[0] diff --git a/volatility/framework/plugins/linux/pslist.py b/volatility/framework/plugins/linux/pslist.py index 03b91f452..0d9dccfd0 100644 --- a/volatility/framework/plugins/linux/pslist.py +++ b/volatility/framework/plugins/linux/pslist.py @@ -21,7 +21,7 @@ from typing import Callable, Iterable, List import volatility.framework.interfaces.plugins as interfaces_plugins -from volatility.framework import renderers, interfaces, contexts +from volatility.framework import renderers, interfaces, contexts, constants from volatility.framework.automagic import linux from volatility.framework.configuration import requirements from volatility.framework.objects import utility @@ -75,9 +75,9 @@ class PsList(interfaces_plugins.PluginInterface): """Lists all the tasks in the primary layer""" linux.LinuxUtilities.aslr_mask_symbol_table(context, vmlinux_symbols, layer_name) - vmlinux = contexts.Module(context, vmlinux_symbols, layer_name, 0, absolute_symbol_addresses = True) + vmlinux = contexts.Module(context, vmlinux_symbols, layer_name, 0) - init_task = vmlinux.object(symbol_name = "init_task") + init_task = vmlinux.object(symbol = "init_task", symbol_type = constants.SymbolType.SYMBOL) for task in init_task.tasks: if not filter_func(task): diff --git a/volatility/framework/plugins/mac/check_syscall.py b/volatility/framework/plugins/mac/check_syscall.py index 49cd6964a..04b30dc48 100644 --- a/volatility/framework/plugins/mac/check_syscall.py +++ b/volatility/framework/plugins/mac/check_syscall.py @@ -25,11 +25,10 @@ class Check_syscall(plugins.PluginInterface): def _generator(self): mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary']) - kernel = contexts.Module( - self._context, self.config['darwin'], self.config['primary'], 0, absolute_symbol_addresses = True) + kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0) - nsysent = kernel.object(symbol_name = "nsysent") - table = kernel.object(symbol_name = "sysent") + nsysent = kernel.object(symbol = "nsysent", symbol_type = constants.SymbolType.SYMBOL) + table = kernel.object(symbol = "sysent", symbol_type = constants.SymbolType.SYMBOL) # smear help num_ents = min(nsysent, table.count) diff --git a/volatility/framework/plugins/mac/check_sysctl.py b/volatility/framework/plugins/mac/check_sysctl.py index 4f5966941..4c50087e2 100644 --- a/volatility/framework/plugins/mac/check_sysctl.py +++ b/volatility/framework/plugins/mac/check_sysctl.py @@ -12,6 +12,7 @@ from volatility.framework.objects import utility vollog = logging.getLogger(__name__) + class Check_sysctl(plugins.PluginInterface): """Check sysctl handlers for hooks""" @@ -25,17 +26,17 @@ class Check_sysctl(plugins.PluginInterface): def _parse_global_variable_sysctls(self, kernel, name): known_sysctls = { - "hostname" : "hostname", - "nisdomainname" : "domainname", + "hostname": "hostname", + "nisdomainname": "domainname", } - + var_str = "" if name in known_sysctls: var_name = known_sysctls[name] try: - var_array = kernel.object(symbol_name = var_name) + var_array = kernel.object(symbol = var_name) except exceptions.SymbolError: var_array = None @@ -61,7 +62,7 @@ class Check_sysctl(plugins.PluginInterface): name = utility.pointer_to_string(sysctl.oid_name, 128) except exceptions.PagedInvalidAddressException: name = "" - + if len(name) == 0: break @@ -103,14 +104,13 @@ class Check_sysctl(plugins.PluginInterface): sysctl = sysctl.oid_link.sle_next except exceptions.PagedInvalidAddressException: break - + def _generator(self): mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary']) - kernel = contexts.Module( - self._context, self.config['darwin'], self.config['primary'], 0, absolute_symbol_addresses = True) + kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0) - sysctl_list = kernel.object(symbol_name = "sysctl__children") + sysctl_list = kernel.object(symbo = "sysctl__children", symbol_type = constants.SymbolType.SYMBOL) for sysctl, name, val in self._process_sysctl_list(kernel, sysctl_list): check_addr = sysctl.oid_handler @@ -130,4 +130,5 @@ class Check_sysctl(plugins.PluginInterface): def run(self): return renderers.TreeGrid([("Name", str), ("Number", int), ("Perms", str), - ("Handler Address", format_hints.Hex), ("Value", str), ("Handler Symbol", str)], self._generator()) + ("Handler Address", format_hints.Hex), ("Value", str), ("Handler Symbol", str)], + self._generator()) diff --git a/volatility/framework/plugins/mac/check_trap_table.py b/volatility/framework/plugins/mac/check_trap_table.py index 8df977d35..7b659ff75 100644 --- a/volatility/framework/plugins/mac/check_trap_table.py +++ b/volatility/framework/plugins/mac/check_trap_table.py @@ -25,10 +25,9 @@ class Check_trap_table(plugins.PluginInterface): def _generator(self): mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary']) - kernel = contexts.Module( - self._context, self.config['darwin'], self.config['primary'], 0, absolute_symbol_addresses = True) + kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0) - table = kernel.object(symbol_name = "mach_trap_table") + table = kernel.object(symbol = "mach_trap_table", symbol_type = constants.SymbolType.SYMBOL) for i, ent in enumerate(table): try: diff --git a/volatility/framework/plugins/mac/lsmod.py b/volatility/framework/plugins/mac/lsmod.py index 4ead29f93..cdcacc579 100644 --- a/volatility/framework/plugins/mac/lsmod.py +++ b/volatility/framework/plugins/mac/lsmod.py @@ -21,7 +21,7 @@ typically found in Mac's lsmod command. """ -from volatility.framework import renderers, interfaces, contexts +from volatility.framework import renderers, interfaces, contexts, constants from volatility.framework.automagic import mac from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins @@ -45,9 +45,9 @@ class Lsmod(plugins.PluginInterface): """Lists all the modules in the primary layer""" mac.MacUtilities.aslr_mask_symbol_table(context, darwin_symbols, layer_name) - kernel = contexts.Module(context, darwin_symbols, layer_name, 0, absolute_symbol_addresses = True) + kernel = contexts.Module(context, darwin_symbols, layer_name, 0) - kmod_ptr = kernel.object(symbol_name = "kmod") + kmod_ptr = kernel.object(symbol = "kmod", symbol_type = constants.SymbolType.SYMBOL) # TODO - use smear-proof list walking API after dev release kmod = kmod_ptr.dereference().cast("kmod_info") diff --git a/volatility/framework/plugins/mac/pslist.py b/volatility/framework/plugins/mac/pslist.py index ed95e0d1b..84be3b539 100644 --- a/volatility/framework/plugins/mac/pslist.py +++ b/volatility/framework/plugins/mac/pslist.py @@ -22,7 +22,7 @@ import logging from typing import Callable, Iterable, List import volatility.framework.interfaces.plugins as interfaces_plugins -from volatility.framework import renderers, interfaces, contexts +from volatility.framework import renderers, interfaces, contexts, constants from volatility.framework.automagic import mac from volatility.framework.configuration import requirements from volatility.framework.objects import utility @@ -78,9 +78,9 @@ class PsList(interfaces_plugins.PluginInterface): mac.MacUtilities.aslr_mask_symbol_table(context, darwin_symbols, layer_name) - kernel = contexts.Module(context, darwin_symbols, layer_name, 0, absolute_symbol_addresses = True) + kernel = contexts.Module(context, darwin_symbols, layer_name, 0) - proc = kernel.object(symbol_name = "allproc").lh_first + proc = kernel.object(symbol = "allproc", symbol_type = constants.SymbolType.SYMBOL).lh_first seen = {} while proc is not None and proc.vol.offset != 0: diff --git a/volatility/framework/plugins/mac/trustedbsd.py b/volatility/framework/plugins/mac/trustedbsd.py index 83470ea2f..37697ae80 100644 --- a/volatility/framework/plugins/mac/trustedbsd.py +++ b/volatility/framework/plugins/mac/trustedbsd.py @@ -47,13 +47,13 @@ class Check_syscall(plugins.PluginInterface): def _generator(self, mods: Iterator[Any]): mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary']) - kernel = contexts.Module( - self._context, self.config['darwin'], self.config['primary'], 0, absolute_symbol_addresses = True) + kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0) - policy_list = kernel.object(symbol_name = "_mac_policy_list").cast("mac_policy_list") + policy_list = kernel.object( + symbol = "_mac_policy_list", symbol_type = constants.SymbolType.SYMBOL).cast("mac_policy_list") entries = kernel.object( - type_name = "array", + symbol = "array", offset = policy_list.entries.dereference().vol.offset, subtype = kernel.get_type('mac_policy_list_element'), count = policy_list.staticmax + 1) diff --git a/volatility/framework/plugins/windows/handles.py b/volatility/framework/plugins/windows/handles.py index 3ffe2e291..d68435c28 100644 --- a/volatility/framework/plugins/windows/handles.py +++ b/volatility/framework/plugins/windows/handles.py @@ -162,7 +162,7 @@ class Handles(interfaces_plugins.PluginInterface): table_addr = ntkrnlmp.get_symbol("ObpObjectTypes").address ptrs = ntkrnlmp.object( - type_name = "array", offset = kvo + table_addr, subtype = ntkrnlmp.get_type("pointer"), count = 100) + symbol = "array", offset = table_addr, subtype = ntkrnlmp.get_type("pointer"), count = 100) for i, ptr in enumerate(ptrs): #type: ignore # the first entry in the table is always null. break the @@ -214,7 +214,7 @@ class Handles(interfaces_plugins.PluginInterface): if not self.context.layers[virtual].is_valid(offset): return - table = ntkrnlmp.object(type_name = "array", offset = offset, subtype = subtype, count = int(count)) + table = ntkrnlmp.object(symbol = "array", offset = offset, subtype = subtype, count = int(count)) layer_object = self.context.layers[virtual] masked_offset = (offset & layer_object.maximum_address) diff --git a/volatility/framework/plugins/windows/info.py b/volatility/framework/plugins/windows/info.py index 4411df4f6..fca45026e 100644 --- a/volatility/framework/plugins/windows/info.py +++ b/volatility/framework/plugins/windows/info.py @@ -105,8 +105,7 @@ class Info(plugins.PluginInterface): vers_offset = ntkrnlmp.get_symbol("KdVersionBlock").address - vers = ntkrnlmp.object( - type_name = "_DBGKD_GET_VERSION64", layer_name = virtual_layer_name, offset = kvo + vers_offset) + vers = ntkrnlmp.object(symbol = "_DBGKD_GET_VERSION64", layer_name = virtual_layer_name, offset = vers_offset) yield (0, ("KdVersionBlock", hex(vers.vol.offset))) yield (0, ("Major/Minor", "{0}.{1}".format(vers.MajorVersion, vers.MinorVersion))) @@ -114,8 +113,7 @@ class Info(plugins.PluginInterface): cpu_count_offset = ntkrnlmp.get_symbol("KeNumberProcessors").address - cpu_count = ntkrnlmp.object( - type_name = "unsigned int", layer_name = virtual_layer_name, offset = kvo + cpu_count_offset) + cpu_count = ntkrnlmp.object(symbol = "unsigned int", layer_name = virtual_layer_name, offset = cpu_count_offset) yield (0, ("KeNumberProcessors", str(cpu_count))) @@ -125,7 +123,8 @@ class Info(plugins.PluginInterface): else: kuser_addr = 0xFFFFF78000000000 - kuser = ntkrnlmp.object(type_name = "_KUSER_SHARED_DATA", layer_name = virtual_layer_name, offset = kuser_addr) + kuser = ntkrnlmp.object( + symbol = "_KUSER_SHARED_DATA", layer_name = virtual_layer_name, offset = kuser_addr, absolute = True) yield (0, ("SystemTime", str(kuser.SystemTime.get_time()))) yield (0, ("NtSystemRoot", diff --git a/volatility/framework/plugins/windows/modules.py b/volatility/framework/plugins/windows/modules.py index 106ba308f..b0ed1f4e0 100644 --- a/volatility/framework/plugins/windows/modules.py +++ b/volatility/framework/plugins/windows/modules.py @@ -75,9 +75,9 @@ class Modules(interfaces.plugins.PluginInterface): type_name = ldr_entry_type.type_name.split(constants.BANG)[1] list_head = ntkrnlmp.get_symbol("PsLoadedModuleList").address - list_entry = ntkrnlmp.object(type_name = "_LIST_ENTRY", offset = kvo + list_head) + list_entry = ntkrnlmp.object(symbol = "_LIST_ENTRY", offset = list_head) reloff = ldr_entry_type.relative_child_offset("InLoadOrderLinks") - module = ntkrnlmp.object(type_name = type_name, offset = list_entry.vol.offset - reloff) + module = ntkrnlmp.object(symbol = type_name, offset = list_entry.vol.offset - reloff, absolute = True) for mod in module.InLoadOrderLinks: yield mod diff --git a/volatility/framework/plugins/windows/poolscanner.py b/volatility/framework/plugins/windows/poolscanner.py index 9e9eaf5f6..d2d342910 100644 --- a/volatility/framework/plugins/windows/poolscanner.py +++ b/volatility/framework/plugins/windows/poolscanner.py @@ -87,7 +87,8 @@ class PoolHeaderScanner(interfaces.layers.ScannerInterface): def __call__(self, data: bytes, data_offset: int): for offset, pattern in self._subscanner(data, data_offset): - header = self._module.object(type_name = "_POOL_HEADER", offset = offset - self._header_offset) + header = self._module.object( + symbol = "_POOL_HEADER", offset = offset - self._header_offset, absolute = True) constraint = self._constraint_lookup[pattern] try: # Size check diff --git a/volatility/framework/plugins/windows/pslist.py b/volatility/framework/plugins/windows/pslist.py index b3a7a50e7..6b2500974 100644 --- a/volatility/framework/plugins/windows/pslist.py +++ b/volatility/framework/plugins/windows/pslist.py @@ -87,7 +87,7 @@ class PsList(plugins.PluginInterface, timeliner.TimeLinerInterface): ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) ps_aph_offset = ntkrnlmp.get_symbol("PsActiveProcessHead").address - list_entry = ntkrnlmp.object(type_name = "_LIST_ENTRY", offset = kvo + ps_aph_offset) + list_entry = ntkrnlmp.object(symbol = "_LIST_ENTRY", offset = ps_aph_offset) # This is example code to demonstrate how to use symbol_space directly, rather than through a module: # @@ -101,7 +101,7 @@ class PsList(plugins.PluginInterface, timeliner.TimeLinerInterface): # having been present. Strictly, the value of the requirement should be joined with the BANG character # defined in the constants file reloff = ntkrnlmp.get_type("_EPROCESS").relative_child_offset("ActiveProcessLinks") - eproc = ntkrnlmp.object(type_name = "_EPROCESS", offset = list_entry.vol.offset - reloff) + eproc = ntkrnlmp.object(symbol = "_EPROCESS", offset = list_entry.vol.offset - reloff, absolute = True) for proc in eproc.ActiveProcessLinks: if not filter_func(proc): diff --git a/volatility/framework/plugins/windows/registry/hivelist.py b/volatility/framework/plugins/windows/registry/hivelist.py index 37a2e9e0d..d97b3c6ab 100644 --- a/volatility/framework/plugins/windows/registry/hivelist.py +++ b/volatility/framework/plugins/windows/registry/hivelist.py @@ -63,9 +63,9 @@ class HiveList(plugins.PluginInterface): ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) list_head = ntkrnlmp.get_symbol("CmpHiveListHead").address - list_entry = ntkrnlmp.object(type_name = "_LIST_ENTRY", offset = kvo + list_head) + list_entry = ntkrnlmp.object(symbol = "_LIST_ENTRY", offset = list_head) reloff = ntkrnlmp.get_type("_CMHIVE").relative_child_offset("HiveList") - cmhive = ntkrnlmp.object(type_name = "_CMHIVE", offset = list_entry.vol.offset - reloff) + cmhive = ntkrnlmp.object(symbol = "_CMHIVE", offset = list_entry.vol.offset - reloff, absolute = True) # Run through the list fowards seen = set() diff --git a/volatility/framework/plugins/windows/ssdt.py b/volatility/framework/plugins/windows/ssdt.py index 35f32d7f5..53cbbf045 100644 --- a/volatility/framework/plugins/windows/ssdt.py +++ b/volatility/framework/plugins/windows/ssdt.py @@ -19,7 +19,7 @@ # import os -from typing import Any, Iterator, List, Tuple, Sequence +from typing import Any, Iterator, List, Tuple from volatility.framework import constants, interfaces from volatility.framework import contexts @@ -85,7 +85,7 @@ class SSDT(plugins.PluginInterface): ## we could also find nt!KeServiceDescriptorTable (NT) and KeServiceDescriptorTableShadow (NT, Win32K) service_table_address = ntkrnlmp.get_symbol("KiServiceTable").address service_limit_address = ntkrnlmp.get_symbol("KiServiceLimit").address - service_limit = ntkrnlmp.object(type_name = "int", offset = kvo + service_limit_address) + service_limit = ntkrnlmp.object(symbol = "int", offset = service_limit_address) # on 32-bit systems the table indexes are 32-bits and contain pointers (unsigned) # on 64-bit systems the indexes are also 32-bits but they're offsets from the @@ -107,8 +107,8 @@ class SSDT(plugins.PluginInterface): find_address = passthrough functions = ntkrnlmp.object( - type_name = "array", - offset = kvo + service_table_address, + symbol = "array", + offset = service_table_address, subtype = ntkrnlmp.get_type(array_subtype), count = service_limit) diff --git a/volatility/framework/plugins/windows/vadinfo.py b/volatility/framework/plugins/windows/vadinfo.py index 6c7c559c7..d88ec0b93 100644 --- a/volatility/framework/plugins/windows/vadinfo.py +++ b/volatility/framework/plugins/windows/vadinfo.py @@ -78,8 +78,7 @@ class VadInfo(interfaces.plugins.PluginInterface): kvo = context.layers[virtual_layer].config["kernel_virtual_offset"] ntkrnlmp = context.module(nt_symbols, layer_name = virtual_layer, offset = kvo) addr = ntkrnlmp.get_symbol("MmProtectToValue").address - values = ntkrnlmp.object( - type_name = "array", offset = kvo + addr, subtype = ntkrnlmp.get_type("int"), count = 32) + values = ntkrnlmp.object(symbol = "array", offset = addr, subtype = ntkrnlmp.get_type("int"), count = 32) return values # type: ignore @classmethod diff --git a/volatility/framework/symbols/__init__.py b/volatility/framework/symbols/__init__.py index 15a4b3c4e..13c66c4d8 100644 --- a/volatility/framework/symbols/__init__.py +++ b/volatility/framework/symbols/__init__.py @@ -20,21 +20,14 @@ import collections import collections.abc -import enum import logging from typing import Any, Dict, Iterable, Iterator, TypeVar from volatility.framework import constants, exceptions, interfaces, objects +from volatility.framework.constants import SymbolType vollog = logging.getLogger(__name__) - -class SymbolType(enum.Enum): - TYPE = 1 - SYMBOL = 2 - ENUM = 3 - - SymbolSpaceReturnType = TypeVar("SymbolSpaceReturnType", interfaces.objects.Template, interfaces.symbols.SymbolInterface, Dict[str, Any]) diff --git a/volatility/framework/symbols/windows/extensions/__init__.py b/volatility/framework/symbols/windows/extensions/__init__.py index 242d55d7f..5ea03aa76 100644 --- a/volatility/framework/symbols/windows/extensions/__init__.py +++ b/volatility/framework/symbols/windows/extensions/__init__.py @@ -700,7 +700,7 @@ class _EPROCESS(generic.GenericIntelProcess, ExecutiveObject): layer_name = self.vol.native_layer_name, offset = kvo, native_layer_name = self.vol.native_layer_name) - session = ntkrnlmp.object(type_name = "_MM_SESSION_SPACE", offset = self.Session) + session = ntkrnlmp.object(symbol = "_MM_SESSION_SPACE", offset = self.Session, absolute = True) if session.has_member("SessionId"): return session.SessionId diff --git a/volatility/framework/symbols/windows/pdbconv.py b/volatility/framework/symbols/windows/pdbconv.py index f2d250e69..1bfb9febb 100644 --- a/volatility/framework/symbols/windows/pdbconv.py +++ b/volatility/framework/symbols/windows/pdbconv.py @@ -353,7 +353,7 @@ class PdbReader: if not tpi_layer: raise ValueError("No TPI stream available") module = self._context.module(module_name = tpi_layer.pdb_symbol_table, layer_name = tpi_layer.name, offset = 0) - header = module.object(type_name = "TPI_HEADER", offset = 0) + header = module.object(symbol = "TPI_HEADER", offset = 0) # Check the header if not (56 <= header.header_size < 1024): @@ -375,7 +375,7 @@ class PdbReader: type_index = 1 while tpi_layer.maximum_address - offset > 0: self._progress_callback(offset * 100 / tpi_layer.maximum_address, "Reading TPI layer") - length = module.object(type_name = length_type, offset = offset) + length = module.object(symbol = length_type, offset = offset) if not isinstance(length, int): raise ValueError("Non-integer length provided") offset += length_len @@ -401,7 +401,7 @@ class PdbReader: if not dbi_layer: raise ValueError("No DBI stream available") module = self._context.module(module_name = dbi_layer.pdb_symbol_table, layer_name = dbi_layer.name, offset = 0) - self._dbiheader = module.object(type_name = "DBI_HEADER", offset = 0) + self._dbiheader = module.object(symbol = "DBI_HEADER", offset = 0) if not self._dbiheader: raise ValueError("DBI Header could not be read") @@ -410,7 +410,7 @@ class PdbReader: dbg_hdr_offset = (self._dbiheader.vol.size + self._dbiheader.module_size + self._dbiheader.secconSize + self._dbiheader.secmapSize + self._dbiheader.filinfSize + self._dbiheader.tsmapSize + self._dbiheader.ecinfoSize) - self._dbidbgheader = module.object(type_name = "DBI_DBG_HEADER", offset = dbg_hdr_offset) + self._dbidbgheader = module.object(symbol = "DBI_DBG_HEADER", offset = dbg_hdr_offset) self._sections = [] self._omap_mapping = [] @@ -465,8 +465,8 @@ class PdbReader: while offset < max_address: self._progress_callback(offset * 100 / max_address, "Reading Symbol layer") - sym = module.object(type_name = "GLOBAL_SYMBOL", offset = offset) - leaf_type = module.object(type_name = "unsigned short", offset = sym.leaf_type.vol.offset) + sym = module.object(symbol = "GLOBAL_SYMBOL", offset = offset) + leaf_type = module.object(symbol = "unsigned short", offset = sym.leaf_type.vol.offset) name = None address = None if sym.segment < len(self._sections): @@ -500,7 +500,7 @@ class PdbReader: raise ValueError("No PDB Info Stream available") module = self._context.module( module_name = pdb_info_layer.pdb_symbol_table, layer_name = pdb_info_layer.name, offset = 0) - pdb_info = module.object(type_name = "PDB_INFORMATION", offset = 0) + pdb_info = module.object(symbol = "PDB_INFORMATION", offset = 0) self.metadata['windows']['pdb'] = { "GUID": self.convert_bytes_to_guid(pdb_info.GUID), @@ -726,7 +726,7 @@ class PdbReader: leaf_type.LF_CLASS, leaf_type.LF_CLASS_ST, leaf_type.LF_STRUCTURE, leaf_type.LF_STRUCTURE_ST, leaf_type.LF_INTERFACE ]: - structure = module.object(type_name = "LF_STRUCTURE", offset = offset + consumed) + structure = module.object(symbol = "LF_STRUCTURE", offset = offset + consumed) name_offset = structure.name.vol.offset - structure.vol.offset name, value, excess = self.determine_extended_value(leaf_type, structure.size, module, remaining - name_offset) @@ -735,7 +735,7 @@ class PdbReader: consumed += remaining result = leaf_type, name, structure elif leaf_type in [leaf_type.LF_MEMBER, leaf_type.LF_MEMBER_ST]: - member = module.object(type_name = "LF_MEMBER", offset = offset + consumed) + member = module.object(symbol = "LF_MEMBER", offset = offset + consumed) name_offset = member.name.vol.offset - member.vol.offset name, value, excess = self.determine_extended_value(leaf_type, member.offset, module, remaining - name_offset) @@ -744,7 +744,7 @@ class PdbReader: result = leaf_type, name, member consumed += member.vol.size + len(name) + 1 + excess elif leaf_type in [leaf_type.LF_ARRAY, leaf_type.LF_ARRAY_ST, leaf_type.LF_STRIDED_ARRAY]: - array = module.object(type_name = "LF_ARRAY", offset = offset + consumed) + array = module.object(symbol = "LF_ARRAY", offset = offset + consumed) name_offset = array.name.vol.offset - array.vol.offset name, value, excess = self.determine_extended_value(leaf_type, array.size, module, remaining - name_offset) array.size = value @@ -752,7 +752,7 @@ class PdbReader: result = leaf_type, name, array consumed += remaining elif leaf_type in [leaf_type.LF_ENUMERATE]: - enum = module.object(type_name = 'LF_ENUMERATE', offset = offset + consumed) + enum = module.object(symbol = 'LF_ENUMERATE', offset = offset + consumed) name_offset = enum.name.vol.offset - enum.vol.offset name, value, excess = self.determine_extended_value(leaf_type, enum.value, module, remaining - name_offset) enum.value = value @@ -760,20 +760,20 @@ class PdbReader: result = leaf_type, name, enum consumed += enum.vol.size + len(name) + 1 + excess elif leaf_type in [leaf_type.LF_ARGLIST, leaf_type.LF_ENUM]: - enum = module.object(type_name = "LF_ENUM", offset = offset + consumed) + enum = module.object(symbol = "LF_ENUM", offset = offset + consumed) name_offset = enum.name.vol.offset - enum.vol.offset name = self.parse_string(enum.name, leaf_type < leaf_type.LF_ST_MAX, size = remaining - name_offset) enum.name = name result = leaf_type, name, enum consumed += remaining elif leaf_type in [leaf_type.LF_UNION]: - union = module.object(type_name = "LF_UNION", offset = offset + consumed) + union = module.object(symbol = "LF_UNION", offset = offset + consumed) name_offset = union.name.vol.offset - union.vol.offset name = self.parse_string(union.name, leaf_type < leaf_type.LF_ST_MAX, size = remaining - name_offset) result = leaf_type, name, union consumed += remaining elif leaf_type in [leaf_type.LF_MODIFIER, leaf_type.LF_POINTER, leaf_type.LF_PROCEDURE]: - obj = module.object(type_name = leaf_type.lookup(), offset = offset + consumed) + obj = module.object(symbol = leaf_type.lookup(), offset = offset + consumed) result = leaf_type, None, obj consumed += remaining elif leaf_type in [leaf_type.LF_FIELDLIST]: @@ -789,7 +789,7 @@ class PdbReader: fields.append(subfield) result = leaf_type, None, fields elif leaf_type in [leaf_type.LF_BITFIELD]: - bitfield = module.object(type_name = "LF_BITFIELD", offset = offset + consumed) + bitfield = module.object(symbol = "LF_BITFIELD", offset = offset + consumed) result = leaf_type, None, bitfield consumed += remaining else: @@ -873,20 +873,20 @@ class PdbReader: # Set the offset at just after the previous size type offset = value.vol.offset + value.vol.data_format.length if sub_leaf_type in [leaf_type.LF_CHAR]: - value = module.object(type_name = 'char', offset = offset) + value = module.object(symbol = 'char', offset = offset) elif sub_leaf_type in [leaf_type.LF_SHORT]: - value = module.object(type_name = 'short', offset = offset) + value = module.object(symbol = 'short', offset = offset) elif sub_leaf_type in [leaf_type.LF_USHORT]: - value = module.object(type_name = 'unsigned short', offset = offset) + value = module.object(symbol = 'unsigned short', offset = offset) elif sub_leaf_type in [leaf_type.LF_LONG]: - value = module.object(type_name = 'long', offset = offset) + value = module.object(symbol = 'long', offset = offset) elif sub_leaf_type in [leaf_type.LF_ULONG]: - value = module.object(type_name = 'unsigned long', offset = offset) + value = module.object(symbol = 'unsigned long', offset = offset) else: raise TypeError("Unexpected extended value type") excess = value.vol.data_format.length # Updated the consume/offset counters - name = module.object(type_name = "string", offset = value.vol.offset + value.vol.data_format.length) + name = module.object(symbol = "string", offset = value.vol.offset + value.vol.data_format.length) name_str = self.parse_string(name, leaf_type < leaf_type.LF_ST_MAX, size = length - excess) return name_str, value, excess