diff --git a/volatility/framework/plugins/windows/driverscan.py b/volatility/framework/plugins/windows/driverscan.py index 47565a161..399ed1273 100644 --- a/volatility/framework/plugins/windows/driverscan.py +++ b/volatility/framework/plugins/windows/driverscan.py @@ -23,13 +23,18 @@ class DriverScan(interfaces.plugins.PluginInterface): architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), requirements.PluginRequirement(name = 'poolscanner', plugin = poolscanner.PoolScanner, version = (1, 0, 0)), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_drivers(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for drivers using the poolscanner module and constraints. @@ -37,6 +42,7 @@ class DriverScan(interfaces.plugins.PluginInterface): context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of Driver objects as found from the `layer_name` layer based on Driver pool signatures @@ -44,13 +50,20 @@ class DriverScan(interfaces.plugins.PluginInterface): constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'Dri\xf6', b'Driv']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for driver in self.scan_drivers(self.context, self.config['primary'], self.config['nt_symbols']): + for driver in self.scan_drivers(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): try: driver_name = driver.get_driver_name() diff --git a/volatility/framework/plugins/windows/filescan.py b/volatility/framework/plugins/windows/filescan.py index 45aa5e68d..566ea875f 100644 --- a/volatility/framework/plugins/windows/filescan.py +++ b/volatility/framework/plugins/windows/filescan.py @@ -21,13 +21,18 @@ class FileScan(interfaces.plugins.PluginInterface): architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), requirements.PluginRequirement(name = 'poolscanner', plugin = poolscanner.PoolScanner, version = (1, 0, 0)), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_files(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for file objects using the poolscanner module and constraints. @@ -35,6 +40,7 @@ class FileScan(interfaces.plugins.PluginInterface): context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of File objects as found from the `layer_name` layer based on File pool signatures @@ -42,13 +48,20 @@ class FileScan(interfaces.plugins.PluginInterface): constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'Fil\xe5', b'File']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for fileobj in self.scan_files(self.context, self.config['primary'], self.config['nt_symbols']): + for fileobj in self.scan_files(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): try: file_name = fileobj.FileName.String diff --git a/volatility/framework/plugins/windows/modscan.py b/volatility/framework/plugins/windows/modscan.py index d99538fe9..c5b6c376c 100644 --- a/volatility/framework/plugins/windows/modscan.py +++ b/volatility/framework/plugins/windows/modscan.py @@ -20,13 +20,18 @@ class ModScan(interfaces.plugins.PluginInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_modules(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for modules using the poolscanner module and constraints. @@ -34,6 +39,7 @@ class ModScan(interfaces.plugins.PluginInterface): context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of Driver objects as found from the `layer_name` layer based on Driver pool signatures @@ -41,13 +47,20 @@ class ModScan(interfaces.plugins.PluginInterface): constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'MmLd']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for mod in self.scan_modules(self.context, self.config['primary'], self.config['nt_symbols']): + for mod in self.scan_modules(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): try: BaseDllName = mod.BaseDllName.get_string() diff --git a/volatility/framework/plugins/windows/mutantscan.py b/volatility/framework/plugins/windows/mutantscan.py index 10f5c776d..e55fc0064 100644 --- a/volatility/framework/plugins/windows/mutantscan.py +++ b/volatility/framework/plugins/windows/mutantscan.py @@ -21,13 +21,18 @@ class MutantScan(interfaces.plugins.PluginInterface): architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), requirements.PluginRequirement(name = 'poolscanner', plugin = poolscanner.PoolScanner, version = (1, 0, 0)), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_mutants(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for mutants using the poolscanner module and constraints. @@ -35,6 +40,7 @@ class MutantScan(interfaces.plugins.PluginInterface): context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of Mutant objects found by scanning memory for the Mutant pool signatures @@ -42,13 +48,20 @@ class MutantScan(interfaces.plugins.PluginInterface): constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'Mut\xe1', b'Muta']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for mutant in self.scan_mutants(self.context, self.config['primary'], self.config['nt_symbols']): + for mutant in self.scan_mutants(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): try: name = mutant.get_name() diff --git a/volatility/framework/plugins/windows/poolscanner.py b/volatility/framework/plugins/windows/poolscanner.py index 73e9c0331..9f3b2bd29 100644 --- a/volatility/framework/plugins/windows/poolscanner.py +++ b/volatility/framework/plugins/windows/poolscanner.py @@ -4,7 +4,7 @@ import enum import logging -from typing import Dict, Generator, List, Optional, Tuple, Callable +from typing import Dict, Generator, List, Optional, Tuple, Callable, Iterable from volatility.framework import constants, interfaces, renderers, exceptions, symbols from volatility.framework.configuration import requirements @@ -411,7 +411,7 @@ class PoolScanner(plugins.PluginInterface): pool_constraints: List[PoolConstraint], alignment: int = 8, progress_callback: Optional[constants.ProgressCallback] = None, - sections: List = None) \ + sections: Iterable[Tuple[int, int]] = None) \ -> Generator[Tuple[PoolConstraint, interfaces.objects.ObjectInterface], None, None]: """Returns the _POOL_HEADER object (based on the symbol_table template) after scanning through layer_name returning all headers that match any @@ -425,6 +425,7 @@ class PoolScanner(plugins.PluginInterface): pool_constraints: List of pool constraints used to limit the scan results alignment: An optional value that all pool headers will be aligned to progress_callback: An optional function to provide progress feedback whilst scanning + sections: Specific memory sections to scan through Returns: An Iterable of pool constraints and the pool headers associated with them diff --git a/volatility/framework/plugins/windows/psscan.py b/volatility/framework/plugins/windows/psscan.py index 2a5cfe48c..69edd9406 100644 --- a/volatility/framework/plugins/windows/psscan.py +++ b/volatility/framework/plugins/windows/psscan.py @@ -22,13 +22,18 @@ class PsScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_processes(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for processes using the poolscanner module and constraints. @@ -36,6 +41,7 @@ class PsScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of processes found by scanning the `layer_name` layer for process pool signatures @@ -43,13 +49,20 @@ class PsScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'Pro\xe3', b'Proc']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for proc in self.scan_processes(self.context, self.config['primary'], self.config['nt_symbols']): + for proc in self.scan_processes(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): yield (0, (proc.UniqueProcessId, proc.InheritedFromUniqueProcessId, proc.ImageFileName.cast("string", max_length = proc.ImageFileName.vol.count, errors = 'replace'), diff --git a/volatility/framework/plugins/windows/registry/hivescan.py b/volatility/framework/plugins/windows/registry/hivescan.py index 7aa6ee7ef..5bbe13309 100644 --- a/volatility/framework/plugins/windows/registry/hivescan.py +++ b/volatility/framework/plugins/windows/registry/hivescan.py @@ -22,13 +22,18 @@ class HiveScan(interfaces.plugins.PluginInterface): architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), requirements.PluginRequirement(name = 'poolscanner', plugin = poolscanner.PoolScanner, version = (1, 0, 0)), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_hives(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for hives using the poolscanner module and constraints. @@ -36,6 +41,7 @@ class HiveScan(interfaces.plugins.PluginInterface): context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of Hive objects as found from the `layer_name` layer based on Hive pool signatures @@ -43,13 +49,20 @@ class HiveScan(interfaces.plugins.PluginInterface): constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'CM10']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for hive in self.scan_hives(self.context, self.config['primary'], self.config['nt_symbols']): + for hive in self.scan_hives(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): yield (0, (format_hints.Hex(hive.vol.offset), )) diff --git a/volatility/framework/plugins/windows/symlinkscan.py b/volatility/framework/plugins/windows/symlinkscan.py index ee41f3d84..f0224167f 100644 --- a/volatility/framework/plugins/windows/symlinkscan.py +++ b/volatility/framework/plugins/windows/symlinkscan.py @@ -22,13 +22,18 @@ class SymlinkScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterfa description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), + requirements.BooleanRequirement(name = 'quick', + description = "Scan just allocated memory", + default = False, + optional = True), ] @classmethod def scan_symlinks(cls, context: interfaces.context.ContextInterface, layer_name: str, - symbol_table: str) -> \ + symbol_table: str, + quick: bool = False) -> \ Iterable[interfaces.objects.ObjectInterface]: """Scans for links using the poolscanner module and constraints. @@ -36,6 +41,7 @@ class SymlinkScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterfa context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols + quick: Scan only memory that windows has allocated Returns: A list of symlink objects found by scanning memory for the Symlink pool signatures @@ -43,13 +49,20 @@ class SymlinkScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterfa constraints = poolscanner.PoolScanner.builtin_constraints(symbol_table, [b'Sym\xe2', b'Symb']) - for result in poolscanner.PoolScanner.generate_pool_scan(context, layer_name, symbol_table, constraints): + for result in poolscanner.PoolScanner.generate_pool_scan(context, + layer_name, + symbol_table, + constraints, + quick = quick): _constraint, mem_object, _header = result yield mem_object def _generator(self): - for link in self.scan_symlinks(self.context, self.config['primary'], self.config['nt_symbols']): + for link in self.scan_symlinks(self.context, + self.config['primary'], + self.config['nt_symbols'], + quick = self.config['quick']): try: from_name = link.get_link_name()