mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-23 14:42:25 +02:00
159 lines
7.9 KiB
Python
159 lines
7.9 KiB
Python
# This file is Copyright 2020 Volatility Foundation and licensed under the Volatility Software License 1.0
|
|
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
|
|
|
from typing import Callable, List, Generator, Iterable, Dict
|
|
from volatility.framework import renderers, interfaces, objects, exceptions
|
|
from volatility.framework.configuration import requirements
|
|
from volatility.framework.objects import utility
|
|
from volatility.plugins.windows import pslist
|
|
from volatility.plugins.windows.registry import hivelist
|
|
|
|
class Envars(interfaces.plugins.PluginInterface):
|
|
"Display process environment variables"
|
|
|
|
_version = (1, 0, 0)
|
|
|
|
@classmethod
|
|
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
|
# Since we're calling the plugin, make sure we have the plugin's requirements
|
|
return [requirements.TranslationLayerRequirement(name = 'primary',
|
|
description = 'Memory layer for the kernel',
|
|
architectures = ["Intel32", "Intel64"]),
|
|
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
|
|
requirements.ListRequirement(name = 'pid',
|
|
description = 'Filter on specific process IDs',
|
|
element_type = int,
|
|
optional = True),
|
|
requirements.BooleanRequirement(name='silent',
|
|
description='Suppress common and non-persistent variables',
|
|
optional=True),
|
|
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
|
|
requirements.PluginRequirement(name = 'hivelist', plugin = hivelist.HiveList, version = (1, 0, 0))
|
|
]
|
|
|
|
def _get_silent_vars(self) -> List[str]:
|
|
"""Enumerate persistent & common variables.
|
|
|
|
This function collects the global (all users) and
|
|
user-specific environment variables from the
|
|
registry. Any variables in a process env block that
|
|
does not exist in the persistent list was explicitly
|
|
set with the SetEnvironmentVariable() API.
|
|
"""
|
|
|
|
values = []
|
|
|
|
|
|
for hive in hivelist.HiveList.list_hives(context = self.context,
|
|
base_config_path = self.config_path,
|
|
layer_name = self.config['primary'],
|
|
symbol_table = self.config['nt_symbols'],
|
|
hive_offsets = None):
|
|
sys = False
|
|
ntuser = False
|
|
|
|
## The global variables
|
|
try:
|
|
key = hive.get_key('CurrentControlSet\\Control\\Session Manager\\Environment')
|
|
sys = True
|
|
except KeyError:
|
|
try:
|
|
key = hive.get_key('ControlSet001\\Control\\Session Manager\\Environment')
|
|
sys = True
|
|
except KeyError:
|
|
pass
|
|
if sys:
|
|
try:
|
|
for node in key.get_values():
|
|
try:
|
|
value_node_name = node.get_name()
|
|
if value_node_name:
|
|
values.append(value_node_name)
|
|
except (exceptions.InvalidAddressException, RegistryFormatException) as excp:
|
|
vollog.log(constants.LOGLEVEL_VVV, "Error while parsing global environment variables keys (some keys might be excluded)")
|
|
continue
|
|
except KeyError:
|
|
pass
|
|
|
|
## The user-specific variables
|
|
try:
|
|
key = hive.get_key('Environment')
|
|
ntuser = True
|
|
except KeyError:
|
|
pass
|
|
if ntuser:
|
|
try:
|
|
for node in key.get_values():
|
|
try:
|
|
value_node_name = node.get_name()
|
|
if value_node_name:
|
|
values.append(value_node_name)
|
|
except (exceptions.InvalidAddressException, RegistryFormatException) as excp:
|
|
vollog.log(constants.LOGLEVEL_VVV, "Error while parsing user environment variables keys (some keys might be excluded)")
|
|
continue
|
|
except KeyError:
|
|
pass
|
|
|
|
## The volatile user variables
|
|
try:
|
|
key = hive.get_key('Volatile Environment')
|
|
except KeyError:
|
|
continue
|
|
try:
|
|
for node in key.get_values():
|
|
try:
|
|
value_node_name = node.get_name()
|
|
if value_node_name:
|
|
values.append(value_node_name)
|
|
except (exceptions.InvalidAddressException, RegistryFormatException) as excp:
|
|
vollog.log(constants.LOGLEVEL_VVV, "Error while parsing volatile environment variables keys (some keys might be excluded)")
|
|
continue
|
|
except KeyError:
|
|
continue
|
|
|
|
|
|
## These are variables set explicitly but are
|
|
## common enough to ignore safely.
|
|
values.extend(["ProgramFiles", "CommonProgramFiles", "SystemDrive",
|
|
"SystemRoot", "ProgramData", "PUBLIC", "ALLUSERSPROFILE",
|
|
"COMPUTERNAME", "SESSIONNAME", "USERNAME", "USERPROFILE",
|
|
"PROMPT", "USERDOMAIN", "AppData", "CommonFiles", "CommonDesktop",
|
|
"CommonProgramGroups", "CommonStartMenu", "CommonStartUp",
|
|
"Cookies", "DesktopDirectory", "Favorites", "History", "NetHood",
|
|
"PersonalDocuments", "RecycleBin", "StartMenu", "Templates",
|
|
"AltStartup", "CommonFavorites", "ConnectionWizard",
|
|
"DocAndSettingRoot", "InternetCache", "windir", "Path", "HOMEDRIVE",
|
|
"PROCESSOR_ARCHITECTURE", "NUMBER_OF_PROCESSORS", "ProgramFiles(x86)",
|
|
"CommonProgramFiles(x86)", "CommonProgramW6432", "PSModulePath",
|
|
"PROCESSOR_IDENTIFIER", "FP_NO_HOST_CHECK", "LOCALAPPDATA", "TMP",
|
|
"ProgramW6432",
|
|
])
|
|
|
|
return values
|
|
|
|
def _generator(self, data):
|
|
if self.config.get('SILENT', None):
|
|
silent_vars = self._get_silent_vars()
|
|
|
|
for task in data:
|
|
for var, val in task.environment_variables():
|
|
if self.config.get('SILENT', None):
|
|
if var in silent_vars:
|
|
continue
|
|
yield (0, [int(task.UniqueProcessId),
|
|
str(objects.utility.array_to_string(task.ImageFileName)),
|
|
hex(task.get_peb().ProcessParameters.Environment.vol.offset),
|
|
str(var),
|
|
str(val)])
|
|
|
|
|
|
def run(self):
|
|
|
|
filter_func = pslist.PsList.create_pid_filter(self.config.get('pid', None))
|
|
|
|
return renderers.TreeGrid([("PID", int),("Process", str),("Block", str),("Variable", str),("Value", str)],
|
|
self._generator(pslist.PsList.list_processes(context = self.context,
|
|
layer_name = self.config['primary'],
|
|
symbol_table = self.config['nt_symbols'],
|
|
filter_func = filter_func)))
|