Move all core plugins over to framework/plugins.

This should have no impact functionality-wise.
The statistics plugin was left out a) as an example and b) because it
was committed by mistake in the first place and was never meant to be a
real plugin.
This commit is contained in:
Mike Auty
2018-12-16 13:40:15 +00:00
parent 9824538bd9
commit 35ad2325a8
38 changed files with 9 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
"""In-memory artifacts from OSX systems"""
from typing import Iterator, Tuple, Any, Generator, List
from volatility.framework import exceptions, renderers, interfaces
from volatility.framework.configuration import requirements
from volatility.framework.interfaces import plugins
from volatility.framework.objects import utility
from volatility.plugins.mac import pslist
class Psaux(plugins.PluginInterface):
"""Recovers program command line arguments"""
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [requirements.TranslationLayerRequirement(name = 'primary',
description = 'Kernel Address Space',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolRequirement(name = "darwin",
description = "Mac Kernel")]
def _generator(self, tasks: Iterator[Any]) -> Generator[Tuple[int, Tuple[int, str, int, str]], None, None]:
for task in tasks:
proc_layer_name = task.add_process_layer()
if proc_layer_name is None:
continue
proc_layer = self.context.memory[proc_layer_name]
argsstart = task.user_stack - task.p_argslen
if (not proc_layer.is_valid(argsstart) or
not task.p_argslen or not task.p_argc):
continue
# Add one because the first two are usually duplicates
argc = task.p_argc + 1
# smear protection
if argc > 1024:
continue
task_name = utility.array_to_string(task.p_comm)
args = []
while argc > 0:
try:
arg = proc_layer.read(argsstart, 256)
except exceptions.PagedInvalidAddressException:
break
idx = arg.find(b'\x00')
if idx > -1:
arg = arg[:idx]
argsstart += len(str(arg)) + 1
# deal with the stupid alignment (leading nulls) and arg duplication
if not args:
while argsstart < task.user_stack:
try:
check = proc_layer.read(argsstart, 1)
except exceptions.PagedInvalidAddressException:
break
if check != b"\x00":
break
argsstart = argsstart + 1
args.append(arg)
# also check for initial duplicates since OS X is painful
elif arg != args[0]:
args.append(arg)
argc -= 1
args_str = " ".join([s.decode("utf-8") for s in args])
yield (0, (task.p_pid, task_name, task.p_argc, args_str))
def run(self) -> renderers.TreeGrid:
filter = pslist.PsList.create_filter([self.config.get('pid', None)])
plugin = pslist.PsList.list_tasks
return renderers.TreeGrid(
[("PID", int),
("Process", str),
("Argc", int),
("Arguments", str)],
self._generator(plugin(self.context,
self.config['primary'],
self.config['darwin'],
filter = filter)))
@@ -0,0 +1,74 @@
import logging
from typing import Callable, Generator, List
import volatility.framework.interfaces.plugins as interfaces_plugins
from volatility.framework import renderers, interfaces
from volatility.framework.automagic import mac
from volatility.framework.configuration import requirements
from volatility.framework.objects import utility
vollog = logging.getLogger(__name__)
class PsList(interfaces_plugins.PluginInterface):
"""Lists the processes present in a particular mac memory image"""
@classmethod
def get_requirements(cls):
return [requirements.TranslationLayerRequirement(name = 'primary',
description = 'Kernel Address Space',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolRequirement(name = "darwin",
description = "Mac Kernel")]
@classmethod
def create_filter(cls, pid_list: List[int] = None) -> Callable[[int], bool]:
filter = lambda _: False
# FIXME: mypy #4973 or #2608
pid_list = pid_list or []
filter_list = [x for x in pid_list if x is not None]
if filter_list:
filter = lambda x: x not in filter_list
return filter
def _generator(self):
for task in self.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter = self.create_filter([self.config.get('pid', None)])):
pid = task.p_pid
ppid = task.p_ppid
name = utility.array_to_string(task.p_comm)
yield (0, (pid, ppid, name))
@classmethod
def list_tasks(cls,
context: interfaces.context.ContextInterface,
layer_name: str,
mac_symbols: str,
filter: Callable[[int], bool] = lambda _: False) \
-> Generator[interfaces.objects.ObjectInterface, None, None]:
"""Lists all the tasks in the primary layer"""
aslr_shift = mac.MacUtilities.find_aslr(context, mac_symbols, layer_name)
darwin = context.module(mac_symbols, layer_name, aslr_shift)
proc = darwin.object(symbol_name = "allproc").lh_first
seen = {}
while proc != None and proc.vol.offset != 0:
if proc.vol.offset in seen:
vollog.log(logging.INFO, "Recursive process list detected (a result of non-atomic acquisition).")
break
else:
seen[proc.vol.offset] = 1
yield proc
proc = proc.p_list.le_next.dereference()
def run(self):
return renderers.TreeGrid([("PID", int),
("PPID", int),
("COMM", str)],
self._generator())