From 4fb24985eba88d7491ebfc9ab07111259c4a7614 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 8 Oct 2017 01:46:05 +0100 Subject: [PATCH] Add in standard registry walking to the regtest plugin. --- volatility/framework/layers/registry.py | 4 ++-- .../symbols/windows/extensions/registry.py | 19 +++++++++++++----- volatility/plugins/regtest.py | 20 +++++++++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/volatility/framework/layers/registry.py b/volatility/framework/layers/registry.py index 478372822..d8948e1f1 100644 --- a/volatility/framework/layers/registry.py +++ b/volatility/framework/layers/registry.py @@ -89,7 +89,7 @@ class RegistryHive(interfaces.layers.TranslationLayerInterface): depth = 0 found_key = [] while len(key_array) > 1 and node_key: - for subkey in node_key.subkeys: + for subkey in node_key.get_subkeys(): if subkey.keyname == key_array[depth]: node_key = subkey found_key, key_array = found_key + [key_array[0]], key_array[1:] @@ -105,7 +105,7 @@ class RegistryHive(interfaces.layers.TranslationLayerInterface): if not node: node = self.get_node(self.root_cell_offset) visitor(node) - for node in node.subkeys: + for node in node.get_subkeys(): self.visit_nodes(visitor, node) @staticmethod diff --git a/volatility/framework/symbols/windows/extensions/registry.py b/volatility/framework/symbols/windows/extensions/registry.py index 0fd2510de..a84be3134 100644 --- a/volatility/framework/symbols/windows/extensions/registry.py +++ b/volatility/framework/symbols/windows/extensions/registry.py @@ -21,12 +21,13 @@ class _CMHIVE(objects.Struct): class _CM_KEY_NODE(objects.Struct): """Extension to allow traversal of registry keys""" - @property - def subkeys(self): + def get_subkeys(self): + """Returns a list of the key nodes""" hive = self._context.memory[self.vol.layer_name] if not isinstance(hive, RegistryHive): raise TypeError("CM_KEY_NODE was not instantiated on a RegistryHive layer") for index in range(2): + # Use get_cell because it should *always* be a KeyIndex subkey_node = hive.get_cell(self.SubKeyLists[index]).u.KeyIndex # The keylist appears to include 4 bytes of key name after each value # We can either double the list and only use the even items, or @@ -35,8 +36,7 @@ class _CM_KEY_NODE(objects.Struct): for key_offset in subkey_node.List[::2]: yield hive.get_node(key_offset) - @property - def values(self): + def get_values(self): """Returns a list of the Value nodes for a key""" hive = self._context.memory[self.vol.layer_name] if not isinstance(hive, RegistryHive): @@ -50,5 +50,14 @@ class _CM_KEY_NODE(objects.Struct): yield node @property - def keyname(self): + def name(self): + """Since this is just a casting convenience, it can be a property""" return self.Name.cast("string", max_length = self.NameLength, encoding = "latin-1") + + def get_key_path(self): + reg = self._context.memory[self.vol.layer_name] + # Using the offset adds a significant delay (since it cannot be cached easily) + # if self.vol.offset == reg.get_node(reg.root_cell_offset).vol.offset: + if self.vol.offset == reg.root_cell_offset + 4: + return self.name + return reg.get_node(self.Parent).get_key_path() + '\\' + self.name diff --git a/volatility/plugins/regtest.py b/volatility/plugins/regtest.py index 872a4f918..f66dacf5d 100644 --- a/volatility/plugins/regtest.py +++ b/volatility/plugins/regtest.py @@ -1,8 +1,11 @@ +import datetime + import volatility.framework.interfaces.plugins as plugins from volatility.framework.configuration import requirements from volatility.framework.interfaces import configuration from volatility.framework.interfaces.configuration import HierarchicalDict from volatility.framework.layers.registry import RegistryHive +from volatility.framework.renderers import TreeGrid class RegTest(plugins.PluginInterface): @@ -23,6 +26,17 @@ class RegTest(plugins.PluginInterface): def update_configuration(self): """No operation since all values provided by config/requirements initially""" + def registry_walker(self, registry, node = None): + if not node: + node = registry.get_node(registry.root_cell_offset) + key_path = node.get_key_path() + unix_time = node.LastWriteTime.QuadPart // 10000000 + unix_time = unix_time - 11644473600 + + yield (key_path.count("\\"), (key_path, str(datetime.datetime.utcfromtimestamp(unix_time)))) + for node in node.get_subkeys(): + yield from self.registry_walker(registry, node) + def run(self): layer = self.context.memory[self.config['primary']] reg_config = HierarchicalDict({'hive_offset': 0xe1ca8210, @@ -33,5 +47,7 @@ class RegTest(plugins.PluginInterface): registry_config_path = configuration.path_join(self.config_path, 'registry') registry_layer = RegistryHive(self.context, registry_config_path, name = 'hive0', os = 'Windows') self.context.memory.add_layer(registry_layer) - root_node = registry_layer.get_cell(registry_layer.root_cell) - print([[y for y in x.values] for x in root_node.subkeys]) + + return TreeGrid(columns = [('Name', str), + ('Last Write Time', str)], + generator = self.registry_walker(registry_layer))