From d3a226d7a8b2bd0ed1c476641c18ef3d652cb38d Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 30 Jul 2016 01:52:44 +0100 Subject: [PATCH] Remove constraints as a thing, they'll need to come back, but in a different form. --- .../framework/configuration/requirements.py | 33 +------- .../framework/interfaces/configuration.py | 82 +++++++++++++++++++ volatility/framework/layers/intel.py | 4 - volatility/framework/layers/lime.py | 1 - volatility/plugins/windows/pslist.py | 11 +-- 5 files changed, 88 insertions(+), 43 deletions(-) diff --git a/volatility/framework/configuration/requirements.py b/volatility/framework/configuration/requirements.py index 61d2a303b..0d3faa85b 100644 --- a/volatility/framework/configuration/requirements.py +++ b/volatility/framework/configuration/requirements.py @@ -46,39 +46,10 @@ class BytesRequirement(InstanceRequirement): instance_type = bytes -class ClassRequirement(config_interface.RequirementInterface): - """Requires a specific class""" - - def __init__(self, *args, **kwargs): - config_interface.RequirementInterface.__init__(self, *args, **kwargs) - self._cls = None - - @property - def cls(self): - return self._cls - - def validate(self, context, config_path): - """Checks to see if a class can be recovered""" - value = self.config_value(context, config_path, None) - self._cls = None - if value is not None: - if "." in value: - # TODO: consider importing the prefix - module = sys.modules.get(value[:value.rindex(".")], None) - class_name = value[value.rindex(".") + 1:] - if hasattr(module, class_name): - self._cls = getattr(module, class_name) - else: - if value in globals(): - self._cls = globals()[value] - return self._cls is not None - - -class TranslationLayerRequirement(config_interface.RequirementInterface): +class TranslationLayerRequirement(config_interface.ConstructableRequirementInterface): """Class maintaining the limitations on what sort of address spaces are acceptable""" - def __init__(self, name, description = None, default = None, - optional = False, constraints = None): + def __init__(self, name, description = None, default = None, optional = False): """Constructs a Translation Layer Requirement The configuration option's value will be the name of the layer once it exists in the store diff --git a/volatility/framework/interfaces/configuration.py b/volatility/framework/interfaces/configuration.py index 9c8394a1a..8de7d53ad 100644 --- a/volatility/framework/interfaces/configuration.py +++ b/volatility/framework/interfaces/configuration.py @@ -83,6 +83,88 @@ class RequirementInterface(validity.ValidityRoutines, metaclass = ABCMeta): """ +class ClassRequirement(RequirementInterface): + """Requires a specific class""" + + def __init__(self, *args, **kwargs): + RequirementInterface.__init__(self, *args, **kwargs) + self._cls = None + + @property + def cls(self): + return self._cls + + def validate(self, context, config_path): + """Checks to see if a class can be recovered""" + value = self.config_value(context, config_path, None) + self._cls = None + if value is not None: + if "." in value: + # TODO: consider importing the prefix + module = sys.modules.get(value[:value.rindex(".")], None) + class_name = value[value.rindex(".") + 1:] + if hasattr(module, class_name): + self._cls = getattr(module, class_name) + else: + if value in globals(): + self._cls = globals()[value] + return self._cls is not None + + +class ConstructableRequirementInterface(RequirementInterface): + def __init__(self, *args, **kwargs): + RequirementInterface.__init__(self, *args, **kwargs) + self.add_requirement(ClassRequirement("class", "Class of the translation layer")) + self._current_class_requirements = set() + + @abstractmethod + def construct(self, context, config_path): + """Method for constructing within the context any required elements from subrequirements""" + + def _check_class(self, context, config_path): + """Method to check if the class Requirement is valid and if so populate the other requirements + (but no need to validate, since we're invalid already) + """ + class_req = self.requirements['class'] + subreq_config_path = path_join(config_path, self.name) + if class_req.validate(context, subreq_config_path): + # We have a class, and since it's validated we can construct our requirements from it + if issubclass(class_req.cls, ConfigurableInterface): + # In case the class has changed, clear out the old requirements + for old_req in self._current_class_requirements.copy(): + del self._requirements[old_req] + self._current_class_requirements.remove(old_req) + # And add the new ones + for requirement in class_req.cls.get_requirements(): + self._current_class_requirements.add(requirement.name) + self.add_requirement(requirement) + + def _construct_class(self, context, config_path, requirement_dict = None): + """Constructs the class, handing args and the subrequirements as parameters to __init__""" + cls = self.requirements["class"].cls + + # These classes all have a name property + # We could subclass this out as a NameableInterface, but it seems a little excessive + # FIXME: We can't test this, because importing the other interfaces causes all kinds of import loops + # if not issubclass(cls, [interfaces.layers.TranslationLayerInterface, + # interfaces.symbols.SymbolTableInterface]): + # return None + + if requirement_dict is None: + requirement_dict = {} + + node_config = context.config.branch(config_path) + # Construct the class + for req in cls.get_requirements(): + if req.name in node_config.data and req.name != "class": + requirement_dict[req.name] = node_config.data[req.name] + # Fulfillment must happen, exceptions happening here mean the requirements aren't correct + # and these need to be raised and fixed, rather than caught and ignored + obj = cls(**requirement_dict) + context.config[config_path] = obj.name + return obj + + class ConfigurableInterface(validity.ValidityRoutines): """Class to allow objects to have requirements and read configuration data from the context config tree""" diff --git a/volatility/framework/layers/intel.py b/volatility/framework/layers/intel.py index 2811882c7..f87ea5298 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -142,12 +142,8 @@ class Intel(interfaces.layers.TranslationLayerInterface): @classmethod def get_requirements(cls): return [requirements.TranslationLayerRequirement(name = 'memory_layer', - constraints = { - "type": "physical"}, optional = False), requirements.TranslationLayerRequirement(name = 'swap_layer', - constraints = { - "type": "physical"}, optional = True), requirements.IntRequirement(name = 'page_map_offset', optional = False)] diff --git a/volatility/framework/layers/lime.py b/volatility/framework/layers/lime.py index 6dc48a2fe..79d93728d 100644 --- a/volatility/framework/layers/lime.py +++ b/volatility/framework/layers/lime.py @@ -141,5 +141,4 @@ class LimeLayer(interfaces.layers.TranslationLayerInterface): @classmethod def get_requirements(cls): return [requirements.TranslationLayerRequirement(name = 'base_layer', - constraints = {"type": "physical"}, optional = False)] diff --git a/volatility/plugins/windows/pslist.py b/volatility/plugins/windows/pslist.py index 9311f1170..f51b726d3 100644 --- a/volatility/plugins/windows/pslist.py +++ b/volatility/plugins/windows/pslist.py @@ -1,20 +1,17 @@ import volatility.framework.interfaces.plugins as plugins from volatility.framework.configuration import requirements from volatility.framework.renderers import TreeGrid +from volatility.framework.symbols import vtypes +from volatility.framework.symbols.windows import xp_sp2_x86_vtypes class PsList(plugins.PluginInterface): @classmethod def get_requirements(cls): return [requirements.TranslationLayerRequirement(name = 'primary', - description = 'Kernel Address Space', - constraints = {"type": "memory", - "architecture": ["ia32", "pae"]}), + description = 'Kernel Address Space'), requirements.SymbolRequirement(name = "ntkrnlmp", - description = "Windows OS", - constraints = {"type": "symbols", - "os": "windows", - "architecture": ["ia32", "pae"]}), + description = "Windows OS"), requirements.IntRequirement(name = 'pid', description = "Process ID", optional = True),