diff --git a/volatility/framework/plugins/mac/bash.py b/volatility/framework/plugins/mac/bash.py index eeda5eb0d..947194632 100644 --- a/volatility/framework/plugins/mac/bash.py +++ b/volatility/framework/plugins/mac/bash.py @@ -12,10 +12,9 @@ from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins from volatility.framework.layers import scanners from volatility.framework.objects import utility -from volatility.plugins import timeliner -from volatility.plugins.mac import tasks - from volatility.framework.symbols.linux.bash import BashIntermedSymbols +from volatility.plugins import timeliner +from volatility.plugins.mac import pslist class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): @@ -28,7 +27,7 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] def _generator(self, tasks): @@ -84,24 +83,23 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): yield (0, (int(task.p_pid), task_name, hist.get_time_object(), hist.get_command())) def run(self): - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) + list_tasks = pslist.PsList.get_list_tasks(self.config.get('method', 'tasks')) return renderers.TreeGrid([("PID", int), ("Process", str), ("CommandTime", datetime.datetime), ("Command", str)], self._generator( - tasks.Tasks.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = filter_func))) + list_tasks(self.context, + self.config['primary'], + self.config['darwin'], + filter_func = filter_func))) def generate_timeline(self): - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) + list_tasks = pslist.PsList.get_list_tasks(self.config.get('pslist_method', pslist.PsList.pslist_methods[0])) for row in self._generator( - tasks.Tasks.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = filter_func)): + list_tasks(self.context, self.config['primary'], self.config['darwin'], filter_func = filter_func)): _depth, row_data = row description = "{} ({}): \"{}\"".format(row_data[0], row_data[1], row_data[3]) yield (description, timeliner.TimeLinerType.CREATED, row_data[2]) diff --git a/volatility/framework/plugins/mac/lsof.py b/volatility/framework/plugins/mac/lsof.py index 8aaf6c43b..6c2176f97 100644 --- a/volatility/framework/plugins/mac/lsof.py +++ b/volatility/framework/plugins/mac/lsof.py @@ -8,7 +8,7 @@ from volatility.framework import renderers from volatility.framework.automagic import mac from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins -from volatility.plugins.mac import tasks +from volatility.plugins.mac import pslist vollog = logging.getLogger(__name__) @@ -23,7 +23,7 @@ class Lsof(plugins.PluginInterface): description = 'Kernel Address Space', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Mac Kernel"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] def _generator(self, tasks): @@ -36,11 +36,12 @@ class Lsof(plugins.PluginInterface): yield (0, (pid, fd, filepath)) def run(self): - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) + list_tasks = pslist.PsList.get_list_tasks(self.config.get('pslist_method', pslist.PsList.pslist_methods[0])) return renderers.TreeGrid([("PID", int), ("File Descriptor", int), ("File Path", str)], self._generator( - tasks.Tasks.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = filter_func))) + list_tasks(self.context, + self.config['primary'], + self.config['darwin'], + filter_func = filter_func))) diff --git a/volatility/framework/plugins/mac/malfind.py b/volatility/framework/plugins/mac/malfind.py index c80fd9799..44370d313 100644 --- a/volatility/framework/plugins/mac/malfind.py +++ b/volatility/framework/plugins/mac/malfind.py @@ -8,7 +8,7 @@ from volatility.framework import renderers from volatility.framework.configuration import requirements from volatility.framework.objects import utility from volatility.framework.renderers import format_hints -from volatility.plugins.mac import tasks +from volatility.plugins.mac import pslist class Malfind(interfaces.plugins.PluginInterface): @@ -21,7 +21,7 @@ class Malfind(interfaces.plugins.PluginInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)), + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)), ] def _list_injections(self, task): @@ -61,13 +61,14 @@ class Malfind(interfaces.plugins.PluginInterface): vma.get_perms(), format_hints.HexBytes(data), disasm)) def run(self): - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) + list_tasks = pslist.PsList.get_list_tasks(self.config.get('pslist_method', pslist.PsList.pslist_methods[0])) return renderers.TreeGrid([("PID", int), ("Process", str), ("Start", format_hints.Hex), ("End", format_hints.Hex), ("Protection", str), ("Hexdump", format_hints.HexBytes), ("Disasm", interfaces.renderers.Disassembly)], self._generator( - tasks.Tasks.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = filter_func))) + list_tasks(self.context, + self.config['primary'], + self.config['darwin'], + filter_func = filter_func))) diff --git a/volatility/framework/plugins/mac/netstat.py b/volatility/framework/plugins/mac/netstat.py index d653d1da6..885ac7d19 100644 --- a/volatility/framework/plugins/mac/netstat.py +++ b/volatility/framework/plugins/mac/netstat.py @@ -11,7 +11,7 @@ from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins from volatility.framework.objects import utility from volatility.framework.renderers import format_hints -from volatility.plugins.mac import tasks +from volatility.plugins.mac import pslist vollog = logging.getLogger(__name__) @@ -26,7 +26,7 @@ class Netstat(plugins.PluginInterface): description = 'Kernel Address Space', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Mac Kernel"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] @classmethod @@ -45,7 +45,9 @@ class Netstat(plugins.PluginInterface): 2) The process ID of the processed that opened the socket 3) The address of the associated socket structure """ - for task in tasks.Tasks.list_tasks(context, layer_name, darwin_symbols, filter_func): + # This is hardcoded, since a change in method + list_tasks = pslist.PsList.get_list_tasks(pslist.PsList.pslist_methods[0]) + for task in list_tasks(context, layer_name, darwin_symbols, filter_func): task_name = utility.array_to_string(task.p_comm) pid = task.p_pid @@ -67,7 +69,7 @@ class Netstat(plugins.PluginInterface): yield task_name, pid, socket def _generator(self): - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) for task_name, pid, socket in self.list_sockets(self.context, self.config['primary'], diff --git a/volatility/framework/plugins/mac/proc_maps.py b/volatility/framework/plugins/mac/proc_maps.py index 2160b0695..faeb70c15 100644 --- a/volatility/framework/plugins/mac/proc_maps.py +++ b/volatility/framework/plugins/mac/proc_maps.py @@ -6,7 +6,7 @@ from volatility.framework import renderers, interfaces from volatility.framework.configuration import requirements from volatility.framework.objects import utility from volatility.framework.renderers import format_hints -from volatility.plugins.mac import tasks +from volatility.plugins.mac import pslist class Maps(interfaces.plugins.PluginInterface): @@ -19,7 +19,7 @@ class Maps(interfaces.plugins.PluginInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] def _generator(self, tasks): @@ -36,12 +36,13 @@ class Maps(interfaces.plugins.PluginInterface): format_hints.Hex(vma.links.end), vma.get_perms(), path)) def run(self): - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) + list_tasks = pslist.PsList.get_list_tasks(self.config.get('pslist_method', pslist.PsList.pslist_methods[0])) return renderers.TreeGrid([("PID", int), ("Process", str), ("Start", format_hints.Hex), ("End", format_hints.Hex), ("Protection", str), ("Map Name", str)], self._generator( - tasks.Tasks.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = filter_func))) + list_tasks(self.context, + self.config['primary'], + self.config['darwin'], + filter_func = filter_func))) diff --git a/volatility/framework/plugins/mac/psaux.py b/volatility/framework/plugins/mac/psaux.py index 208954acc..cc984b9e5 100644 --- a/volatility/framework/plugins/mac/psaux.py +++ b/volatility/framework/plugins/mac/psaux.py @@ -8,7 +8,7 @@ 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 tasks +from volatility.plugins.mac import pslist class Psaux(plugins.PluginInterface): @@ -21,7 +21,7 @@ class Psaux(plugins.PluginInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] def _generator(self, tasks: Iterator[Any]) -> Generator[Tuple[int, Tuple[int, str, int, str]], None, None]: @@ -86,11 +86,12 @@ class Psaux(plugins.PluginInterface): yield (0, (task.p_pid, task_name, task.p_argc, args_str)) def run(self) -> renderers.TreeGrid: - filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)]) + filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)]) + list_tasks = pslist.PsList.get_list_tasks(self.config.get('pslist_method', pslist.PsList.pslist_methods[0])) return renderers.TreeGrid([("PID", int), ("Process", str), ("Argc", int), ("Arguments", str)], self._generator( - tasks.Tasks.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = filter_func))) + list_tasks(self.context, + self.config['primary'], + self.config['darwin'], + filter_func = filter_func))) diff --git a/volatility/framework/plugins/mac/pslist.py b/volatility/framework/plugins/mac/pslist.py index e13ef624a..c32ca5c22 100644 --- a/volatility/framework/plugins/mac/pslist.py +++ b/volatility/framework/plugins/mac/pslist.py @@ -6,7 +6,6 @@ import logging from typing import Callable, Iterable, List, Dict from volatility.framework import renderers, interfaces, contexts, exceptions -from volatility.framework.automagic import mac from volatility.framework.configuration import requirements from volatility.framework.objects import utility @@ -16,7 +15,8 @@ vollog = logging.getLogger(__name__) class PsList(interfaces.plugins.PluginInterface): """Lists the processes present in a particular mac memory image.""" - _version = (1, 0, 0) + _version = (2, 0, 0) + pslist_methods = ['tasks', 'allproc', 'process_group'] @classmethod def get_requirements(cls): @@ -24,9 +24,43 @@ class PsList(interfaces.plugins.PluginInterface): requirements.TranslationLayerRequirement(name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols") + requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"), + requirements.ChoiceRequirement(name = 'pslist_method', + description = 'Method to determine for processes', + choices = cls.pslist_methods, + default = cls.pslist_methods[0], + optional = True) ] + @classmethod + def get_list_tasks( + cls, method: str + ) -> Callable[[interfaces.context.ContextInterface, str, str, Callable[[int], bool]], + Iterable[interfaces.objects.ObjectInterface]]: + """Returns the list_tasks method based on the selector + + Args: + method: Must be one fo the available methods in get_task_choices + + Returns: + list_tasks method for listing tasks + """ + # Ensure method is one of the suitable choices + if method not in cls.pslist_methods: + method = cls.pslist_methods[0] + + if method == 'allproc': + list_tasks = cls.list_tasks_allproc + elif method == 'tasks': + list_tasks = cls.list_tasks_tasks + elif method == 'process_group': + list_tasks = cls.list_tasks_process_group + else: + raise ValueError("Impossible method choice chosen") + vollog.debug("Using method {}".format(method)) + + return list_tasks + @classmethod def create_pid_filter(cls, pid_list: List[int] = None) -> Callable[[int], bool]: @@ -43,23 +77,25 @@ class PsList(interfaces.plugins.PluginInterface): return filter_func def _generator(self): - for task in self.list_tasks(self.context, - self.config['primary'], - self.config['darwin'], - filter_func = self.create_pid_filter([self.config.get('pid', None)])): + list_tasks = self.get_list_tasks(self.config.get('method', self.pslist_methods[0])) + + for task in list_tasks(self.context, + self.config['primary'], + self.config['darwin'], + filter_func = self.create_pid_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, - darwin_symbols: str, - filter_func: Callable[[int], bool] = lambda _: False) -> \ + def list_tasks_allproc(cls, + context: interfaces.context.ContextInterface, + layer_name: str, + darwin_symbols: str, + filter_func: Callable[[int], bool] = lambda _: False) -> \ Iterable[interfaces.objects.ObjectInterface]: - """Lists all the processes in the primary layer. + """Lists all the processes in the primary layer based on the allproc method Args: context: The context to retrieve required elements (layers, symbol tables) from @@ -73,7 +109,7 @@ class PsList(interfaces.plugins.PluginInterface): kernel = contexts.Module(context, darwin_symbols, layer_name, 0) - kernel_as = context.layers[layer_name] + kernel_layer = context.layers[layer_name] proc = kernel.object_from_symbol(symbol_name = "allproc").lh_first @@ -85,7 +121,7 @@ class PsList(interfaces.plugins.PluginInterface): else: seen[proc.vol.offset] = 1 - if not filter_func(proc) and kernel_as.is_valid(proc.vol.offset, proc.vol.size): + if not filter_func(proc) and kernel_layer.is_valid(proc.vol.offset, proc.vol.size): yield proc try: @@ -93,5 +129,112 @@ class PsList(interfaces.plugins.PluginInterface): except exceptions.InvalidAddressException: break + @classmethod + def list_tasks_tasks(cls, + context: interfaces.context.ContextInterface, + layer_name: str, + darwin_symbols: str, + filter_func: Callable[[int], bool] = lambda _: False) -> \ + Iterable[interfaces.objects.ObjectInterface]: + """Lists all the tasks in the primary layer based on the tasks queue + + Args: + context: The context to retrieve required elements (layers, symbol tables) from + layer_name: The name of the layer on which to operate + darwin_symbols: The name of the table containing the kernel symbols + filter_func: A function which takes a task object and returns True if the task should be ignored/filtered + + Returns: + The list of task objects from the `layer_name` layer's `tasks` list after filtering + """ + + kernel = contexts.Module(context, darwin_symbols, layer_name, 0) + + kernel_layer = context.layers[layer_name] + + queue_entry = kernel.object_from_symbol(symbol_name = "tasks") + + seen = {} # type: Dict[int, int] + for task in queue_entry.walk_list(queue_entry, "tasks", "task"): + if task.vol.offset in seen: + vollog.log(logging.INFO, "Recursive process list detected (a result of non-atomic acquisition).") + break + else: + seen[task.vol.offset] = 1 + + try: + proc = task.bsd_info.dereference().cast("proc") + except exceptions.PagedInvalidAddressException: + continue + + if kernel_layer.is_valid(proc.vol.offset, proc.vol.size) and not filter_func(proc): + yield proc + + @classmethod + def list_tasks_process_group(cls, + context: interfaces.context.ContextInterface, + layer_name: str, + darwin_symbols: str, + filter_func: Callable[[int], bool] = lambda _: False) -> \ + Iterable[interfaces.objects.ObjectInterface]: + """Lists all the tasks in the primary layer using process groups + + Args: + context: The context to retrieve required elements (layers, symbol tables) from + layer_name: The name of the layer on which to operate + darwin_symbols: The name of the table containing the kernel symbols + filter_func: A function which takes a task object and returns True if the task should be ignored/filtered + + Returns: + The list of task objects from the `layer_name` layer's `tasks` list after filtering + """ + + kernel = contexts.Module(context, darwin_symbols, layer_name, 0) + + table_size = kernel.object_from_symbol(symbol_name = "pgrphash") + + pgrphashtbl = kernel.object_from_symbol(symbol_name = "pgrphashtbl") + + proc_array = kernel.object(object_type = "array", + offset = pgrphashtbl, + count = table_size + 1, + subtype = kernel.get_type("pgrphashhead")) + + for proc_list in proc_array: + # test the validity of the current element + # it is expected that many won't be initialized + try: + pgrp = proc_list.lh_first + except exceptions.PagedInvalidAddressException: + continue + + seen_pgrps = set() + + # this walks the particular process group + while pgrp and pgrp.vol.offset not in seen_pgrps: + seen_pgrps.add(pgrp.vol.offset) + + # nothing can be done if this list pointer is invalid, so move on + try: + p = pgrp.pg_members.lh_first + except exceptions.PagedInvalidAddressException: + break + + seen_pg = set() + while p and p.vol.offset not in seen_pg: + seen_pg.add(p.vol.offset) + + if p.is_readable() and not filter_func(p): + yield p + + try: + p = p.p_pglist.le_next + except exceptions.PagedInvalidAddressException: + break + try: + pgrp = pgrp.pg_hash.le_next + except exceptions.PagedInvalidAddressException: + break + def run(self): return renderers.TreeGrid([("PID", int), ("PPID", int), ("COMM", str)], self._generator()) diff --git a/volatility/framework/plugins/mac/pslist_process_groups.py b/volatility/framework/plugins/mac/pslist_process_groups.py deleted file mode 100644 index e145aba14..000000000 --- a/volatility/framework/plugins/mac/pslist_process_groups.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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 -# - -import logging -from typing import Callable, Dict, Iterable - -from volatility.framework import constants, interfaces, objects, contexts, exceptions -from volatility.plugins.mac import pslist - -vollog = logging.getLogger(__name__) - -class Pslist_Process_Groups(pslist.PsList): - """Lists the processes present in a particular mac memory image by enumerating the process group hash table.""" - - @classmethod - def list_tasks(cls, - context: interfaces.context.ContextInterface, - layer_name: str, - darwin_symbols: str, - filter_func: Callable[[int], bool] = lambda _: False) -> \ - Iterable[interfaces.objects.ObjectInterface]: - """Lists all the tasks in the primary layer. - - Args: - context: The context to retrieve required elements (layers, symbol tables) from - layer_name: The name of the layer on which to operate - darwin_symbols: The name of the table containing the kernel symbols - filter_func: A function which takes a task object and returns True if the task should be ignored/filtered - - Returns: - The list of task objects from the `layer_name` layer's `tasks` list after filtering - """ - - kernel = contexts.Module(context, darwin_symbols, layer_name, 0) - - kernel_as = context.layers[layer_name] - - table_size = kernel.object_from_symbol(symbol_name = "pgrphash") - - pgrphashtbl = kernel.object_from_symbol(symbol_name = "pgrphashtbl") - - proc_array = kernel.object(object_type = "array", - offset = pgrphashtbl, - count = table_size + 1, - subtype = kernel.get_type("pgrphashhead")) - - for proc_list in proc_array: - # test the validity of the current element - # it is expected that many won't be initialized - try: - pgrp = proc_list.lh_first - except exceptions.PagedInvalidAddressException: - continue - - seen_pgrps = set() - - # this walks the particular process group - while pgrp and pgrp.vol.offset not in seen_pgrps: - seen_pgrps.add(pgrp.vol.offset) - - # nothing can be done if this list pointer is invalid, so move on - try: - p = pgrp.pg_members.lh_first - except exceptions.PagedInvalidAddressException: - break - - seen_pg = set() - while p and p.vol.offset not in seen_pg: - seen_pg.add(p.vol.offset) - - if p.is_readable(): - yield p - - try: - p = p.p_pglist.le_next - except exceptions.PagedInvalidAddressException: - break - try: - pgrp = pgrp.pg_hash.le_next - except exceptions.PagedInvalidAddressException: - break - - - - - - - diff --git a/volatility/framework/plugins/mac/pstree.py b/volatility/framework/plugins/mac/pstree.py index 75f0a2a66..0f033175c 100644 --- a/volatility/framework/plugins/mac/pstree.py +++ b/volatility/framework/plugins/mac/pstree.py @@ -6,7 +6,7 @@ from volatility.framework import renderers from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins from volatility.framework.objects import utility -from volatility.plugins.mac import tasks +from volatility.plugins.mac import pslist class PsTree(plugins.PluginInterface): @@ -26,7 +26,7 @@ class PsTree(plugins.PluginInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"), - requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] def _find_level(self, pid): @@ -45,8 +45,10 @@ class PsTree(plugins.PluginInterface): self._levels[pid] = level def _generator(self): - """Generates the.""" - for proc in tasks.Tasks.list_tasks(self.context, self.config['primary'], self.config['darwin']): + """Generates the tree list of processes""" + list_tasks = pslist.PsList.get_list_tasks(self.config.get('pslist_method', pslist.PsList.pslist_methods[0])) + + for proc in list_tasks(self.context, self.config['primary'], self.config['darwin']): self._processes[proc.p_pid] = proc # Build the child/level maps diff --git a/volatility/framework/plugins/mac/tasks.py b/volatility/framework/plugins/mac/tasks.py deleted file mode 100644 index d7f472161..000000000 --- a/volatility/framework/plugins/mac/tasks.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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 -# - -import logging -from typing import Callable, Dict, Iterable - -from volatility.framework import interfaces, contexts, exceptions -from volatility.plugins.mac import pslist - -vollog = logging.getLogger(__name__) - - -class Tasks(pslist.PsList): - """Lists the processes present in a particular mac memory image.""" - - @classmethod - def list_tasks(cls, - context: interfaces.context.ContextInterface, - layer_name: str, - darwin_symbols: str, - filter_func: Callable[[int], bool] = lambda _: False) -> \ - Iterable[interfaces.objects.ObjectInterface]: - """Lists all the tasks in the primary layer. - - Args: - context: The context to retrieve required elements (layers, symbol tables) from - layer_name: The name of the layer on which to operate - darwin_symbols: The name of the table containing the kernel symbols - filter_func: A function which takes a task object and returns True if the task should be ignored/filtered - - Returns: - The list of task objects from the `layer_name` layer's `tasks` list after filtering - """ - - kernel = contexts.Module(context, darwin_symbols, layer_name, 0) - - kernel_as = context.layers[layer_name] - - queue_entry = kernel.object_from_symbol(symbol_name = "tasks") - - seen = {} # type: Dict[int, int] - for task in queue_entry.walk_list(queue_entry, "tasks", "task"): - if task.vol.offset in seen: - vollog.log(logging.INFO, "Recursive process list detected (a result of non-atomic acquisition).") - break - else: - seen[task.vol.offset] = 1 - - try: - proc = task.bsd_info.dereference().cast("proc") - except exceptions.PagedInvalidAddressException: - continue - - if kernel_as.is_valid(proc.vol.offset, proc.vol.size) and not filter_func(proc): - yield proc