Fix up the DTB finder code and stick it all together.

This commit is contained in:
Mike Auty
2016-07-30 02:35:40 +01:00
parent 43aba96e3f
commit b92ccd771f
6 changed files with 62 additions and 35 deletions
+5 -7
View File
@@ -53,14 +53,15 @@ class CommandLine(object):
# UI fills in the config:
ctx = contexts.Context()
ctx.config["plugins.pslist.primary.class"] = "volatility.framework.layers.intel.Intel"
ctx.config["plugins.pslist.primary.class"] = "volatility.framework.layers.intel.IntelPAE"
ctx.config["plugins.pslist.primary.memory_layer.class"] = "volatility.framework.layers.physical.FileLayer"
ctx.config[
"plugins.pslist.primary.memory_layer.filename"] = "/run/media/mike/disk/memory/xp-laptop-2005-07-04-1430.img"
ctx.config["plugins.pslist.offset"] = 0x823c87c0
ctx.config["plugins.pslist.offset"] = 0x023c87c0
ctx.config["plugins.pslist.primary.memory_layer.class"] = "volatility.framework.layers.physical.FileLayer"
ctx.config["plugins.pslist.primary.memory_layer.filename"] = "/run/media/mike/disk/memory/private/jon-fres.dmp"
ctx.config["plugins.pslist.offset"] = 0x81bcc830
ctx.config["plugins.pslist.offset"] = 0x01bcc830
ctx.config["plugins.pslist.ntkrnlmp.class"] = "volatility.framework.symbols.windows.WindowsKernelVTypeSymbols"
ctx.config["plugins.pslist.ntkrnlmp.vtype_pymodule"] = "volatility.framework.symbols.windows.xp_sp2_x86_vtypes"
@@ -75,9 +76,6 @@ class CommandLine(object):
automagics = automagic.available()
automagic.run(automagics, ctx, plugin, "plugins")
import pdb
pdb.set_trace()
# Check all the requirements and/or go back to the automagic step
if not plugin.validate(ctx, config_path):
raise RuntimeError("Unable to validate the plugin configuration")
@@ -1,28 +1,31 @@
from volatility.framework.configuration import requirements
import logging
from volatility.framework.interfaces import automagic as automagic_interface, configuration as config_interface
vollog = logging.getLogger(__name__)
class ConstructLayers(automagic_interface.AutomagicInterface):
class ConstructionMagic(automagic_interface.AutomagicInterface):
"""Runs through the requirement tree and from the bottom up attempts to construct all TranslationLayerRequirements"""
priority = 10
def __call__(self, context, requirement, config_path):
print("Processing", config_path, requirement.name)
if not requirement.validate(context, config_path):
# Having called validate at the top level tells us both that we need to dig deeper
# but also ensures that TranslationLayerRequirements have got the correct subrequirements if their class is populated
success = True
subreq_config_path = config_interface.path_join(config_path, requirement.name)
for subreq in requirement.requirements.values():
subreq_config_path = config_interface.path_join(config_path, requirement.name)
self(context, subreq, subreq_config_path)
valid = subreq.validate(context, subreq_config_path)
# We want to traverse optional paths, so don't check until we've tried to validate
if not valid and not subreq.optional:
vollog.debug("Failed on requirement " + subreq.name)
success = False
if not success:
return False
elif isinstance(requirement, requirements.TranslationLayerRequirement):
elif isinstance(requirement, config_interface.ConstructableRequirementInterface):
# We know all the subrequirements are filled, so let's populate
requirement.construct(context, config_path)
return True
+44 -16
View File
@@ -1,4 +1,6 @@
from volatility.framework import automagic
from volatility.framework.configuration import requirements
from volatility.framework.interfaces import configuration as config_interface
if __name__ == "__main__":
import os
@@ -129,11 +131,16 @@ class SelfReferentialTest(object):
return response
class PageMapScanner(interfaces.layers.ScannerInterface):
def __call__(self, data, data_offset):
pass
class PageMapOffsetHelper(automagic_interface.AutomagicInterface):
priority = 20
def __init__(self):
self.tests = dict([(test.layer_type, test) for test in [DtbTest32bit(), DtbTest64bit(), DtbTestPae()]])
self.tests = [DtbTest32bit(), DtbTest64bit(), DtbTestPae()]
def branch_leave(self, node, config_path):
"""Ensure we're called on internal nodes as well as external"""
@@ -141,23 +148,44 @@ class PageMapOffsetHelper(automagic_interface.AutomagicInterface):
return True
def __call__(self, context, requirement, config_path):
useful = []
sub_config_path = config_interface.path_join(config_path, requirement.name)
if isinstance(requirement, requirements.TranslationLayerRequirement):
# Determine if a class has been chosen
# If a class hasn't been chosen, look through the underlying config for appropriate parameters
# If possible run scan and choose an appropriate class
# Once an appropriate class has been chosen, attempt to determine the page_map_offset value
pass
class_req = requirement.requirements["class"]
if not class_req.validate(context, sub_config_path):
# All the intel spaces require the same kind of parameters, so pick one for the requirements
context.config.branch(config_path)
automagic.run(context, layers.intel.Intel,
config_interface.path_join(config_path, requirement.name))
# hits = scan(self.context, memory_layer, useful)
# for test in useful:
# if hits.get(test.layer_type, []):
# self.context.config[prefix + "page_map_offset"] = hits[test.layer_type][0]
# else:
# # Delete the node rather than fixing the constraints,
# # since the requirements haven't changed, but some of the candidates are no longer valid
# # If the constraints were global across the tree, then tagging the constraints may be more useful
# del node.candidates[test.layer_type]
return True
# If a class hasn't been chosen, look through the underlying config for appropriate parameters
# If possible run scan and choose an appropriate class
pass
for test in self.tests:
if (test.layer_type.__module__ + "." + test.layer_type.__name__ ==
class_req.config_value(context, sub_config_path)):
useful.append(test)
print(repr(requirement.requirements))
# Determine if a class has been chosen
# Once an appropriate class has been chosen, attempt to determine the page_map_offset value
if ("memory_layer" in requirement.requirements and
requirement.requirements["memory_layer"].validate(context, sub_config_path)):
physical_layer = requirement.requirements["memory_layer"].config_value(context, sub_config_path)
# TODO: Convert to scanner framework
# context.memory[physical_layer].scan(context, scanner)
hits = scan(context, physical_layer, useful)
# TODO: At this point, we know the class, so ditch the other tests
for test in useful:
if hits.get(test.layer_type, []):
context.config[config_interface.path_join(sub_config_path, "page_map_offset")] = \
hits[test.layer_type][0]
requirement.construct(context, config_path)
else:
for subreq in requirement.requirements.values():
self(context, subreq, sub_config_path)
if __name__ == '__main__':
@@ -130,7 +130,9 @@ class SymbolRequirement(config_interface.ConstructableRequirementInterface):
if name in context.symbol_space:
raise ValueError("Symbol space already contains a SymbolTable by the same name")
args = {"name": name}
args = {"context": context,
"config_path": config_path,
"name": name}
config_path = config_interface.path_join(config_path, self.name)
if not all([subreq.validate(context, config_path) for subreq in self.requirements.values() if
@@ -10,8 +10,7 @@ class WindowsKernelVTypeSymbols(vtypes.VTypeSymbolTable):
def __init__(self, context, config_path, name, vtype_pymodule, vtype_variable):
# FIXME: Make natives another requirement, or in some way hand it in when building the vtype_table
vtypes.VTypeSymbolTable.__init__(self, name, vtype_pymodule, vtype_variable,
context.context.symbol_space.natives)
vtypes.VTypeSymbolTable.__init__(self, name, vtype_pymodule, vtype_variable, context.symbol_space.natives)
# Set-up windows specific types
self.set_type_class('_ETHREAD', extensions._ETHREAD)
+1 -4
View File
@@ -1,8 +1,6 @@
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):
@@ -37,10 +35,9 @@ class PsList(plugins.PluginInterface):
errors = 'replace')))
def run(self):
# Use the primary twice until we figure out how to specify base layers of a particular translation layer
eproc = self.kernel_process_from_physical_process(self.context,
self.config['primary'],
self.config['primary.memory_layer'],
self.config['primary'],
self.config['offset'])