diff --git a/volatility/framework/symbols/windows/__init__.py b/volatility/framework/symbols/windows/__init__.py index 0261268e1..3023eb25e 100644 --- a/volatility/framework/symbols/windows/__init__.py +++ b/volatility/framework/symbols/windows/__init__.py @@ -1,6 +1,7 @@ from volatility.framework.configuration import requirements from volatility.framework.symbols import intermed from volatility.framework.symbols.windows import extensions +from volatility.framework.symbols.windows.extensions import registry class WindowsKernelIntermedSymbols(intermed.IntermediateSymbolTable): @@ -14,7 +15,8 @@ class WindowsKernelIntermedSymbols(intermed.IntermediateSymbolTable): self.set_type_class('_LIST_ENTRY', extensions._LIST_ENTRY) self.set_type_class('_EPROCESS', extensions._EPROCESS) self.set_type_class('_UNICODE_STRING', extensions._UNICODE_STRING) - self.set_type_class('_CMHIVE', extensions._CMHIVE) + self.set_type_class('_CMHIVE', registry._CMHIVE) + self.set_type_class('_CM_KEY_NODE', registry._CM_KEY_NODE) @classmethod def get_requirements(cls): diff --git a/volatility/framework/symbols/windows/extensions/__init__.py b/volatility/framework/symbols/windows/extensions/__init__.py index 1fc1fd6bb..35e8470cc 100644 --- a/volatility/framework/symbols/windows/extensions/__init__.py +++ b/volatility/framework/symbols/windows/extensions/__init__.py @@ -1,6 +1,6 @@ import collections.abc -from volatility.framework import constants, exceptions, objects +from volatility.framework import constants, objects from volatility.framework.symbols import generic @@ -13,24 +13,6 @@ class _ETHREAD(objects.Struct): return self.ThreadsProcess.dereference(kernel_layer) -class _CMHIVE(objects.Struct): - @property - def helper_name(self): - """Determine a name for the hive. Note that some attributes are - unpredictably blank across different OS versions while others are populated, - so we check all possibilities and take the first one that's not empty""" - - for attr in ["FileFullPath", "FileUserName", "HiveRootPath"]: - try: - return getattr(self, attr).helper_string - except (AttributeError, exceptions.InvalidAddressException): - pass - - return None - - name = helper_name - - class _UNICODE_STRING(objects.Struct): @property def helper_string(self): diff --git a/volatility/framework/symbols/windows/extensions/registry.py b/volatility/framework/symbols/windows/extensions/registry.py new file mode 100644 index 000000000..d978bb3d5 --- /dev/null +++ b/volatility/framework/symbols/windows/extensions/registry.py @@ -0,0 +1,57 @@ +from volatility.framework import objects, constants, exceptions +from volatility.framework.layers.registry import RegistryHive + + +class _CMHIVE(objects.Struct): + @property + def name(self): + """Determine a name for the hive. Note that some attributes are + unpredictably blank across different OS versions while others are populated, + so we check all possibilities and take the first one that's not empty""" + + for attr in ["FileFullPath", "FileUserName", "HiveRootPath"]: + try: + return getattr(self, attr).String + except (AttributeError, exceptions.InvalidAddressException): + pass + + return None + + +class _CM_KEY_NODE(objects.Struct): + """Extension to allow traversal of registry keys""" + + @property + def subkeys(self): + 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): + subkey_node = hive.get_cell(self.SubKeyLists[index]) + if subkey_node.vol.type_name.endswith(constants.BANG + '_CM_KEY_INDEX'): + # 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 + # We could change the array type to a struct with both parts + subkey_node.List.count = subkey_node.Count * 2 + for key_offset in subkey_node.List[::2]: + yield hive.get_cell(key_offset) + else: + raise TypeError("Unexpected SubKeyList item") + + @property + def 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): + raise TypeError("CM_KEY_NODE was not instantiated on a RegistryHive layer") + child_list = hive.get_cell(self.ValueList.List) + child_list.count = self.ValueList.Count + for v in child_list: + if v != 0: + node = hive.get_cell(v) + if node.vol.type_name.endswith(constants.BANG + '_CM_KEY_VALUE'): + yield hive.get_cell(v) + + @property + def keyname(self): + return self.Name.cast("string", max_length = self.NameLength, encoding = "latin-1")