diff --git a/volatility/framework/plugins/windows/poolscanner.py b/volatility/framework/plugins/windows/poolscanner.py index 4c4f9744d..e2ee83ab5 100644 --- a/volatility/framework/plugins/windows/poolscanner.py +++ b/volatility/framework/plugins/windows/poolscanner.py @@ -85,11 +85,11 @@ class PoolHeaderScanner(interfaces.layers.ScannerInterface): if constraint.page_type is not None: checks_pass = False - if (constraint.page_type & PoolType.FREE) and header.PoolType == 0: + if (constraint.page_type & PoolType.FREE) and header.is_free_pool(): checks_pass = True - elif (constraint.page_type & PoolType.PAGED) and header.PoolType % 2 == 0 and header.PoolType > 0: + elif (constraint.page_type & PoolType.NONPAGED) and header.is_nonpaged_pool(): checks_pass = True - elif (constraint.page_type & PoolType.NONPAGED) and header.PoolType % 2 == 1: + elif (constraint.page_type & PoolType.PAGED) and header.is_paged_pool: checks_pass = True if not checks_pass: @@ -202,6 +202,9 @@ class PoolScanner(plugins.PluginInterface): fallback_checks = [("_OBJECT_HEADER", "TypeIndex", True), ("_HANDLE_TABLE", "HandleCount", True)]) + is_vista_or_later = os_distinguisher(version_check = lambda x: x >= (6, 0), + fallback_checks = [("KdCopyDataBlock", None, True)]) + def _generator(self): symbol_table = self.config["nt_symbols"] @@ -445,13 +448,19 @@ class PoolScanner(plugins.PluginInterface): else: pool_header_json_filename = "poolheader-x86" + is_vista_or_later = cls.is_vista_or_later(context, symbol_table) + if is_vista_or_later: + class_type = extensions.pool.POOL_HEADER_VISTA + else: + class_type = extensions.pool.POOL_HEADER + new_table_name = intermed.IntermediateSymbolTable.create( context = context, config_path = configuration.path_join(context.symbol_space[symbol_table].config_path, "poolheader"), sub_path = "windows", filename = pool_header_json_filename, table_mapping = {'nt_symbols': symbol_table}, - class_types = {'_POOL_HEADER': extensions.pool.POOL_HEADER}) + class_types = {'_POOL_HEADER': class_type}) module = context.module(new_table_name, layer_name, offset = 0) return module diff --git a/volatility/framework/symbols/windows/__init__.py b/volatility/framework/symbols/windows/__init__.py index 1c376ac09..d932767fc 100644 --- a/volatility/framework/symbols/windows/__init__.py +++ b/volatility/framework/symbols/windows/__init__.py @@ -36,7 +36,10 @@ class WindowsKernelIntermedSymbols(intermed.IntermediateSymbolTable): # This doesn't exist in very specific versions of windows try: - self.set_type_class('_POOL_HEADER', pool.POOL_HEADER) + if self.get_type("_POOL_TRACKER_BIG_PAGES").has_member("PoolType"): + self.set_type_class('_POOL_HEADER', pool.POOL_HEADER_VISTA) + else: + self.set_type_class('_POOL_HEADER', pool.POOL_HEADER) except ValueError: pass diff --git a/volatility/framework/symbols/windows/extensions/pool.py b/volatility/framework/symbols/windows/extensions/pool.py index 6db6b0b70..c169b2d8f 100644 --- a/volatility/framework/symbols/windows/extensions/pool.py +++ b/volatility/framework/symbols/windows/extensions/pool.py @@ -165,6 +165,29 @@ class POOL_HEADER(objects.StructType): pass return headers, sizes + def is_free_pool(self): + return self.PoolType == 0 + + def is_paged_pool(self): + return self.PoolType % 2 == 0 and self.PoolType > 0 + + def is_nonpaged_pool(self): + return self.PoolType % 2 == 1 + + +class POOL_HEADER_VISTA(POOL_HEADER): + """A kernel pool allocation header, updated for Vista and later. + + Exists at the base of the allocation and provides a tag that we can + scan for. + """ + + def is_paged_pool(self): + return self.PoolType % 2 == 1 + + def is_nonpaged_pool(self): + return self.PoolType % 2 == 0 and self.PoolType > 0 + class POOL_TRACKER_BIG_PAGES(objects.StructType): """A kernel big page pool tracker."""