diff --git a/volatility/cli/__init__.py b/volatility/cli/__init__.py index 7383d3a9a..ae7468d88 100644 --- a/volatility/cli/__init__.py +++ b/volatility/cli/__init__.py @@ -6,6 +6,7 @@ import volatility.framework import volatility.plugins from volatility.cli import argparse_adapter from volatility.framework import interfaces, plugins, configuration, contexts +from volatility.framework.configuration import depresolver __author__ = 'mike' @@ -37,6 +38,9 @@ class CommandLine(object): parser.parse_args() # Determine the selected plugin + # Resolve the dependencies on that plugin + dldr = depresolver.DataLayerDependencyResolver(plugin) + # Translate the parsed args to a context configuration # Generate the layers from the arguments @@ -47,17 +51,6 @@ class CommandLine(object): # Construct and run the plugin plugin(context).run() - @staticmethod - def construct_translation_layer_factory(name, requirement): - """Create a factory that can provides requirements for the configuration - The factory also populates the - """ - factory = contexts.LayerFactory(name, requirement, - [contexts.physical.PhysicalContextModifier, - contexts.intel.IntelContextModifier, - contexts.windows.WindowsContextModifier]) - return factory - def collect_plugin_requirements(self, plugin): """Generates the requirements necessary for the plugin""" reqs = plugin.requirements() @@ -69,10 +62,6 @@ class CommandLine(object): if isinstance(req, configuration.TranslationLayerRequirement): # Choose an appropriate LayerFactory (add layer to the req.name so we don't blat the requirement itself namespace = interfaces.configuration.schema_name_join([plugin.__name__, req.name + "_layer"]) - factory = self.construct_translation_layer_factory(namespace, req) - req_mapping[req] = factory - for facreq in factory.requirements(): - context.config.add_item(facreq, namespace = namespace) else: context.config.add_item(req, plugin.__name__) return context, req_mapping diff --git a/volatility/framework/configuration/depresolver.py b/volatility/framework/configuration/depresolver.py index 39959019a..5b401fbe9 100644 --- a/volatility/framework/configuration/depresolver.py +++ b/volatility/framework/configuration/depresolver.py @@ -3,7 +3,7 @@ import volatility.framework.interfaces as interfaces import volatility.framework.validity as validity -class TranslationLayerDependencyResolver(validity.ValidityRoutines): +class DataLayerDependencyResolver(validity.ValidityRoutines): def __init__(self): # Maintain a cache of translation layers self.layer_cache = [] @@ -13,8 +13,16 @@ class TranslationLayerDependencyResolver(validity.ValidityRoutines): self.layer_cache.append(layer_class) def resolve_dependencies(self, configurable): - """Takes a configurable and produces a priority ordered tree of possible solutions to satisfy the various requirements""" + """Takes a configurable and produces a priority ordered tree of possible solutions to satisfy the various requirements + + The return should include each of the potential nodes (and requirements, including optional ones) allowing the UI + to decide the layer build-path and get all the necessary variables from the user for that path. + """ self._check_type(configurable, interfaces.configuration.Configurable) for requirement in configurable.get_schemas(): - pass + # If the requirement is a layer/configurable + # Recurse over it + print(requirement) + # Add all base-type requirements + # Add all optional base-type requirements in order diff --git a/volatility/framework/contexts/__init__.py b/volatility/framework/contexts/__init__.py index e128057cf..1de315b2a 100644 --- a/volatility/framework/contexts/__init__.py +++ b/volatility/framework/contexts/__init__.py @@ -1,56 +1,8 @@ -from volatility.framework import validity, interfaces, symbols, layers -from volatility.framework.contexts import intel, physical, windows -from volatility.framework.interfaces.context import ContextModifierInterface +from volatility.framework import interfaces, symbols, layers __author__ = 'mike' -class LayerFactory(validity.ValidityRoutines, list): - """Class to establish and load the appropriate components of the context for a given operating system""" - - def __init__(self, name, requirement, lst = None): - if lst is None: - lst = [] - self._check_type(lst, list) - self._check_type(name, str) - self._name = name - self._req = requirement - - validity.ValidityRoutines.__init__(self) - list.__init__(self, []) - for element in lst: - self.append(element) - - @property - def name(self): - return self._name - - def __setitem__(self, key, value): - self._check_class(value, ContextModifierInterface) - super(LayerFactory, self).__setitem__(key, value) - - def requirements(self): - """Returns all the possible configuration options that might be required for this particular LayerFactory""" - groups = [] - for index in range(len(self)): - modifier = self[index] - group = interfaces.configuration.ConfigurationSchemaGroup(modifier.__name__ + str(index)) - for req in modifier.requirements(): - group.add_item(req) - groups.append(group) - return groups - - def __call__(self, context): - """Constructs a standard context based on the architecture information - - Returns a new context with all appropriate modifications (symbols, layers, etc) - """ - for index in range(len(self)): - namespace = interfaces.configuration.schema_name_join([self.name, self[index].__name__ + str(index)]) - self[index](namespace).modify_context(context = context) - return context - - class Context(interfaces.context.ContextInterface): """Maintains the context within which to construct objects diff --git a/volatility/framework/contexts/intel.py b/volatility/framework/contexts/intel.py deleted file mode 100644 index ea8efdb00..000000000 --- a/volatility/framework/contexts/intel.py +++ /dev/null @@ -1,44 +0,0 @@ -from volatility.framework import interfaces, layers, configuration - -__author__ = 'mike' - - -class IntelContextModifier(interfaces.context.ContextModifierInterface): - @classmethod - def requirements(cls): - return [configuration.ChoiceRequirement(name = "architecture", - choices = ["auto", "pae", "32", "64"], - description = "Determines the memory image", - default = "auto"), - configuration.IntRequirement(name = "page_map_offset", - description = "Offset to the directory table base"), - configuration.StringRequirement(name = 'layer_name', - description = 'Name of the layer to be added to the memory space', - default = 'intel'), - configuration.TranslationLayerRequirement(name = 'physical_layer', - description = 'Physical Address Space', - os_type = 'windows', - architectures = None, - layer_type = 'physical'), - configuration.TranslationLayerRequirement(name = 'swap_layer', - description = "Layer name for the swap layer", - optional = True)] - - def modify_context(self, context): - # TODO: Attempt to determine whether the image is 32, PAE or x64 (although the context must already know whether it is x64) - config = self.config_get(context) - - if config.get('architecture') == 'pae': - layer = layers.intel.IntelPAE - elif config.get('architecture') == '32': - layer = layers.intel.Intel - elif config.get('architecture') == '64': - layer = layers.intel.Intel32e - else: - # TODO: Add automagic here - layer = layers.intel.IntelPAE - - intel = layer(context, config.get_value('layer_name'), - config.get_value('physical_layer').name, - page_map_offset = config.get_value('page_map_offset')) - context.add_layer(intel) diff --git a/volatility/framework/contexts/physical.py b/volatility/framework/contexts/physical.py deleted file mode 100644 index da69ef8b3..000000000 --- a/volatility/framework/contexts/physical.py +++ /dev/null @@ -1,22 +0,0 @@ -from volatility.framework import interfaces, layers, configuration - -__author__ = 'mike' - - -class PhysicalContextModifier(interfaces.context.ContextModifierInterface): - @classmethod - def requirements(cls): - return [configuration.StringRequirement(name = 'location', - description = 'URL to the physical address space', - default = '/home/mike/memory/jon-fres.dmp'), - configuration.StringRequirement(name = 'layer_name', - description = 'Layer name for the physical space', - default = 'physical')] - - def modify_context(self, context): - # Ideally allow for the plugin to specify the layering, but if not then guess at the best one - modconfig = self.config_get(context) - base = layers.physical.FileLayer(context, - modconfig.get_value('layer_name'), - filename = modconfig.get_value('location')) - context.add_layer(base) diff --git a/volatility/framework/contexts/windows.py b/volatility/framework/contexts/windows.py deleted file mode 100644 index d509f8cbb..000000000 --- a/volatility/framework/contexts/windows.py +++ /dev/null @@ -1,24 +0,0 @@ -from volatility.framework import interfaces -from volatility.framework.symbols import vtypes, windows - -__author__ = 'mike' - - -class WindowsContextModifier(interfaces.context.ContextModifierInterface): - # TODO: Only import the vtypes only when necessary - def __init__(self, namespace): - interfaces.context.ContextModifierInterface.__init__(namespace) - from volatility.framework import xp_sp2_x86_vtypes - - self._virtual_types = xp_sp2_x86_vtypes.ntkrnlmp_types - - @classmethod - def requirements(cls): - return [] - - def modify_context(self, context): - virtual_types = self._virtual_types - ntkrnlmp = vtypes.VTypeSymbolTable('ntkrnlmp', virtual_types, context.symbol_space.natives) - ntkrnlmp.set_structure_class('_ETHREAD', windows._ETHREAD) - ntkrnlmp.set_structure_class('_LIST_ENTRY', windows._LIST_ENTRY) - context.symbol_space.append(ntkrnlmp) diff --git a/volatility/framework/interfaces/configuration.py b/volatility/framework/interfaces/configuration.py index ec8315cfa..0a82edd27 100644 --- a/volatility/framework/interfaces/configuration.py +++ b/volatility/framework/interfaces/configuration.py @@ -76,7 +76,7 @@ class ConfigurationSchemaNode(validity.ValidityRoutines): """ -class Configurable(metaclass = ABCMeta): +class Configurable(object, metaclass = ABCMeta): """Class to allow objects to have requirements and populate the context config tree""" @classmethod diff --git a/volatility/framework/interfaces/context.py b/volatility/framework/interfaces/context.py index a5d082859..ade8cd207 100644 --- a/volatility/framework/interfaces/context.py +++ b/volatility/framework/interfaces/context.py @@ -6,6 +6,7 @@ Created on 6 May 2013 from abc import ABCMeta, abstractmethod, abstractproperty from volatility.framework import validity +from volatility.framework.interfaces import configuration class ContextInterface(object, metaclass = ABCMeta): @@ -51,7 +52,7 @@ class ContextInterface(object, metaclass = ABCMeta): """ -class ContextModifierInterface(validity.ValidityRoutines, metaclass = ABCMeta): +class ContextModifierInterface(validity.ValidityRoutines, configuration.Configurable, metaclass = ABCMeta): def __init__(self, namespace): """Initializes the context modifier @@ -63,12 +64,6 @@ class ContextModifierInterface(validity.ValidityRoutines, metaclass = ABCMeta): def config_get(self, context): return context.config[self.namespace] - @classmethod - @abstractmethod - def requirements(cls): - """Returns all the options that might need to be passed to modify the context""" - return [] - @abstractmethod def modify_context(self, context): """Modifies the context in place""" diff --git a/volatility/framework/interfaces/layers.py b/volatility/framework/interfaces/layers.py index 1eb08d5de..f541cc9ff 100644 --- a/volatility/framework/interfaces/layers.py +++ b/volatility/framework/interfaces/layers.py @@ -61,8 +61,8 @@ class DataLayerInterface(validity.ValidityRoutines, configuration.Configurable, (exceptions will be thrown using a DataLayer after destruction)""" pass - @abstractmethod @classmethod + @abstractmethod def get_schema(cls): """Returns a list of requirements for this type of layer""" diff --git a/volatility/framework/interfaces/plugins.py b/volatility/framework/interfaces/plugins.py index 763f5b550..3db8cfff6 100644 --- a/volatility/framework/interfaces/plugins.py +++ b/volatility/framework/interfaces/plugins.py @@ -5,8 +5,9 @@ Created on 6 May 2013 """ from abc import abstractmethod, ABCMeta -from volatility.framework import interfaces from volatility.framework import validity +from volatility.framework.interfaces import configuration as configuration_interface +from volatility.framework.interfaces import context as context_interface # @@ -22,11 +23,11 @@ from volatility.framework import validity # The plugin accepts the context and modifies as necessary # The plugin runs and produces a TreeGrid output -class PluginInterface(validity.ValidityRoutines, interfaces.configuration.Configurable, metaclass = ABCMeta): +class PluginInterface(validity.ValidityRoutines, configuration_interface.Configurable, metaclass = ABCMeta): """Class that defines the interface all Plugins must maintain""" def __init__(self, context): - self._check_type(context, interfaces.context.ContextInterface) + 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 691dfa0ad..4439b1777 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -7,16 +7,15 @@ Created on 7 May 2013 import math import struct -import volatility.framework.configuration as configuration -from volatility.framework import interfaces, exceptions +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, memory_layer, page_map_offset): + def __init__(self, context, name, physical_layer, page_map_offset): interfaces.layers.TranslationLayerInterface.__init__(self, context, name) - self._base_layer = memory_layer + self._base_layer = physical_layer self._page_map_offset = page_map_offset # All Intel address spaces work on 4096 byte pages self._page_size_in_bits = 12 @@ -135,8 +134,8 @@ class Intel(interfaces.layers.TranslationLayerInterface): class IntelPAE(Intel): """Class for handling Physical Address Extensions for Intel architectures""" - def __init__(self, context, name, memory_layer, page_map_offset): - Intel.__init__(self, context, name, memory_layer, page_map_offset) + def __init__(self, context, name, physical_layer, page_map_offset): + Intel.__init__(self, context, name, physical_layer, page_map_offset) # These can vary depending on the type of space self._entry_format = "