mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-10-01 05:54:58 +02:00
Merge branch 'volatilityfoundation:develop' into feature/reg-cert
This commit is contained in:
@@ -321,7 +321,7 @@ class SizedModule(Module):
|
||||
|
||||
The mapping should be sorted and should be quicker than reading
|
||||
the data We turn it into JSON to make a common string and use a
|
||||
quick hash, because collissions are unlikely
|
||||
quick hash, because collisions are unlikely
|
||||
"""
|
||||
layer = self._context.layers[self.layer_name]
|
||||
if not isinstance(layer, interfaces.layers.TranslationLayerInterface):
|
||||
|
||||
@@ -169,7 +169,7 @@ class BaseSymbolTableInterface:
|
||||
|
||||
def optional_set_type_class(self, name: str, clazz: Type[objects.ObjectInterface]) -> bool:
|
||||
"""Calls the set_type_class function but does not throw an exception.
|
||||
Returns whether setting the type class was successfull.
|
||||
Returns whether setting the type class was successful.
|
||||
Args:
|
||||
name: The name of the type to override the class for
|
||||
clazz: The actual class to override for the provided type name
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
# 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
|
||||
#
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework import symbols, exceptions, renderers, interfaces
|
||||
from volatility3.framework.objects import utility
|
||||
from volatility3.plugins.linux import pslist
|
||||
from volatility3.framework.interfaces import plugins
|
||||
|
||||
class PsAux(plugins.PluginInterface):
|
||||
""" Lists processes with their command line arguments """
|
||||
|
||||
_required_framework_version = (2, 0, 0)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls):
|
||||
# Since we're calling the plugin, make sure we have the plugin's requirements
|
||||
return [
|
||||
requirements.ModuleRequirement(name = 'kernel', description = 'Linux kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)),
|
||||
requirements.ListRequirement(name = 'pid',
|
||||
description = 'Filter on specific process IDs',
|
||||
element_type = int,
|
||||
optional = True)
|
||||
]
|
||||
|
||||
def _get_command_line_args(self, task: interfaces.objects.ObjectInterface,
|
||||
name: str) -> Optional[str]:
|
||||
"""
|
||||
Reads the command line arguments of a process
|
||||
These are stored on the userland stack
|
||||
Kernel threads re-use the process data structure, but do not have a valid 'mm' pointer
|
||||
|
||||
Parameters:
|
||||
task: task_struct object of the process
|
||||
name: string name of the process (from task.comm)
|
||||
"""
|
||||
|
||||
# kernel theads never have an mm as they do not have userland mappings
|
||||
try:
|
||||
mm = task.mm
|
||||
except exceptions.InvalidAddressException:
|
||||
mm = None
|
||||
|
||||
if mm:
|
||||
proc_layer_name = task.add_process_layer()
|
||||
if proc_layer_name is None:
|
||||
return renderers.UnreadableValue()
|
||||
|
||||
proc_layer = self.context.layers[proc_layer_name]
|
||||
|
||||
# read argv from userland
|
||||
start = task.mm.arg_start
|
||||
|
||||
# get the size of the arguments with sanity checking
|
||||
size_to_read = task.mm.arg_end - task.mm.arg_start
|
||||
if not (0 < size_to_read <= 4096):
|
||||
return renderers.UnreadableValue()
|
||||
|
||||
# attempt to read it all as partial values are invalid and misleading
|
||||
try:
|
||||
argv = proc_layer.read(start, size_to_read)
|
||||
except exceptions.InvalidAddressException:
|
||||
return renderers.UnreadableValue()
|
||||
|
||||
# the arguments are null byte terminated, replace the nulls with spaces
|
||||
s = argv.decode().split('\x00')
|
||||
args = " ".join(s)
|
||||
else:
|
||||
# kernel thread
|
||||
# [ ] mimics ps on a live system
|
||||
# also helps identify malware masquerading as a kernel thread, which is fairly common
|
||||
args = "[" + name + "]"
|
||||
|
||||
# remove trailing space, if present
|
||||
if len(args) > 1 and args[-1] == " ":
|
||||
args = args[:-1]
|
||||
|
||||
return args
|
||||
|
||||
def _generator(self, tasks):
|
||||
""" Generates a listing of processes along with command line arguments """
|
||||
|
||||
# walk the process list and report the arguments
|
||||
for task in tasks:
|
||||
pid = task.pid
|
||||
|
||||
try:
|
||||
ppid = task.parent.pid
|
||||
except exceptions.InvalidAddressException:
|
||||
ppid = 0
|
||||
|
||||
name = utility.array_to_string(task.comm)
|
||||
|
||||
args = self._get_command_line_args(task, name)
|
||||
|
||||
yield (0, (pid, ppid, name, args))
|
||||
|
||||
def run(self):
|
||||
filter_func = pslist.PsList.create_pid_filter(self.config.get('pid', None))
|
||||
|
||||
return renderers.TreeGrid([("PID", int), ("PPID", int), ("COMM", str), ("ARGS", str)],
|
||||
self._generator(
|
||||
pslist.PsList.list_tasks(self.context,
|
||||
self.config['kernel'],
|
||||
filter_func = filter_func)))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# This file is Copyright 2019 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 List, Tuple, Iterator
|
||||
from typing import Iterator, List, Tuple
|
||||
|
||||
from volatility3 import framework
|
||||
from volatility3.framework import exceptions, constants, interfaces, objects
|
||||
from volatility3.framework import constants, exceptions, interfaces, objects
|
||||
from volatility3.framework.objects import utility
|
||||
from volatility3.framework.symbols import intermed
|
||||
from volatility3.framework.symbols.linux import extensions
|
||||
@@ -29,7 +29,9 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable):
|
||||
self.set_type_class('files_struct', extensions.files_struct)
|
||||
self.set_type_class('vfsmount', extensions.vfsmount)
|
||||
self.set_type_class('kobject', extensions.kobject)
|
||||
self.set_type_class('mnt_namespace', extensions.mnt_namespace)
|
||||
|
||||
if 'mnt_namespace' in self.types:
|
||||
self.set_type_class('mnt_namespace', extensions.mnt_namespace)
|
||||
|
||||
if 'module' in self.types:
|
||||
self.set_type_class('module', extensions.module)
|
||||
@@ -267,4 +269,4 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface):
|
||||
while list_start:
|
||||
list_struct = vmlinux.object(object_type = struct_name, offset = list_start.vol.offset)
|
||||
yield list_struct
|
||||
list_start = getattr(list_struct, list_member)
|
||||
list_start = getattr(list_struct, list_member)
|
||||
|
||||
Reference in New Issue
Block a user