diff --git a/volatility3/framework/plugins/windows/debugregisters.py b/volatility3/framework/plugins/windows/debugregisters.py index 0f6655c78..38b0cb97e 100644 --- a/volatility3/framework/plugins/windows/debugregisters.py +++ b/volatility3/framework/plugins/windows/debugregisters.py @@ -38,7 +38,7 @@ class DebugRegisters(interfaces.plugins.PluginInterface): name="pslist", component=pslist.PsList, version=(3, 0, 0) ), requirements.VersionRequirement( - name="threads", component=threads.Threads, version=(2, 0, 0) + name="threads", component=threads.Threads, version=(3, 0, 0) ), requirements.VersionRequirement( name="pe_symbols", component=pe_symbols.PESymbols, version=(2, 0, 0) @@ -111,8 +111,6 @@ class DebugRegisters(interfaces.plugins.PluginInterface): None, None, ]: - kernel = self.context.modules[self.config["kernel"]] - vads_cache: Dict[int, pe_symbols.ranges_type] = {} proc_modules = None @@ -122,7 +120,9 @@ class DebugRegisters(interfaces.plugins.PluginInterface): ) for proc in procs: - for thread in threads.Threads.list_threads(kernel, proc): + for thread in threads.Threads.list_threads( + self.context, self.config["kernel"], proc + ): debug_info = self._get_debug_info(thread) if not debug_info: continue diff --git a/volatility3/framework/plugins/windows/suspended_threads.py b/volatility3/framework/plugins/windows/suspended_threads.py index f83a201b5..f8f5027d4 100644 --- a/volatility3/framework/plugins/windows/suspended_threads.py +++ b/volatility3/framework/plugins/windows/suspended_threads.py @@ -36,7 +36,7 @@ class SuspendedThreads(interfaces.plugins.PluginInterface): name="pe_symbols", component=pe_symbols.PESymbols, version=(2, 0, 0) ), requirements.VersionRequirement( - name="threads", component=threads.Threads, version=(2, 0, 0) + name="threads", component=threads.Threads, version=(3, 0, 0) ), ] @@ -54,8 +54,6 @@ class SuspendedThreads(interfaces.plugins.PluginInterface): https://www.volexity.com/wp-content/uploads/2024/08/Defcon24_EDR_Evasion_Detection_White-Paper_Andrew-Case.pdf """ - kernel = self.context.modules[self.config["kernel"]] - vads_cache: Dict[int, pe_symbols.PESymbols.ranges_type] = {} proc_modules = None @@ -64,7 +62,9 @@ class SuspendedThreads(interfaces.plugins.PluginInterface): for proc in pslist.PsList.list_processes( context=self.context, kernel_module_name=self.config["kernel"] ): - for thread in threads.Threads.list_threads(kernel, proc): + for thread in threads.Threads.list_threads( + self.context, self.config["kernel"], proc + ): try: # we only care if the thread is suspended if thread.Tcb.SuspendCount == 0: diff --git a/volatility3/framework/plugins/windows/suspicious_threads.py b/volatility3/framework/plugins/windows/suspicious_threads.py index f83f3efc9..c98b06792 100644 --- a/volatility3/framework/plugins/windows/suspicious_threads.py +++ b/volatility3/framework/plugins/windows/suspicious_threads.py @@ -41,7 +41,7 @@ class SuspiciousThreads(interfaces.plugins.PluginInterface): name="pslist", component=pslist.PsList, version=(3, 0, 0) ), requirements.VersionRequirement( - name="threads", component=threads.Threads, version=(2, 0, 0) + name="threads", component=threads.Threads, version=(3, 0, 0) ), requirements.VersionRequirement( name="vadinfo", component=vadinfo.VadInfo, version=(2, 0, 0) @@ -169,7 +169,9 @@ class SuspiciousThreads(interfaces.plugins.PluginInterface): # there is no benefit to checking the same address more than once per process checked = set() - for thread in threads.Threads.list_threads(kernel, proc): + for thread in threads.Threads.list_threads( + self.context, self.config["kernel"], proc + ): # do not process if a thread is exited or terminated (4 = Terminated) if thread.ExitTime.QuadPart > 0 or thread.Tcb.State == 4: continue diff --git a/volatility3/framework/plugins/windows/threads.py b/volatility3/framework/plugins/windows/threads.py index f6d542357..e7150bbe4 100644 --- a/volatility3/framework/plugins/windows/threads.py +++ b/volatility3/framework/plugins/windows/threads.py @@ -16,7 +16,7 @@ class Threads(thrdscan.ThrdScan): """Lists process threads""" _required_framework_version = (2, 4, 0) - _version = (2, 0, 0) + _version = (3, 0, 0) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -36,9 +36,11 @@ class Threads(thrdscan.ThrdScan): ), ] - @classmethod + @staticmethod def list_threads( - cls, kernel, proc: interfaces.objects.ObjectInterface + context: interfaces.context.ContextInterface, + kernel_module_name: str, + proc: interfaces.objects.ObjectInterface, ) -> Generator[interfaces.objects.ObjectInterface, None, None]: """Lists the Threads of a specific process. @@ -48,6 +50,8 @@ class Threads(thrdscan.ThrdScan): Returns: A list of threads based on the process and filtered based on the filter function """ + kernel = context.modules[kernel_module_name] + seen = set() for thread in proc.ThreadListHead.to_list( f"{kernel.symbol_table_name}{constants.BANG}_ETHREAD", "ThreadListEntry" @@ -64,8 +68,6 @@ class Threads(thrdscan.ThrdScan): kernel_module_name: str, ) -> Iterable[interfaces.objects.ObjectInterface]: """Runs through all processes and lists threads for each process""" - module = context.modules[kernel_module_name] - filter_func = pslist.PsList.create_pid_filter(context.config.get("pid", None)) for proc in pslist.PsList.list_processes( @@ -73,4 +75,4 @@ class Threads(thrdscan.ThrdScan): kernel_module_name=kernel_module_name, filter_func=filter_func, ): - yield from cls.list_threads(module, proc) + yield from cls.list_threads(context, kernel_module_name, proc)