mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-10 19:57:39 +02:00
Merge pull request #626 from kevthehermit/plugin/sessions
Sessions Plugin
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 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.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,
|
||||
description = "Process IDs to include (all other processes are excluded)",
|
||||
optional = True)
|
||||
]
|
||||
|
||||
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 pslist.PsList.list_processes(self.context,
|
||||
kernel.layer_name,
|
||||
kernel.symbol_table_name,
|
||||
filter_func = filter_func):
|
||||
|
||||
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):
|
||||
|
||||
return renderers.TreeGrid([("Session ID", int), ('Session Type', str), ("Process ID", int), ("Process", str),
|
||||
("User Name", str), ("Create Time", datetime.datetime)], self._generator())
|
||||
Reference in New Issue
Block a user