From 0f23089cb483484ce1eed54ca87d5e78825d02e3 Mon Sep 17 00:00:00 2001 From: KevTheHermit Date: Mon, 17 Jan 2022 00:28:59 +0000 Subject: [PATCH 1/2] Create Sessions Plugin --- .../framework/plugins/windows/sessions.py | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 volatility3/framework/plugins/windows/sessions.py diff --git a/volatility3/framework/plugins/windows/sessions.py b/volatility3/framework/plugins/windows/sessions.py new file mode 100644 index 000000000..cd02668ae --- /dev/null +++ b/volatility3/framework/plugins/windows/sessions.py @@ -0,0 +1,96 @@ +# This file is Copyright 2022 Volatility Foundation and licensed under the Volatility Software License 1.0 +# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 +# + +import datetime +import logging + +from volatility3.framework import renderers, interfaces +from volatility3.framework.configuration import requirements +from volatility3.framework.objects import utility +from volatility3.plugins.windows import pslist + +vollog = logging.getLogger(__name__) + + +class Sessions(interfaces.plugins.PluginInterface): + """lists Processes with Session information extracted from Environmental Variables""" + + _required_framework_version = (2, 0, 0) + + @classmethod + def get_requirements(cls): + return [ + requirements.TranslationLayerRequirement(name = 'primary', + description = 'Memory layer for the kernel', + architectures = ["Intel32", "Intel64"]), + requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)), + requirements.ListRequirement(name = 'pid', + element_type = int, + description = "Process IDs to include (all other processes are excluded)", + optional = True) + ] + + def _generator(self, procs): + + # Collect all the values as we will want to group them later + sessions = {} + + for proc in procs: + + session_id = proc.get_session_id() + + # Detect RDP, Console or set default value + session_type = renderers.NotAvailableValue() + + # Construct Username from Process Env + user_domain = '' + user_name = '' + + for var, val in proc.environment_variables(): + if var.lower() == 'username': + user_name = val + elif var.lower() == 'userdomain': + user_domain = val + if var.lower() == 'sessionname': + session_type = val + + # Concat Domain and User + full_user = f'{user_domain}/{user_name}' + if full_user == '/': + full_user = renderers.NotAvailableValue() + + # Collect all the values in to a row we can yield after sorting. + row = { + "session_id": session_id, + "process_id": proc.UniqueProcessId, + "process_name": utility.array_to_string(proc.ImageFileName), + "user_name": full_user, + "process_start": proc.get_create_time(), + "session_type": session_type + } + + # Add row to correct session so we can sort it later + if session_id in sessions: + sessions[session_id].append(row) + else: + sessions[session_id] = [row] + + # Group and yield each row + for rows in sessions.values(): + for row in rows: + yield 0, (row.get('session_id'), row.get('session_type'), row.get('process_id'), + row.get('process_name'), row.get('user_name'), row.get('process_start')) + + def run(self): + + filter_func = pslist.PsList.create_pid_filter(self.config.get('pid', None)) + + return renderers.TreeGrid([("Session ID", int), ('Session Type', str), ("Process ID", int), ("Process", str), + ("User Name", str), ("Create Time", datetime.datetime)], + self._generator( + pslist.PsList.list_processes(self.context, + self.config['primary'], + self.config['nt_symbols'], + filter_func = filter_func))) From be0dd49d314bc6d4b2aa907928f0fb7123cb5f43 Mon Sep 17 00:00:00 2001 From: KevTheHermit Date: Tue, 18 Jan 2022 19:34:06 +0000 Subject: [PATCH 2/2] Sessions Plugin use ModuleRequirement --- .../framework/plugins/windows/sessions.py | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/volatility3/framework/plugins/windows/sessions.py b/volatility3/framework/plugins/windows/sessions.py index cd02668ae..66a54c3f0 100644 --- a/volatility3/framework/plugins/windows/sessions.py +++ b/volatility3/framework/plugins/windows/sessions.py @@ -21,10 +21,9 @@ class Sessions(interfaces.plugins.PluginInterface): @classmethod def get_requirements(cls): return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), + requirements.ModuleRequirement(name = 'kernel', + description = 'Windows kernel', + architectures = ["Intel32", "Intel64"]), requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)), requirements.ListRequirement(name = 'pid', element_type = int, @@ -32,12 +31,17 @@ class Sessions(interfaces.plugins.PluginInterface): optional = True) ] - def _generator(self, procs): + def _generator(self): + kernel = self.context.modules[self.config['kernel']] + filter_func = pslist.PsList.create_pid_filter(self.config.get('pid', None)) # Collect all the values as we will want to group them later sessions = {} - for proc in procs: + for proc in pslist.PsList.list_processes(self.context, + kernel.layer_name, + kernel.symbol_table_name, + filter_func = filter_func): session_id = proc.get_session_id() @@ -56,7 +60,7 @@ class Sessions(interfaces.plugins.PluginInterface): if var.lower() == 'sessionname': session_type = val - # Concat Domain and User + # Concat Domain and User full_user = f'{user_domain}/{user_name}' if full_user == '/': full_user = renderers.NotAvailableValue() @@ -85,12 +89,5 @@ class Sessions(interfaces.plugins.PluginInterface): def run(self): - filter_func = pslist.PsList.create_pid_filter(self.config.get('pid', None)) - return renderers.TreeGrid([("Session ID", int), ('Session Type', str), ("Process ID", int), ("Process", str), - ("User Name", str), ("Create Time", datetime.datetime)], - self._generator( - pslist.PsList.list_processes(self.context, - self.config['primary'], - self.config['nt_symbols'], - filter_func = filter_func))) + ("User Name", str), ("Create Time", datetime.datetime)], self._generator())