From bef0689982935da9e9fb1c58737ced2a2386b0a0 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Mon, 4 Jan 2016 01:17:23 +0000 Subject: [PATCH] Add in constraints for dependency solving. --- .../framework/configuration/__init__.py | 9 +++++++-- volatility/framework/interfaces/layers.py | 7 ++++++- volatility/framework/interfaces/plugins.py | 2 ++ volatility/framework/layers/intel.py | 20 +++++++++++++++---- volatility/framework/layers/physical.py | 4 ++++ volatility/plugins/windows/pslist.py | 4 ++-- 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/volatility/framework/configuration/__init__.py b/volatility/framework/configuration/__init__.py index ceffea5c4..2e5e2ae87 100644 --- a/volatility/framework/configuration/__init__.py +++ b/volatility/framework/configuration/__init__.py @@ -28,7 +28,7 @@ class TranslationLayerRequirement(ConfigurationSchemaNode): """Class maintaining the limitations on what sort of address spaces are acceptable""" def __init__(self, name, description = None, default = None, - optional = False, layer_name = None): + optional = False, layer_name = None, constraints = None): """Constructs a Translation Layer Requirement The configuration option's value will be the name of the layer once it exists in the store @@ -37,12 +37,17 @@ class TranslationLayerRequirement(ConfigurationSchemaNode): :param layer_name: String detailing the expected name of the required layer, this can be None if it is to be randomly generated :return: """ - ConfigurationSchemaNode.__init__(name, description, default, optional) + ConfigurationSchemaNode.__init__(self, name, description, default, optional) + self._constraints = constraints or {} self._layer_name = layer_name # TODO: Add requirements: acceptable OSes from the address_space information # TODO: Add requirements: acceptable arches from the available layers + @property + def constraints(self): + return self._constraints + def validate(self, value, context): """Validate that the value is a valid layer name and that the layer adheres to the requirements""" if not isinstance(value, str): diff --git a/volatility/framework/interfaces/layers.py b/volatility/framework/interfaces/layers.py index f541cc9ff..e97350968 100644 --- a/volatility/framework/interfaces/layers.py +++ b/volatility/framework/interfaces/layers.py @@ -14,6 +14,8 @@ from abc import ABCMeta, abstractmethod, abstractproperty class DataLayerInterface(validity.ValidityRoutines, configuration.Configurable, metaclass = ABCMeta): """A Layer that directly holds data (and does not translate it""" + metadata = {"type": "interface"} + def __init__(self, context, name): self._check_type(name, str) self._check_type(context, context_module.ContextInterface) @@ -62,12 +64,15 @@ class DataLayerInterface(validity.ValidityRoutines, configuration.Configurable, pass @classmethod - @abstractmethod def get_schema(cls): """Returns a list of requirements for this type of layer""" + return [] class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta): + # Unfortunately class attributes can't easily be inheritted from parent classes + metadata = {"type": "interface"} + @abstractmethod def translate(self, offset): """Returns a tuple of (offset, layer) indicating the translation of input domain to the output range""" diff --git a/volatility/framework/interfaces/plugins.py b/volatility/framework/interfaces/plugins.py index 3db8cfff6..6e768c4e4 100644 --- a/volatility/framework/interfaces/plugins.py +++ b/volatility/framework/interfaces/plugins.py @@ -27,6 +27,8 @@ class PluginInterface(validity.ValidityRoutines, configuration_interface.Configu """Class that defines the interface all Plugins must maintain""" def __init__(self, context): + validity.ValidityRoutines.__init__(self) + configuration_interface.Configurable.__init__(self) self._check_type(context, context_interface.ContextInterface) self._context = context self.validate_inputs() diff --git a/volatility/framework/layers/intel.py b/volatility/framework/layers/intel.py index 4439b1777..3965afabe 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -13,9 +13,13 @@ from volatility.framework import interfaces, exceptions, configuration class Intel(interfaces.layers.TranslationLayerInterface): """Translation Layer for the Intel IA32 memory mapping""" - def __init__(self, context, name, physical_layer, page_map_offset): + metadata = {"type": "memory", + "architecture": "ia32" + } + + def __init__(self, context, name, page_map_offset, memory_layer, swao_layer): interfaces.layers.TranslationLayerInterface.__init__(self, context, name) - self._base_layer = physical_layer + self._base_layer = memory_layer self._page_map_offset = page_map_offset # All Intel address spaces work on 4096 byte pages self._page_size_in_bits = 12 @@ -126,8 +130,12 @@ class Intel(interfaces.layers.TranslationLayerInterface): @classmethod def get_schema(cls): - return [configuration.TranslationLayerRequirement(name = 'memory_layer', optional = False), - configuration.TranslationLayerRequirement(name = 'swap_layer', optional = True), + return [configuration.TranslationLayerRequirement(name = 'memory_layer', + constraints = {"type": "physical"}, + optional = False), + configuration.TranslationLayerRequirement(name = 'swap_layer', + constraints = {"type": "physical"}, + optional = True), configuration.IntRequirement(name = 'page_map_offset', optional = False)] @@ -149,6 +157,10 @@ class IntelPAE(Intel): class Intel32e(Intel): + metadata = {"type": "memory", + "architecture": "ia64" + } + def __init__(self, context, name, physical_layer, page_map_offset): Intel.__init__(self, context, name, physical_layer, page_map_offset) diff --git a/volatility/framework/layers/physical.py b/volatility/framework/layers/physical.py index 6980f53b2..871f14c00 100644 --- a/volatility/framework/layers/physical.py +++ b/volatility/framework/layers/physical.py @@ -12,6 +12,8 @@ from volatility.framework import interfaces, exceptions, configuration class BufferDataLayer(interfaces.layers.DataLayerInterface): """A DataLayer class backed by a buffer in memory, designed for testing and swift data access""" + metadata = {"type": "physical"} + def __init__(self, context, name, buffer): interfaces.layers.DataLayerInterface.__init__(self, context, name) self._buffer = self._check_type(buffer, bytes) @@ -51,6 +53,8 @@ class BufferDataLayer(interfaces.layers.DataLayerInterface): class FileLayer(interfaces.layers.DataLayerInterface): """a DataLayer backed by a file on the filesystem""" + metadata = {"type": "physical"} + def __init__(self, context, name, filename): interfaces.layers.DataLayerInterface.__init__(self, context, name) diff --git a/volatility/plugins/windows/pslist.py b/volatility/plugins/windows/pslist.py index b8f2e2be4..d4c129da8 100644 --- a/volatility/plugins/windows/pslist.py +++ b/volatility/plugins/windows/pslist.py @@ -7,8 +7,8 @@ class PsList(plugins.PluginInterface): def get_schema(cls): return [configuration.TranslationLayerRequirement(name = 'primary', description = 'Kernel Address Space', - os_type = 'windows', - architectures = None), + constraints = {"type": "memory", + "architecture": "ia32"}), configuration.IntRequirement(name = 'pid', description = "Process ID", optional = True),