mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-25 11:04:52 +02:00
Initial attempt at cleaning up the API
Context.object accepts a template or a string name (and now a type flag). Module.object only accepts a string (because a template already has most of the stuff built in and might as well be passed to the Context.object constructor). The gotcha here is the absolute flag, which must now be set appropriately in all cases *except* where the module is constructed with an offset of 0 (whereby it will have no impact).
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"""
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user