From ca61cf10b967e4d13a626654deea5be0129d5005 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 14 Aug 2016 21:28:43 +0100 Subject: [PATCH] Refactor the context back into the ConfigurableInterface. This also adds support for manually constructed configurables to populate the config tree in the current context. I'm still toying around with this though, I need to figure out what to do with optional values and think the whole thing through to make sure it's worthwhile. --- .../framework/interfaces/configuration.py | 20 ++++++++++++++++--- volatility/framework/interfaces/layers.py | 3 +-- volatility/framework/interfaces/plugins.py | 11 +--------- volatility/framework/layers/intel.py | 5 +++++ volatility/framework/layers/physical.py | 6 ++++++ volatility/plugins/windows/pslist.py | 3 +++ 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/volatility/framework/interfaces/configuration.py b/volatility/framework/interfaces/configuration.py index d6885fd4a..ac18d9e13 100644 --- a/volatility/framework/interfaces/configuration.py +++ b/volatility/framework/interfaces/configuration.py @@ -2,6 +2,7 @@ import sys from abc import ABCMeta, abstractmethod from volatility.framework import validity +from volatility.framework.interfaces.context import ContextInterface __author__ = 'mike' @@ -166,17 +167,30 @@ class ConstructableRequirementInterface(RequirementInterface): return obj -class ConfigurableInterface(validity.ValidityRoutines): +class ConfigurableInterface(validity.ValidityRoutines, metaclass = ABCMeta): """Class to allow objects to have requirements and read configuration data from the context config tree""" - def __init__(self, config_path): + def __init__(self, context, config_path): """Basic initializer that allows configurables to access their own config settings""" super().__init__() + self._context = self._check_type(context, ContextInterface) self._config_path = self._check_type(config_path, str) + @property + def context(self): + return self._context + + @property + def config(self): + return self._context.config.branch(self._config_path) + + @abstractmethod + def update_configuration(self): + """Ensures that if the class has been created, its configuration is correct""" + @classmethod def get_requirements(cls): - """Returns a list of RequirementInterface objects required by this object""" + """Returns a list of RequirementInterface objects required by this object""" return [] @classmethod diff --git a/volatility/framework/interfaces/layers.py b/volatility/framework/interfaces/layers.py index 8e37cd266..a6cff8a1f 100644 --- a/volatility/framework/interfaces/layers.py +++ b/volatility/framework/interfaces/layers.py @@ -68,8 +68,7 @@ class DataLayerInterface(configuration.ConfigurableInterface, validity.ValidityR provides = {"type": "interface"} def __init__(self, context, config_path, name): - super().__init__(config_path) - self._context = context + super().__init__(context, config_path) self._check_type(name, str) self._name = name diff --git a/volatility/framework/interfaces/plugins.py b/volatility/framework/interfaces/plugins.py index b2fa10901..401ab04ac 100644 --- a/volatility/framework/interfaces/plugins.py +++ b/volatility/framework/interfaces/plugins.py @@ -26,18 +26,9 @@ class PluginInterface(configuration_interface.ConfigurableInterface, validity.Va """Class that defines the interface all Plugins must maintain""" def __init__(self, context, config_path): - super().__init__(config_path) - self._context = self._check_type(context, context_interface.ContextInterface) + super().__init__(context, config_path) # self.validate() - @property - def context(self): - return self._context - - @property - def config(self): - return self._context.config.branch(self._config_path) - @classmethod def get_requirements(cls): """Returns a list of Requirement objects for this plugin""" diff --git a/volatility/framework/layers/intel.py b/volatility/framework/layers/intel.py index 944412161..b7afb1fc0 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -148,6 +148,11 @@ class Intel(interfaces.layers.TranslationLayerInterface): requirements.IntRequirement(name = 'page_map_offset', optional = False)] + def update_configuration(self): + self.config["class"] = self.__class__.__name__ + self.config["memory_layer"] = self._base_layer + self.config["page_map_offset"] = self._page_map_offset + class IntelPAE(Intel): """Class for handling Physical Address Extensions for Intel architectures""" diff --git a/volatility/framework/layers/physical.py b/volatility/framework/layers/physical.py index f117afba8..963cfa8e4 100644 --- a/volatility/framework/layers/physical.py +++ b/volatility/framework/layers/physical.py @@ -56,6 +56,9 @@ class BufferDataLayer(interfaces.layers.DataLayerInterface): return [requirements.BytesRequirement(name = 'buffer', description = "The direct bytes to interact with", optional = False)] + def update_configuration(self): + self.config["buffer"] = self._buffer + class FileLayer(interfaces.layers.DataLayerInterface): """a DataLayer backed by a file on the filesystem""" @@ -137,3 +140,6 @@ class FileLayer(interfaces.layers.DataLayerInterface): @classmethod def get_requirements(cls): return [requirements.StringRequirement(name = 'filename', optional = False)] + + def update_configuration(self): + self.config['filename'] = self._filename diff --git a/volatility/plugins/windows/pslist.py b/volatility/plugins/windows/pslist.py index c21b8d0aa..0e56bbc43 100644 --- a/volatility/plugins/windows/pslist.py +++ b/volatility/plugins/windows/pslist.py @@ -16,6 +16,9 @@ class PsList(plugins.PluginInterface): requirements.IntRequirement(name = 'offset', description = 'Virtual address of any process')] + def update_configuration(self): + """No operation since all values provided by config/requirements initially""" + @staticmethod def kernel_process_from_physical_process(ctx, physical_layer, kernel_layer, offset): """Return a kernel process object from physical process data."""