From a76d71a7dc289cf69eb885acd478ec2c4296ffd4 Mon Sep 17 00:00:00 2001 From: Michael Ligh Date: Wed, 3 Oct 2018 21:51:11 -0500 Subject: [PATCH] move the functionality for getting an object's type into the _OBJECT_HEADER extension --- .../symbols/windows/extensions/__init__.py | 18 +++++++++ volatility/plugins/windows/handles.py | 40 +++++++------------ 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/volatility/framework/symbols/windows/extensions/__init__.py b/volatility/framework/symbols/windows/extensions/__init__.py index d84ff911d..6676092a6 100644 --- a/volatility/framework/symbols/windows/extensions/__init__.py +++ b/volatility/framework/symbols/windows/extensions/__init__.py @@ -426,6 +426,24 @@ class _OBJECT_HEADER(objects.Struct): """A class for the headers for executive kernel objects, which contains quota information, ownership details, naming data, and ACLs.""" + def get_object_type(self, type_map: dict, cookie: int = None) -> str: + """Across all Windows versions, the _OBJECT_HEADER embeds details on the type of + object (i.e. process, file) but the way its embedded differs between versions. + This API abstracts away those details.""" + + try: + # vista and earlier have a Type member + return self.Type.Name.String + except AttributeError: + # windows 7 and later have a TypeIndex, but windows 10 + # further encodes the index value with nt1!ObHeaderCookie + try: + type_index = ((self.vol.offset >> 8) ^ cookie ^ ord(self.TypeIndex)) & 0xFF + except AttributeError: + type_index = ord(self.TypeIndex) + + return type_map.get(type_index) + @property def NameInfo(self) -> interfaces.objects.ObjectInterface: if constants.BANG not in self.vol.type_name: diff --git a/volatility/plugins/windows/handles.py b/volatility/plugins/windows/handles.py index 0b652b85e..c869ca5ba 100644 --- a/volatility/plugins/windows/handles.py +++ b/volatility/plugins/windows/handles.py @@ -1,8 +1,9 @@ import logging +import typing import volatility.framework.interfaces.plugins as interfaces_plugins import volatility.plugins.windows.pslist as pslist -from volatility.framework import constants, exceptions, renderers +from volatility.framework import constants, exceptions, renderers, interfaces from volatility.framework.configuration import requirements from volatility.framework.objects import utility from volatility.framework.renderers import format_hints @@ -24,7 +25,6 @@ class Handles(interfaces_plugins.PluginInterface): super().__init__(*args, **kwargs) self._sar_value = None self._type_map = None - self._cookie = None self._level_mask = 7 @classmethod @@ -162,31 +162,20 @@ class Handles(interfaces_plugins.PluginInterface): return self._type_map - def object_type(self, object_header, type_map): - """Across all Windows versions, the _OBJECT_HEADER embeds details on the type of - object (i.e. process, file) but the way its embedded differs between versions. - This API abstracts away those details.""" + def find_cookie(self) -> typing.Optional[interfaces.objects.ObjectInterface]: + """Find the ObHeaderCookie value (if it exists)""" + + virtual = self.config["primary"] try: - # vista and earlier have a Type member - return object_header.Type.Name.String - except AttributeError: - # windows 7 and later have a TypeIndex, but windows 10 - # further encodes the index value with nt1!ObHeaderCookie - virtual = self.config["primary"] - try: - if self._cookie is None: - offset = self.context.symbol_space.get_symbol( - self.config["nt_symbols"] + constants.BANG + "ObHeaderCookie").address - kvo = self.context.memory[virtual].config['kernel_virtual_offset'] - self._cookie = self.context.object(self.config["nt_symbols"] + constants.BANG + "unsigned int", - virtual, offset = kvo + offset) + offset = self.context.symbol_space.get_symbol( + self.config["nt_symbols"] + constants.BANG + "ObHeaderCookie").address + except exceptions.SymbolError: + return None - type_index = ((object_header.vol.offset >> 8) ^ self._cookie ^ ord(object_header.TypeIndex)) & 0xFF - except AttributeError: - type_index = ord(object_header.TypeIndex) - - return type_map.get(type_index) + kvo = self.context.memory[virtual].config['kernel_virtual_offset'] + return self.context.object(self.config["nt_symbols"] + constants.BANG + "unsigned int", + virtual, offset = kvo + offset) def _make_handle_array(self, offset, level, depth = 0): """Parse a process' handle table and yield valid handle table @@ -255,6 +244,7 @@ class Handles(interfaces_plugins.PluginInterface): def _generator(self, procs): type_map = self.list_objects() + cookie = self.find_cookie() for proc in procs: @@ -269,7 +259,7 @@ class Handles(interfaces_plugins.PluginInterface): for entry in self.handles(object_table): try: - obj_type = self.object_type(entry, type_map) + obj_type = entry.get_object_type(type_map, cookie) if obj_type == None: continue