From 3a28d7ae415e536fa97acf578bc4f553ecc6a9f7 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Mon, 19 Jan 2015 23:57:49 +0000 Subject: [PATCH] Refactor the context work, to use composable objects rather than inheritable classes. --- test_rig.py | 32 ++++----- volatility/framework/contexts/__init__.py | 84 +++++++--------------- volatility/framework/contexts/intel.py | 17 +++++ volatility/framework/contexts/physical.py | 19 +++++ volatility/framework/contexts/windows.py | 23 ++++++ volatility/framework/interfaces/context.py | 34 ++------- volatility/framework/interfaces/symbols.py | 11 ++- volatility/framework/symbols/__init__.py | 3 +- 8 files changed, 118 insertions(+), 105 deletions(-) create mode 100644 volatility/framework/contexts/intel.py create mode 100644 volatility/framework/contexts/physical.py create mode 100644 volatility/framework/contexts/windows.py diff --git a/test_rig.py b/test_rig.py index b6f177726..cc44ebab4 100644 --- a/test_rig.py +++ b/test_rig.py @@ -30,7 +30,12 @@ def test_symbols(): def utils_load_as(): - return framework.contexts.ContextWindowsX86()() + # TODO: This should hold the smarts for determining the physical layers and guessing at various values and so on + c = framework.contexts + factory = c.ContextFactory([c.physical.PhysicalContextModifier(None), + c.intel.IntelContextModifier(None), + c.windows.WindowsContextModifier(None)]) + return factory() def test_memory(): @@ -42,24 +47,24 @@ def test_memory(): ctx.symbol_space.append(ntkrnlmp) - base = layers.physical.FileLayer(ctx, 'data', filename = 'trig_data.bin') + base = layers.physical.FileLayer(ctx, 'physical', filename = 'trig_data.bin') ctx.memory.add_layer(base) - val = ctx.object('ntkrnlmp!TEST_POINTER', 'data', 0) + val = ctx.object('ntkrnlmp!TEST_POINTER', 'physical', 0) print(hex(val.point1.test1), val.point1.test2) def test_kdbgfind(): ctx = utils_load_as() - base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/xp-laptop-2005-06-25.img') + base = layers.physical.FileLayer(ctx, 'physical', filename = '/home/mike/memory/xp-laptop-2005-06-25.img') ctx.memory.add_layer(base) - intel = layers.intel.Intel(ctx, 'intel', 'data', page_map_offset = 0x39000) + intel = layers.intel.Intel(ctx, 'kernel', 'physical', page_map_offset = 0x39000) ctx.memory.add_layer(intel) def intel32(ctx): - base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/xp-laptop-2005-06-25.img') + base = layers.physical.FileLayer(ctx, 'physical', filename = '/home/mike/memory/xp-laptop-2005-06-25.img') ctx.memory.add_layer(base) - intel = layers.intel.Intel(ctx, 'intel', 'data', page_map_offset = 0x39000) + intel = layers.intel.Intel(ctx, 'kernel', 'physical', page_map_offset = 0x39000) x = [0x823c87c0, 0x81fdf020, 0x81f5a3b8, 0x81f8eb10, 0x820e0da0, 0x82199668, 0x81fa5aa0, 0x81fa8650, 0x81faba78, 0x81fa8240, 0x81f8dda0, 0x81f6e7e8, 0x81f9a670, 0x81f5f020, 0x8202bda0, 0x82113c48, 0x81f67500, 0x81f6ca90, 0x820dd588, 0x82025608, 0x81faf280, 0x821125d0, 0x82076558, 0x81f68518, 0x82059da0, 0x81f6db28, 0x82021a78, @@ -70,9 +75,9 @@ def intel32(ctx): def intelpae(ctx): - base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/private/jon-fres.dmp') + base = layers.physical.FileLayer(ctx, 'physical', filename = '/home/mike/memory/private/jon-fres.dmp') ctx.memory.add_layer(base) - intel = layers.intel.IntelPAE(ctx, 'intel', 'data', page_map_offset = 0x319000) + intel = layers.intel.IntelPAE(ctx, 'intel', 'physical', page_map_offset = 0x319000) x = [0x81bcc830, 0x81989940, 0x81915020, 0x8192ad18, 0x818fa7b8, 0x818f6da0, 0x818d1020, 0x818b2878, 0x8189f180, 0x8188db58, 0x81884a40, 0x818766b0, 0x8185a948, 0x8183ad70, 0x81826020, 0x818a64c8, 0x81818020, 0x81800020, 0x817ff460, 0x817eb020, 0x817e9020, 0x817a62a8, 0x817a4b28, 0x81865020, 0x817972c0] @@ -82,7 +87,7 @@ def intelpae(ctx): def intel32e(ctx): base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/private/ikelos-winxpsp2-x64.dmp') ctx.memory.add_layer(base) - intel = layers.intel.Intel32e(ctx, 'intel', 'data', page_map_offset = 0x3c3000) + intel = layers.intel.Intel32e(ctx, 'kernel', 'data', page_map_offset = 0x3c3000) x = [0xfffffadffa517c20, 0xfffffadffa2c9510, 0xfffffadffb16a660, 0xfffffadff9d77c20, 0xfffffadffb0fe040, 0xfffffadffb0f2040, 0xfffffadffb0c2040, 0xfffffadffb0b7c20, 0xfffffadffb087c20, 0xfffffadffb06a760, 0xfffffadffb039c20, 0xfffffadffb02c040, 0xfffffadffafe9c20, 0xfffffadffafa7040, 0xfffffadffaf2e040, @@ -113,14 +118,9 @@ def test_translation(): def test_plugin(): ctx = utils_load_as() - base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/private/jon-fres.dmp') - ctx.add_layer(base) - intel = layers.intel.IntelPAE(ctx, 'intel', 'data', page_map_offset = 0x319000) - ctx.add_layer(intel) - import volatility.plugins.windows.pslist as pslist - eproc = pslist.PsList.kernel_process_from_physical_process(ctx, 'data', 'intel', 0x192ad18) + eproc = pslist.PsList.kernel_process_from_physical_process(ctx, 'physical', 'kernel', 0x192ad18) for proc in eproc.ActiveProcessLinks: print(proc.UniqueProcessId) diff --git a/volatility/framework/contexts/__init__.py b/volatility/framework/contexts/__init__.py index 7dc249327..081ade20c 100644 --- a/volatility/framework/contexts/__init__.py +++ b/volatility/framework/contexts/__init__.py @@ -1,71 +1,35 @@ +from volatility.framework import validity +from volatility.framework.symbols import native import volatility -from volatility.framework import layers -from volatility.framework.symbols import vtypes, native, windows + __author__ = 'mike' -from volatility.framework import interfaces +from volatility.framework.contexts import intel, physical, windows -class ContextPhysicalLoaderInterface(interfaces.context.ContextFactoryInterface): - def construct_physical_layers(self, context): - # TODO: Add in the physical layer automagic to determine the layering - # Ideally allow for the plugin to specify the layering, but if not then guess at the best one - base = layers.physical.FileLayer(context, 'data', filename = '/home/mike/memory/private/jon-fres.dmp') - context.add_layer(base) +class ContextFactory(validity.ValidityRoutines, list): + """Class to establish and load the appropriate components of the context for a given operating system""" + + def __setitem__(self, key, value): + self._type_check(value) + super(ContextFactory, self).__setitem__(key, value) + + def get_config_options(self): + """Returns all the possible configuration options that might be required for this particular ContextFactory""" + # TODO: Chainmap the options from each component + for modifier in self: + modifier.get_config_options() -### NATIVE TYPES + def __call__(self): + """Constructs a standard context based on the architecture information -class Context32Bit(ContextPhysicalLoaderInterface): - def construct_context(self): - """Creates a base context with the 32-bit NativeTables""" - native_list = native.x86NativeTable - return volatility.framework.Context(native_list) + Returns a new context with all appropriate modifications (symbols, layers, etc) + """ + context = volatility.framework.Context(native.x86NativeTable) + for modifier in self: + modifier(context = context) + return context -class Context64Bit(ContextPhysicalLoaderInterface): - def construct_context(self): - """Creates a base context with the 32-bit NativeTables""" - native_list = native.x64NativeTable - return volatility.framework.Context(native_list) - - -### INTEL SPACES - -class ContextIntel(Context32Bit): - def construct_architecture(self, context): - # TODO: Determine the DTB - intel = layers.intel.Intel(context, 'kernel', 'data', page_map_offset = 0x319000) - context.add_layer(intel) - - -class ContextIntelPAE(Context32Bit): - def construct_architecture(self, context): - # TODO: Determine the DTB - intel = layers.intel.IntelPAE(context, 'kernel', 'data', page_map_offset = 0x319000) - context.add_layer(intel) - - -class ContextIntelX64(Context64Bit): - def construct_architecture(self, context): - # TODO; Determine the DTB - intel = layers.intel.Intel32e(context, 'kernel', 'data', page_map_offset = 0x319000) - context.add_layer(intel) - - -### Operating Systems - -class ContextWindowsX86(ContextIntel): - # TODO: Only import the vtypes during init - def __init__(self): - from volatility.framework import xp_sp2_x86_vtypes - - self._virtual_types = xp_sp2_x86_vtypes.ntkrnlmp_types - - def construct_os_symbols(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/contexts/intel.py b/volatility/framework/contexts/intel.py new file mode 100644 index 000000000..5168468bd --- /dev/null +++ b/volatility/framework/contexts/intel.py @@ -0,0 +1,17 @@ +from volatility.framework import interfaces, layers + +__author__ = 'mike' + + +class IntelContextModifier(interfaces.context.ContextModifierInterface): + def __init__(self, config): + pass + + @classmethod + def get_config_options(cls): + pass + + def __call__(self, context): + # TODO: Attempt to determine whether the image is 32, PAE or x64 (although the context must already know whether it is x64) + intel = layers.intel.IntelPAE(context, 'kernel', 'physical', page_map_offset = 0x319000) + context.add_layer(intel) diff --git a/volatility/framework/contexts/physical.py b/volatility/framework/contexts/physical.py new file mode 100644 index 000000000..9aaf8f327 --- /dev/null +++ b/volatility/framework/contexts/physical.py @@ -0,0 +1,19 @@ +from volatility.framework import interfaces, layers + +__author__ = 'mike' + + +class PhysicalContextModifier(interfaces.context.ContextModifierInterface): + def __init__(self, filename): + self.filename = '/home/mike/memory/private/jon-fres.dmp' + + @classmethod + def get_config_options(cls): + pass + + def __call__(self, context): + # TODO: Add in the physical layer automagic to determine the layering + # Ideally allow for the plugin to specify the layering, but if not then guess at the best one + base = layers.physical.FileLayer(context, 'physical', filename = self.filename) + context.add_layer(base) + diff --git a/volatility/framework/contexts/windows.py b/volatility/framework/contexts/windows.py new file mode 100644 index 000000000..3ff5b4dfe --- /dev/null +++ b/volatility/framework/contexts/windows.py @@ -0,0 +1,23 @@ +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, config): + from volatility.framework import xp_sp2_x86_vtypes + + self._virtual_types = xp_sp2_x86_vtypes.ntkrnlmp_types + + @classmethod + def get_config_options(cls): + pass + + def __call__(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/context.py b/volatility/framework/interfaces/context.py index 67af42ff9..1e3640ffe 100644 --- a/volatility/framework/interfaces/context.py +++ b/volatility/framework/interfaces/context.py @@ -45,32 +45,12 @@ class ContextInterface(object, metaclass = ABCMeta): """ -class ContextFactoryInterface(object, metaclass = ABCMeta): - """Class to establish and load the appropriate components of the context for a given operating system""" - - def __call__(self): - """Constructs a standard context based on the architecture information - - The context is modified - """ - context = self.construct_context() - self.construct_physical_layers(context) - self.construct_architecture(context) - self.construct_os_symbols(context) - return context +class ContextModifierInterface(object, metaclass = ABCMeta): + @classmethod + @abstractmethod + def get_config_options(cls): + """Returns all the options that might need to be passed to modify the context""" @abstractmethod - def construct_context(self): - """Returns a context based on some native types""" - - @abstractmethod - def construct_physical_layers(self, context): - """Adds a 'physical' layer to the context that should be used by the architecture, and any additional layers that might be usable by the architecture""" - - @abstractmethod - def construct_architecture(self, context): - """Applies the architecture mapping layer, using the primary 'physical' layer and any other layers it can additionally make use of""" - - @abstractmethod - def construct_os_symbols(self, context): - """Add the appropriate symbols for the operating system""" + def __call__(self, context): + """Modifies the context in place""" diff --git a/volatility/framework/interfaces/symbols.py b/volatility/framework/interfaces/symbols.py index 346af4f42..c58ce1e11 100644 --- a/volatility/framework/interfaces/symbols.py +++ b/volatility/framework/interfaces/symbols.py @@ -15,7 +15,7 @@ class SymbolTableInterface(validity.ValidityRoutines): if name: self._type_check(name, str) self.name = name or None - self._native_structures = native_structures + self.natives = native_structures # ## Required Constant symbol functions @@ -52,6 +52,15 @@ class SymbolTableInterface(validity.ValidityRoutines): """Returns None or a symbol_space for handling space specific native types""" return self._native_structures + @natives.setter + def natives(self, value): + """Checks the natives value and then applies it internally + + WARNING: This allows changing the underlying size of all the other structures referenced in the symbolspace + """ + self._type_check(value, NativeTableInterface) + self._native_structures = value + # ## Functions for overriding classes def set_structure_class(self, name, clazz): diff --git a/volatility/framework/symbols/__init__.py b/volatility/framework/symbols/__init__.py index 16b428812..fbb13ef3b 100644 --- a/volatility/framework/symbols/__init__.py +++ b/volatility/framework/symbols/__init__.py @@ -7,6 +7,7 @@ Created on 7 Feb 2013 import collections from volatility.framework import objects, interfaces, exceptions +from volatility.framework.symbols import native, vtypes class SymbolType(object): @@ -100,7 +101,7 @@ class SymbolSpace(collections.Mapping): if child.vol.structure_name not in self._resolved: traverse_list.append(child.vol.structure_name) self._resolved[child.vol.structure_name] = self._weak_resolve(SymbolType.STRUCTURE, - child.vol.structure_name) + child.vol.structure_name) # Stash the replacement replacements.add((traverser, child)) elif child.children: