From 881d4e85e8cd7864a613e70240e2ef1c1415752e Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 31 Jan 2026 17:53:30 +0000 Subject: [PATCH 1/4] Add in intial support for locating windows 'banners' --- volatility3/framework/plugins/banners.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/volatility3/framework/plugins/banners.py b/volatility3/framework/plugins/banners.py index eea39206d..85a6f4862 100644 --- a/volatility3/framework/plugins/banners.py +++ b/volatility3/framework/plugins/banners.py @@ -4,10 +4,11 @@ import logging from typing import List -from volatility3.framework import interfaces, renderers, layers +from volatility3.framework import constants, interfaces, layers, renderers from volatility3.framework.configuration import requirements from volatility3.framework.layers import scanners from volatility3.framework.renderers import format_hints +from volatility3.framework.symbols.windows import pdbutil vollog = logging.getLogger(__name__) @@ -16,6 +17,7 @@ class Banners(interfaces.plugins.PluginInterface): """Attempts to identify potential linux banners in an image""" _required_framework_version = (2, 0, 0) + _version = (1, 1, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: @@ -42,6 +44,7 @@ class Banners(interfaces.plugins.PluginInterface): cls, context: interfaces.context.ContextInterface, layer_name: str ): """Identifies banners from a memory image""" + # Look for likely linux/mac banners layer = context.layers[layer_name] for offset in layer.scan( context=context, @@ -64,6 +67,25 @@ class Banners(interfaces.plugins.PluginInterface): format_hints.Hex(offset), str(data, encoding="latin-1", errors="?"), ) + yield from cls.locate_windows_banners(context, layer_name) + + @classmethod + def locate_windows_banners( + cls, context: interfaces.context.ContextInterface, layer_name: str + ): + layer = context.layers[layer_name] + kernel_pdb_names = [ + bytes(name + ".pdb", "utf-8") + for name in constants.windows.KERNEL_MODULE_NAMES + ] + for guid, age, pdb_name, offset in layer.scan( + context=context, + scanner=pdbutil.PdbSignatureScanner(kernel_pdb_names), + ): + yield ( + format_hints.Hex(offset), + f"{pdb_name.decode('latin-1')} - {guid}-{age}", + ) def run(self): return renderers.TreeGrid( From 1b58e7e25b319785a116c1d7bdbeafbda58a754e Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 31 Jan 2026 17:58:45 +0000 Subject: [PATCH 2/4] Add version to pdb signature scanner and require it for the banners plugin --- volatility3/framework/plugins/banners.py | 5 +++++ volatility3/framework/symbols/windows/pdbutil.py | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/volatility3/framework/plugins/banners.py b/volatility3/framework/plugins/banners.py index 85a6f4862..2b354edcb 100644 --- a/volatility3/framework/plugins/banners.py +++ b/volatility3/framework/plugins/banners.py @@ -30,6 +30,11 @@ class Banners(interfaces.plugins.PluginInterface): component=scanners.RegExScanner, version=(1, 0, 0), ), + requirements.VersionRequirement( + name="pdb_signature_scanner", + component=pdbutil.PdbSignatureScanner, + version=(1, 0, 0), + ), ] def _generator(self): diff --git a/volatility3/framework/symbols/windows/pdbutil.py b/volatility3/framework/symbols/windows/pdbutil.py index 5f5c8cac8..d1ea4abd5 100644 --- a/volatility3/framework/symbols/windows/pdbutil.py +++ b/volatility3/framework/symbols/windows/pdbutil.py @@ -525,6 +525,10 @@ class PdbSignatureScanner(interfaces.layers.ScannerInterface): .. note:: The pdb_names must be a list of byte strings, unicode strs will not match against the data scanned """ + _version = (1, 0, 0) + + _required_framework_version = (2, 27, 0) + overlap = 0x4000 """The size of overlap needed for the signature to ensure data cannot hide between two scanned chunks""" thread_safe = True @@ -548,9 +552,7 @@ class PdbSignatureScanner(interfaces.layers.ScannerInterface): ) for match in re.finditer(pattern, data, flags=re.DOTALL): pdb_name = data[ - match.start(0) - + 4 - + self._RSDS_format.size : match.start(0) + match.start(0) + 4 + self._RSDS_format.size : match.start(0) + len(match.group()) - 1 ] From 743927d6a2c3ebb2c531e274127f91062ff2455a Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 31 Jan 2026 18:00:07 +0000 Subject: [PATCH 3/4] Make black happy --- volatility3/framework/symbols/windows/pdbutil.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/volatility3/framework/symbols/windows/pdbutil.py b/volatility3/framework/symbols/windows/pdbutil.py index d1ea4abd5..af86f6997 100644 --- a/volatility3/framework/symbols/windows/pdbutil.py +++ b/volatility3/framework/symbols/windows/pdbutil.py @@ -552,7 +552,9 @@ class PdbSignatureScanner(interfaces.layers.ScannerInterface): ) for match in re.finditer(pattern, data, flags=re.DOTALL): pdb_name = data[ - match.start(0) + 4 + self._RSDS_format.size : match.start(0) + match.start(0) + + 4 + + self._RSDS_format.size : match.start(0) + len(match.group()) - 1 ] From 48a5000f78fcd386cf29673104a7ee917756aa16 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 31 Jan 2026 18:03:55 +0000 Subject: [PATCH 4/4] Make the output of banners match the identifier in isfinfo --- volatility3/framework/plugins/banners.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/volatility3/framework/plugins/banners.py b/volatility3/framework/plugins/banners.py index 2b354edcb..69a1ee2b7 100644 --- a/volatility3/framework/plugins/banners.py +++ b/volatility3/framework/plugins/banners.py @@ -89,7 +89,7 @@ class Banners(interfaces.plugins.PluginInterface): ): yield ( format_hints.Hex(offset), - f"{pdb_name.decode('latin-1')} - {guid}-{age}", + f"{pdb_name.decode('latin-1')}|{guid}|{age}", ) def run(self):