From d667a68f97d27fcf0ee0ffa3da1de1c0bf88a937 Mon Sep 17 00:00:00 2001 From: Michael Ligh Date: Wed, 24 Oct 2018 12:16:09 -0500 Subject: [PATCH] switch Handles.list_objects() to a classmethod so it can be called from the poolscanner. pass the type_map into get_object() --- .../symbols/windows/extensions/__init__.py | 3 +- volatility/plugins/windows/handles.py | 61 +++++++++---------- volatility/plugins/windows/poolscanner.py | 7 +++ 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/volatility/framework/symbols/windows/extensions/__init__.py b/volatility/framework/symbols/windows/extensions/__init__.py index 6676092a6..f2e91595f 100644 --- a/volatility/framework/symbols/windows/extensions/__init__.py +++ b/volatility/framework/symbols/windows/extensions/__init__.py @@ -20,6 +20,7 @@ class _POOL_HEADER(objects.Struct): def get_object(self, type_name: str, + type_map: dict, native_layer_name: str = None, object_type: str = None) -> typing.Optional[interfaces.objects.ObjectInterface]: """Carve an object or data structure from a kernel pool allocation. @@ -55,7 +56,7 @@ class _POOL_HEADER(objects.Struct): object_header = mem_object.object_header() try: - object_type_string = object_header.NameInfo.Name.String + object_type_string = object_header.get_object_type(type_map) # FIXME: pass in the cookie if object_type_string == object_type: return mem_object else: diff --git a/volatility/plugins/windows/handles.py b/volatility/plugins/windows/handles.py index c869ca5ba..cff01f469 100644 --- a/volatility/plugins/windows/handles.py +++ b/volatility/plugins/windows/handles.py @@ -24,7 +24,6 @@ class Handles(interfaces_plugins.PluginInterface): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._sar_value = None - self._type_map = None self._level_mask = 7 @classmethod @@ -118,7 +117,8 @@ class Handles(interfaces_plugins.PluginInterface): return self._sar_value - def list_objects(self): + @classmethod + def list_objects(cls, context, layer_name, symbol_table): """List the executive object types (_OBJECT_TYPE) using the ObTypeIndexTable or ObpObjectTypes symbol (differs per OS). This method will be necessary for determining what type of @@ -127,40 +127,37 @@ class Handles(interfaces_plugins.PluginInterface): Note: The object type index map was hard coded into profiles in vol2, but we generate it dynamically now.""" - if self._type_map is None: + type_map = {} - self._type_map = {} + kvo = context.memory[layer_name].config['kernel_virtual_offset'] + ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) - virtual_layer = self.config['primary'] - kvo = self.context.memory[virtual_layer].config['kernel_virtual_offset'] - ntkrnlmp = self.context.module(self.config["nt_symbols"], layer_name = virtual_layer, offset = kvo) + try: + table_addr = ntkrnlmp.get_symbol("ObTypeIndexTable").address + except exceptions.SymbolError: + table_addr = ntkrnlmp.get_symbol("ObpObjectTypes").address + + ptrs = ntkrnlmp.object(type_name = "array", offset = kvo + table_addr, + subtype = ntkrnlmp.get_type("pointer"), + count = 100) + + for i, ptr in enumerate(ptrs): + # the first entry in the table is always null. break the + # loop when we encounter the first null entry after that + if i > 0 and ptr == 0: + break + objt = ptr.dereference().cast(symbol_table + constants.BANG + "_OBJECT_TYPE") try: - table_addr = ntkrnlmp.get_symbol("ObTypeIndexTable").address - except exceptions.SymbolError: - table_addr = ntkrnlmp.get_symbol("ObpObjectTypes").address + type_name = objt.Name.String + except exceptions.PagedInvalidAddressException: + vollog.log(constants.LOGLEVEL_VVV, + "Cannot access _OBJECT_HEADER.Name at {0:#x}".format(objt.Name.vol.offset)) + continue - ptrs = ntkrnlmp.object(type_name = "array", offset = kvo + table_addr, - subtype = ntkrnlmp.get_type("pointer"), - count = 100) + type_map[i] = type_name - for i, ptr in enumerate(ptrs): - # the first entry in the table is always null. break the - # loop when we encounter the first null entry after that - if i > 0 and ptr == 0: - break - objt = ptr.dereference().cast(self.config["nt_symbols"] + constants.BANG + "_OBJECT_TYPE") - - try: - type_name = objt.Name.String - except exceptions.PagedInvalidAddressException: - vollog.log(constants.LOGLEVEL_VVV, - "Cannot access _OBJECT_HEADER.Name at {0:#x}".format(objt.Name.vol.offset)) - continue - - self._type_map[i] = type_name - - return self._type_map + return type_map def find_cookie(self) -> typing.Optional[interfaces.objects.ObjectInterface]: """Find the ObHeaderCookie value (if it exists)""" @@ -243,7 +240,9 @@ class Handles(interfaces_plugins.PluginInterface): def _generator(self, procs): - type_map = self.list_objects() + type_map = self.list_objects(context = self.context, + layer_name = self.config["primary"], + symbol_table = self.config["nt_symbols"]) cookie = self.find_cookie() for proc in procs: diff --git a/volatility/plugins/windows/poolscanner.py b/volatility/plugins/windows/poolscanner.py index 021c0c791..4f952d58d 100644 --- a/volatility/plugins/windows/poolscanner.py +++ b/volatility/plugins/windows/poolscanner.py @@ -9,6 +9,7 @@ from volatility.framework.layers import scanners from volatility.framework.renderers import format_hints from volatility.framework.symbols import intermed from volatility.framework.symbols.windows import extensions +import volatility.plugins.windows.handles as handles vollog = logging.getLogger(__name__) @@ -79,6 +80,11 @@ class PoolScanner(plugins.PluginInterface): page_type = PoolType.PAGED | PoolType.NONPAGED | PoolType.FREE), ] + # get the object type map + type_map = handles.Handles.list_objects(context = self.context, + layer_name = self.config["primary"], + symbol_table = self.config["nt_symbols"]) + # FIXME: replace this lambda with a real function is_windows_10 = lambda: False @@ -97,6 +103,7 @@ class PoolScanner(plugins.PluginInterface): alignment = 8): mem_object = header.get_object(type_name = constraint.type_name, + type_map = type_map, object_type = constraint.object_type, native_layer_name = 'primary')