Source code for volatility3.plugins.linux.library_list

# This file is Copyright 2024 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 Iterable, Tuple

from volatility3.framework import interfaces, renderers, constants, exceptions
from volatility3.framework.configuration import requirements
from volatility3.framework.renderers import format_hints
from volatility3.framework.objects import utility
from volatility3.framework.symbols import intermed
from volatility3.framework.symbols.linux.extensions import elf
from volatility3.plugins.linux import pslist


vollog = logging.getLogger(__name__)


[docs]class LibraryList(interfaces.plugins.PluginInterface): """Enumerate libraries loaded into processes""" _required_framework_version = (2, 0, 0) _version = (1, 0, 0)
[docs] @classmethod def get_requirements(cls): return [ requirements.ModuleRequirement( name="kernel", description="Linux kernel", architectures=["Intel32", "Intel64"], ), requirements.PluginRequirement( name="pslist", plugin=pslist.PsList, version=(2, 2, 0) ), requirements.ListRequirement( name="pids", description="Filter on specific process IDs", element_type=int, optional=True, ), ]
def _get_libdl_libraries( self, proc_layer_name: str, vma_start: int ) -> interfaces.objects.ObjectInterface: """Get the ELF link map objects for the given VMA address Args: proc_layer_name (str): Name of the process layer vma_start (int): VMA start address Yields: ELF link map objects for the given VMA address """ elf_table_name = intermed.IntermediateSymbolTable.create( self.context, self.config_path, "linux", "elf", class_types=elf.class_types, ) elf_object = self.context.object( elf_table_name + constants.BANG + "Elf", offset=vma_start, layer_name=proc_layer_name, ) if not elf_object or not elf_object.is_valid(): return None kernel = self.context.modules[self.config["kernel"]] try: for link_map in elf_object.get_link_maps(kernel.symbol_table_name): if link_map.l_addr and link_map.l_name: yield link_map except exceptions.InvalidAddressException: # Protection against memory smear in this VMA pass def _get_libdl_maps( self, task: interfaces.objects.ObjectInterface, proc_layer_name: str ) -> interfaces.objects.ObjectInterface: """Get the ELF link maps objects for a task Args: task (task_struct): A reference task proc_layer_name (str): Name of the process layer Yields: ELF link map objects """ link_map_seen = set() for vma in task.mm.get_vma_iter(): for link_map in self._get_libdl_libraries(proc_layer_name, vma.vm_start): if link_map.l_addr in link_map_seen: continue yield link_map link_map_seen.add(link_map.l_addr) def _get_task_libraries( self, task: interfaces.objects.ObjectInterface ) -> Tuple[int, str]: """Get the task libraries from the ELF headers found within the memory maps Args: task (task_struct): The reference task Yields: Tuples with a ELF link map address and name """ proc_layer_name = task.add_process_layer() if not proc_layer_name: return for elf_link_map in self._get_libdl_maps(task, proc_layer_name): name = elf_link_map.get_name() if not name: continue yield elf_link_map.l_addr, name def _get_tasks_libraries( self, tasks: Iterable[interfaces.objects.ObjectInterface], ) -> Iterable[Tuple[str, int, int, str]]: """Get the task libraries from the ELF headers found within the memory maps for all the tasks. Args: tasks: An iterable of tasks Yields: Tuples with a task name, task tgid, an ELF link map address and name """ for task in tasks: task_name = utility.array_to_string(task.comm) for linkmap_addr, linkmap_name in self._get_task_libraries(task): yield task_name, task.tgid, linkmap_addr, linkmap_name def _format_fields(self, fields): task_name, task_pid, addr, name = fields return task_name, task_pid, format_hints.Hex(addr), name def _generator( self, tasks: Iterable[interfaces.objects.ObjectInterface] ) -> Iterable[Tuple[int, Tuple]]: for fields in self._get_tasks_libraries(tasks): yield 0, self._format_fields(fields)
[docs] def run(self): pids = self.config.get("pids") pid_filter = pslist.PsList.create_pid_filter(pids) tasks = pslist.PsList.list_tasks( self.context, self.config["kernel"], filter_func=pid_filter ) headers = [ ("Name", str), ("Pid", int), ("LoadAddress", format_hints.Hex), ("Path", str), ] return renderers.TreeGrid(headers, self._generator(tasks))