From 1480aca4538739b45b9d792f8ce7886170f807bd Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Thu, 22 Jul 2021 22:40:09 +0100 Subject: [PATCH] Linux: Update all plugins to ModuleRequirement --- volatility3/framework/plugins/linux/bash.py | 13 +++---- .../framework/plugins/linux/check_afinfo.py | 12 +++---- .../framework/plugins/linux/check_creds.py | 17 ++++----- .../framework/plugins/linux/check_idt.py | 29 +++++++-------- .../framework/plugins/linux/check_modules.py | 30 ++++++++-------- .../framework/plugins/linux/check_syscall.py | 35 ++++++++++--------- volatility3/framework/plugins/linux/elfs.py | 10 ++---- .../plugins/linux/keyboard_notifiers.py | 24 ++++++------- volatility3/framework/plugins/linux/lsmod.py | 18 ++++------ volatility3/framework/plugins/linux/lsof.py | 14 ++++---- .../framework/plugins/linux/malfind.py | 13 +++---- volatility3/framework/plugins/linux/proc.py | 10 ++---- volatility3/framework/plugins/linux/pslist.py | 21 ++++------- volatility3/framework/plugins/linux/pstree.py | 5 ++- .../framework/plugins/linux/tty_check.py | 26 ++++++-------- 15 files changed, 116 insertions(+), 161 deletions(-) diff --git a/volatility3/framework/plugins/linux/bash.py b/volatility3/framework/plugins/linux/bash.py index 3e8ac5890..471f4cbe7 100644 --- a/volatility3/framework/plugins/linux/bash.py +++ b/volatility3/framework/plugins/linux/bash.py @@ -21,16 +21,13 @@ from volatility3.plugins.linux import pslist class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): """Recovers bash command history from memory.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)), + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)), requirements.ListRequirement(name = 'pid', element_type = int, description = "Process IDs to include (all other processes are excluded)", @@ -38,7 +35,7 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): ] def _generator(self, tasks): - is_32bit = not symbols.symbol_table_is_64bit(self.context, self.config["vmlinux"]) + is_32bit = not symbols.symbol_table_is_64bit(self.context, self.config["vmlinux.symbol_table_name"]) if is_32bit: pack_format = "I" bash_json_file = "bash32" @@ -93,7 +90,6 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): ("Command", str)], self._generator( pslist.PsList.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = filter_func))) @@ -102,7 +98,6 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface): for row in self._generator( pslist.PsList.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = filter_func)): _depth, row_data = row diff --git a/volatility3/framework/plugins/linux/check_afinfo.py b/volatility3/framework/plugins/linux/check_afinfo.py index 29e697540..9105247be 100644 --- a/volatility3/framework/plugins/linux/check_afinfo.py +++ b/volatility3/framework/plugins/linux/check_afinfo.py @@ -6,7 +6,7 @@ found in Linux's /proc file system.""" import logging from typing import List -from volatility3.framework import exceptions, interfaces, contexts +from volatility3.framework import exceptions, interfaces from volatility3.framework import renderers from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import plugins @@ -18,15 +18,12 @@ vollog = logging.getLogger(__name__) class Check_afinfo(plugins.PluginInterface): """Verifies the operation function pointers of network protocols.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols") + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), ] # returns whether the symbol is found within the kernel (system.map) or not @@ -63,7 +60,8 @@ class Check_afinfo(plugins.PluginInterface): yield var_name, "show", var.seq_show def _generator(self): - vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) + + vmlinux = self.context.modules[self.config['vmlinux']] op_members = vmlinux.get_type('file_operations').members seq_members = vmlinux.get_type('seq_operations').members diff --git a/volatility3/framework/plugins/linux/check_creds.py b/volatility3/framework/plugins/linux/check_creds.py index 20e3d26fb..28f3d178b 100644 --- a/volatility3/framework/plugins/linux/check_creds.py +++ b/volatility3/framework/plugins/linux/check_creds.py @@ -4,7 +4,7 @@ import logging -from volatility3.framework import interfaces, renderers, constants +from volatility3.framework import interfaces, renderers from volatility3.framework.configuration import requirements from volatility3.plugins.linux import pslist @@ -14,22 +14,19 @@ vollog = logging.getLogger(__name__) class Check_creds(interfaces.plugins.PluginInterface): """Checks if any processes are sharing credential structures""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls): return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)) + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)) ] def _generator(self): - # vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) + vmlinux = self.context.modules[self.config['vmlinux']] - type_task = self.context.symbol_space.get_type(self.config['vmlinux'] + constants.BANG + "task_struct") + type_task = vmlinux.get_type("task_struct") if not type_task.has_member("cred"): raise TypeError( @@ -40,7 +37,7 @@ class Check_creds(interfaces.plugins.PluginInterface): creds = {} - tasks = pslist.PsList.list_tasks(self.context, self.config['primary'], self.config['vmlinux']) + tasks = pslist.PsList.list_tasks(self.context, vmlinux.name) for task in tasks: diff --git a/volatility3/framework/plugins/linux/check_idt.py b/volatility3/framework/plugins/linux/check_idt.py index f171ab846..016717841 100644 --- a/volatility3/framework/plugins/linux/check_idt.py +++ b/volatility3/framework/plugins/linux/check_idt.py @@ -5,7 +5,7 @@ import logging from typing import List -from volatility3.framework import interfaces, renderers, contexts, symbols +from volatility3.framework import interfaces, renderers, symbols from volatility3.framework.configuration import requirements from volatility3.framework.renderers import format_hints from volatility3.framework.symbols import linux @@ -17,32 +17,28 @@ vollog = logging.getLogger(__name__) class Check_idt(interfaces.plugins.PluginInterface): """ Checks if the IDT has been altered """ - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (1, 0, 0)), - requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0)) + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (2, 0, 0)), + requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (2, 0, 0)) ] def _generator(self): - vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) + vmlinux = self.context.modules[self.config['vmlinux']] - modules = lsmod.Lsmod.list_modules(self.context, self.config['primary'], self.config['vmlinux']) + modules = lsmod.Lsmod.list_modules(self.context, vmlinux.name) - handlers = linux.LinuxUtilities.generate_kernel_handler_info(self.context, self.config['primary'], - self.config['vmlinux'], modules) + handlers = linux.LinuxUtilities.generate_kernel_handler_info(self.context, vmlinux.name, modules) - is_32bit = not symbols.symbol_table_is_64bit(self.context, self.config["vmlinux"]) + is_32bit = not symbols.symbol_table_is_64bit(self.context, vmlinux.symbol_table_name) idt_table_size = 256 - address_mask = self.context.layers[self.config['primary']].address_mask + address_mask = self.context.layers[vmlinux.layer_name].address_mask # hw handlers + system call check_idxs = list(range(0, 20)) + [128] @@ -65,7 +61,8 @@ class Check_idt(interfaces.plugins.PluginInterface): table = vmlinux.object(object_type = 'array', offset = addrs.vol.offset, subtype = vmlinux.get_type(idt_type), - count = idt_table_size) + count = idt_table_size, + absolute = True) for i in check_idxs: ent = table[i] @@ -88,7 +85,7 @@ class Check_idt(interfaces.plugins.PluginInterface): idt_addr = idt_addr & address_mask - module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(self.context, handlers, idt_addr) + module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(vmlinux, handlers, idt_addr) yield (0, [format_hints.Hex(i), format_hints.Hex(idt_addr), module_name, symbol_name]) diff --git a/volatility3/framework/plugins/linux/check_modules.py b/volatility3/framework/plugins/linux/check_modules.py index 449046e86..362dce692 100644 --- a/volatility3/framework/plugins/linux/check_modules.py +++ b/volatility3/framework/plugins/linux/check_modules.py @@ -5,7 +5,7 @@ import logging from typing import List -from volatility3.framework import interfaces, renderers, exceptions, constants, contexts +from volatility3.framework import interfaces, renderers, exceptions, constants from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import plugins from volatility3.framework.objects import utility @@ -18,19 +18,19 @@ vollog = logging.getLogger(__name__) class Check_modules(plugins.PluginInterface): """Compares module list to sysfs info, if available""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0)) + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (2, 0, 0)) ] - def get_kset_modules(self, vmlinux): + @classmethod + def get_kset_modules(self, context: interfaces.context.ContextInterface, vmlinux_name: str): + + vmlinux = context.modules[vmlinux_name] try: module_kset = vmlinux.object_from_symbol("module_kset") @@ -44,12 +44,12 @@ class Check_modules(plugins.PluginInterface): ret = {} - kobj_off = self.context.symbol_space.get_type(self.config['vmlinux'] + constants.BANG + - 'module_kobject').relative_child_offset('kobj') + kobj_off = vmlinux.get_type('module_kobject').relative_child_offset('kobj') - for kobj in module_kset.list.to_list(vmlinux.name + constants.BANG + "kobject", "entry"): + for kobj in module_kset.list.to_list(vmlinux.symbol_table_name + constants.BANG + "kobject", "entry"): - mod_kobj = vmlinux.object(object_type = "module_kobject", offset = kobj.vol.offset - kobj_off) + mod_kobj = vmlinux.object(object_type = "module_kobject", offset = kobj.vol.offset - kobj_off, + absolute = True) mod = mod_kobj.mod @@ -60,13 +60,11 @@ class Check_modules(plugins.PluginInterface): return ret def _generator(self): - vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) - - kset_modules = self.get_kset_modules(vmlinux) + kset_modules = self.get_kset_modules(self.context, self.config['vmlinux']) lsmod_modules = set( str(utility.array_to_string(modules.name)) - for modules in lsmod.Lsmod.list_modules(self.context, self.config['primary'], self.config['vmlinux'])) + for modules in lsmod.Lsmod.list_modules(self.context, self.config['vmlinux'])) for mod_name in set(kset_modules.keys()).difference(lsmod_modules): yield (0, (format_hints.Hex(kset_modules[mod_name]), str(mod_name))) diff --git a/volatility3/framework/plugins/linux/check_syscall.py b/volatility3/framework/plugins/linux/check_syscall.py index b845ad4aa..3acd2877a 100644 --- a/volatility3/framework/plugins/linux/check_syscall.py +++ b/volatility3/framework/plugins/linux/check_syscall.py @@ -6,7 +6,7 @@ found in Linux's /proc file system.""" import logging from typing import List -from volatility3.framework import exceptions, interfaces, contexts +from volatility3.framework import exceptions, interfaces from volatility3.framework import renderers, constants from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import plugins @@ -25,24 +25,26 @@ except ImportError: class Check_syscall(plugins.PluginInterface): """Check system call table for hooks.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols") + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), ] def _get_table_size_next_symbol(self, table_addr, ptr_sz, vmlinux): """Returns the size of the table based on the next symbol.""" ret = 0 - sym_table = self.context.symbol_space[vmlinux.name] - - sorted_symbols = sorted([(sym_table.get_symbol(sn).address, sn) for sn in sym_table.symbols]) + symbol_list = [] + for sn in vmlinux.symbols: + try: + # When requesting the symbol from the module, a full resolve is performed + symbol_list.append((vmlinux.get_symbol(sn).address, sn)) + except exceptions.SymbolError: + pass + sorted_symbols = sorted(symbol_list) sym_address = 0 @@ -62,7 +64,8 @@ class Check_syscall(plugins.PluginInterface): accurate.""" return len( - [sym for sym in self.context.symbol_space[vmlinux.name].symbols if sym.startswith("__syscall_meta__")]) + [sym for sym in self.context.symbol_space[vmlinux.symbol_table_name].symbols if + sym.startswith("__syscall_meta__")]) def _get_table_info_other(self, table_addr, ptr_sz, vmlinux): table_size_meta = self._get_table_size_meta(vmlinux) @@ -93,12 +96,12 @@ class Check_syscall(plugins.PluginInterface): md = capstone.Cs(capstone.CS_ARCH_X86, mode) try: - func_addr = self.context.symbol_space.get_symbol(vmlinux.name + constants.BANG + syscall_entry_func).address + func_addr = vmlinux.get_symbol(syscall_entry_func).address except exceptions.SymbolError as e: # if we can't find the disassemble function then bail and rely on a different method return 0 - data = self.context.layers.read(self.config['primary'], func_addr, 6) + data = self.context.layers.read(self.config['vmlinux.layer_name'], func_addr, 6) for (address, size, mnemonic, op_str) in md.disasm_lite(data, func_addr): if mnemonic == 'CMP': @@ -108,7 +111,7 @@ class Check_syscall(plugins.PluginInterface): return table_size def _get_table_info(self, vmlinux, table_name, ptr_sz): - table_sym = self.context.symbol_space.get_symbol(vmlinux.name + constants.BANG + table_name) + table_sym = vmlinux.get_symbol(table_name) table_size = self._get_table_info_disassembly(ptr_sz, vmlinux) @@ -123,7 +126,7 @@ class Check_syscall(plugins.PluginInterface): # TODO - add finding and parsing unistd.h once cached file enumeration is added def _generator(self): - vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) + vmlinux = self.context.modules[self.config['vmlinux']] ptr_sz = vmlinux.get_type("pointer").size if ptr_sz == 4: @@ -143,7 +146,7 @@ class Check_syscall(plugins.PluginInterface): # enabled in order to support 32 bit programs and libraries # if the symbol isn't there then the support isn't in the kernel and so we skip it try: - ia32_symbol = self.context.symbol_space.get_symbol(vmlinux.name + constants.BANG + "ia32_sys_call_table") + ia32_symbol = vmlinux.get_symbol("ia32_sys_call_table") except exceptions.SymbolError: ia32_symbol = None @@ -161,7 +164,7 @@ class Check_syscall(plugins.PluginInterface): if not call_addr: continue - symbols = list(self.context.symbol_space.get_symbols_by_location(call_addr)) + symbols = list(vmlinux.get_symbols_by_absolute_location(call_addr)) if len(symbols) > 0: sym_name = str(symbols[0].split(constants.BANG)[1]) if constants.BANG in symbols[0] else \ diff --git a/volatility3/framework/plugins/linux/elfs.py b/volatility3/framework/plugins/linux/elfs.py index 89909f4ff..3fcb017cd 100644 --- a/volatility3/framework/plugins/linux/elfs.py +++ b/volatility3/framework/plugins/linux/elfs.py @@ -17,16 +17,13 @@ from volatility3.plugins.linux import pslist class Elfs(plugins.PluginInterface): """Lists all memory mapped ELF files for all processes.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)), + requirements.ModuleRequirement(name = 'vmlinux', 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, @@ -59,6 +56,5 @@ class Elfs(plugins.PluginInterface): ("End", format_hints.Hex), ("File Path", str)], self._generator( pslist.PsList.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = filter_func))) diff --git a/volatility3/framework/plugins/linux/keyboard_notifiers.py b/volatility3/framework/plugins/linux/keyboard_notifiers.py index 290c0a180..012632bb6 100644 --- a/volatility3/framework/plugins/linux/keyboard_notifiers.py +++ b/volatility3/framework/plugins/linux/keyboard_notifiers.py @@ -4,7 +4,7 @@ import logging -from volatility3.framework import interfaces, renderers, contexts, exceptions +from volatility3.framework import interfaces, renderers, exceptions from volatility3.framework.configuration import requirements from volatility3.framework.renderers import format_hints from volatility3.framework.symbols import linux @@ -16,26 +16,22 @@ vollog = logging.getLogger(__name__) class Keyboard_notifiers(interfaces.plugins.PluginInterface): """Parses the keyboard notifier call chain""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls): return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0)), - requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (1, 0, 0)) + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (2, 0, 0)), + requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (2, 0, 0)) ] def _generator(self): - vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) + vmlinux = self.context.modules[self.config['vmlinux']] - modules = lsmod.Lsmod.list_modules(self.context, self.config['primary'], self.config['vmlinux']) + modules = lsmod.Lsmod.list_modules(self.context, vmlinux.name) - handlers = linux.LinuxUtilities.generate_kernel_handler_info(self.context, self.config['primary'], - self.config['vmlinux'], modules) + handlers = linux.LinuxUtilities.generate_kernel_handler_info(self.context, vmlinux.name, modules) try: knl_addr = vmlinux.object_from_symbol("keyboard_notifier_list") @@ -49,12 +45,12 @@ class Keyboard_notifiers(interfaces.plugins.PluginInterface): "This means you are either analyzing an unsupported kernel version or that your symbol table is corrupt." ) - knl = vmlinux.object(object_type = "atomic_notifier_head", offset = knl_addr.vol.offset) + knl = vmlinux.object(object_type = "atomic_notifier_head", offset = knl_addr.vol.offset, absolute = True) for call_back in linux.LinuxUtilities.walk_internal_list(vmlinux, "notifier_block", "next", knl.head): call_addr = call_back.notifier_call - module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(self.context, handlers, call_addr) + module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(vmlinux, handlers, call_addr) yield (0, [format_hints.Hex(call_addr), module_name, symbol_name]) diff --git a/volatility3/framework/plugins/linux/lsmod.py b/volatility3/framework/plugins/linux/lsmod.py index 2d390cc82..a871ebed9 100644 --- a/volatility3/framework/plugins/linux/lsmod.py +++ b/volatility3/framework/plugins/linux/lsmod.py @@ -7,7 +7,6 @@ found in Linux's /proc file system.""" import logging from typing import List, Iterable -from volatility3.framework import contexts from volatility3.framework import exceptions, renderers, constants, interfaces from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import plugins @@ -20,21 +19,18 @@ vollog = logging.getLogger(__name__) class Lsmod(plugins.PluginInterface): """Lists loaded kernel modules.""" - _required_framework_version = (1, 0, 0) - _version = (1, 0, 0) + _required_framework_version = (1, 2, 0) + _version = (2, 0, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols") + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), ] @classmethod - def list_modules(cls, context: interfaces.context.ContextInterface, layer_name: str, - vmlinux_symbols: str) -> Iterable[interfaces.objects.ObjectInterface]: + def list_modules(cls, context: interfaces.context.ContextInterface, vmlinux_module_name: str) -> Iterable[ + interfaces.objects.ObjectInterface]: """Lists all the modules in the primary layer. Args: @@ -47,7 +43,7 @@ class Lsmod(plugins.PluginInterface): This function will throw a SymbolError exception if kernel module support is not enabled. """ - vmlinux = contexts.Module(context, vmlinux_symbols, layer_name, 0) + vmlinux = context.modules[vmlinux_module_name] modules = vmlinux.object_from_symbol(symbol_name = "modules").cast("list_head") @@ -58,7 +54,7 @@ class Lsmod(plugins.PluginInterface): def _generator(self): try: - for module in self.list_modules(self.context, self.config['primary'], self.config['vmlinux']): + for module in self.list_modules(self.context, self.config['vmlinux']): mod_size = module.get_init_size() + module.get_core_size() diff --git a/volatility3/framework/plugins/linux/lsof.py b/volatility3/framework/plugins/linux/lsof.py index 153d28f6a..3b21d9682 100644 --- a/volatility3/framework/plugins/linux/lsof.py +++ b/volatility3/framework/plugins/linux/lsof.py @@ -19,17 +19,14 @@ vollog = logging.getLogger(__name__) class Lsof(plugins.PluginInterface): """Lists all memory maps for all processes.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)), - requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (1, 0, 0)), + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)), + requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (2, 0, 0)), requirements.ListRequirement(name = 'pid', description = 'Filter on specific process IDs', element_type = int, @@ -37,6 +34,8 @@ class Lsof(plugins.PluginInterface): ] def _generator(self, tasks): + vmlinux = self.context.modules[self.config['vmlinux']] + symbol_table = None for task in tasks: if symbol_table is None: @@ -57,6 +56,5 @@ class Lsof(plugins.PluginInterface): return renderers.TreeGrid([("PID", int), ("Process", str), ("FD", int), ("Path", str)], self._generator( pslist.PsList.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = filter_func))) diff --git a/volatility3/framework/plugins/linux/malfind.py b/volatility3/framework/plugins/linux/malfind.py index 149222f37..c7fbd9ad1 100644 --- a/volatility3/framework/plugins/linux/malfind.py +++ b/volatility3/framework/plugins/linux/malfind.py @@ -15,16 +15,13 @@ from volatility3.plugins.linux import pslist class Malfind(interfaces.plugins.PluginInterface): """Lists process memory ranges that potentially contain injected code.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)), + requirements.ModuleRequirement(name = 'vmlinux', 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, @@ -48,7 +45,8 @@ class Malfind(interfaces.plugins.PluginInterface): def _generator(self, tasks): # determine if we're on a 32 or 64 bit kernel - if self.context.symbol_space.get_type(self.config["vmlinux"] + constants.BANG + "pointer").size == 4: + if self.context.symbol_space.get_type( + self.config["vmlinux.symbol_table_name"] + constants.BANG + "pointer").size == 4: is_32bit_arch = True else: is_32bit_arch = False @@ -75,6 +73,5 @@ class Malfind(interfaces.plugins.PluginInterface): ("Disasm", interfaces.renderers.Disassembly)], self._generator( pslist.PsList.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = filter_func))) diff --git a/volatility3/framework/plugins/linux/proc.py b/volatility3/framework/plugins/linux/proc.py index 8bd0db538..893646d04 100644 --- a/volatility3/framework/plugins/linux/proc.py +++ b/volatility3/framework/plugins/linux/proc.py @@ -15,17 +15,14 @@ from volatility3.plugins.linux import pslist class Maps(plugins.PluginInterface): """Lists all memory maps for all processes.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls): # 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 = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)), + requirements.ModuleRequirement(name = 'vmlinux', 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, @@ -68,6 +65,5 @@ class Maps(plugins.PluginInterface): ("File Path", str)], self._generator( pslist.PsList.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = filter_func))) diff --git a/volatility3/framework/plugins/linux/pslist.py b/volatility3/framework/plugins/linux/pslist.py index 78fce978b..14295be06 100644 --- a/volatility3/framework/plugins/linux/pslist.py +++ b/volatility3/framework/plugins/linux/pslist.py @@ -1,10 +1,9 @@ # 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 Callable, Iterable, List, Any -from volatility3.framework import renderers, interfaces, contexts +from volatility3.framework import renderers, interfaces from volatility3.framework.configuration import requirements from volatility3.framework.objects import utility @@ -12,17 +11,14 @@ from volatility3.framework.objects import utility class PsList(interfaces.plugins.PluginInterface): """Lists the processes present in a particular linux memory image.""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) - _version = (1, 0, 0) + _version = (2, 0, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), + requirements.ModuleRequirement(name = 'vmlinux'), requirements.ListRequirement(name = 'pid', description = 'Filter on specific process IDs', element_type = int, @@ -53,7 +49,6 @@ class PsList(interfaces.plugins.PluginInterface): def _generator(self): for task in self.list_tasks(self.context, - self.config['primary'], self.config['vmlinux'], filter_func = self.create_pid_filter(self.config.get('pid', None))): pid = task.pid @@ -67,20 +62,18 @@ class PsList(interfaces.plugins.PluginInterface): def list_tasks( cls, context: interfaces.context.ContextInterface, - layer_name: str, - vmlinux_symbols: str, + vmlinux_module_name: 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 - vmlinux_symbols: The name of the table containing the kernel symbols + vmlinux_module_name: The name of the kernel module on which to operate Yields: Process objects """ - vmlinux = contexts.Module(context, vmlinux_symbols, layer_name, 0) + vmlinux = context.modules[vmlinux_module_name] init_task = vmlinux.object_from_symbol(symbol_name = "init_task") diff --git a/volatility3/framework/plugins/linux/pstree.py b/volatility3/framework/plugins/linux/pstree.py index a187ea907..2f11cf5ec 100644 --- a/volatility3/framework/plugins/linux/pstree.py +++ b/volatility3/framework/plugins/linux/pstree.py @@ -10,8 +10,6 @@ class PsTree(pslist.PsList): """Plugin for listing processes in a tree based on their parent process ID.""" - _required_framework_version = (1, 0, 0) - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._processes = {} @@ -36,7 +34,8 @@ class PsTree(pslist.PsList): def _generator(self): """Generates the.""" - for proc in self.list_tasks(self.context, self.config['primary'], self.config['vmlinux']): + for proc in self.list_tasks(self.context, self.config['vmlinux.layer_name'], + self.config['vmlinux.symbol_table_name']): self._processes[proc.pid] = proc # Build the child/level maps diff --git a/volatility3/framework/plugins/linux/tty_check.py b/volatility3/framework/plugins/linux/tty_check.py index f633b9985..f4a4a2820 100644 --- a/volatility3/framework/plugins/linux/tty_check.py +++ b/volatility3/framework/plugins/linux/tty_check.py @@ -5,7 +5,7 @@ import logging from typing import List -from volatility3.framework import interfaces, renderers, exceptions, constants, contexts +from volatility3.framework import interfaces, renderers, exceptions, constants from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import plugins from volatility3.framework.objects import utility @@ -19,26 +19,22 @@ vollog = logging.getLogger(__name__) class tty_check(plugins.PluginInterface): """Checks tty devices for hooks""" - _required_framework_version = (1, 0, 0) + _required_framework_version = (1, 2, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: return [ - requirements.TranslationLayerRequirement(name = 'primary', - description = 'Memory layer for the kernel', - architectures = ["Intel32", "Intel64"]), - requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"), - requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0)), - requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (1, 0, 0)) + requirements.ModuleRequirement(name = 'vmlinux', architectures = ["Intel32", "Intel64"]), + requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (2, 0, 0)), + requirements.VersionRequirement(name = 'linuxutils', component = linux.LinuxUtilities, version = (2, 0, 0)) ] def _generator(self): - vmlinux = contexts.Module(self.context, self.config['vmlinux'], self.config['primary'], 0) + vmlinux = self.context.modules[self.config['vmlinux']] - modules = lsmod.Lsmod.list_modules(self.context, self.config['primary'], self.config['vmlinux']) + modules = lsmod.Lsmod.list_modules(self.context, vmlinux.name) - handlers = linux.LinuxUtilities.generate_kernel_handler_info(self.context, self.config['primary'], - self.config['vmlinux'], modules) + handlers = linux.LinuxUtilities.generate_kernel_handler_info(self.context, vmlinux.name, modules) try: tty_drivers = vmlinux.object_from_symbol("tty_drivers").cast("list_head") @@ -52,12 +48,12 @@ class tty_check(plugins.PluginInterface): "This means you are either analyzing an unsupported kernel version or that your symbol table is corrupt." ) - for tty in tty_drivers.to_list(vmlinux.name + constants.BANG + "tty_driver", "tty_drivers"): + for tty in tty_drivers.to_list(vmlinux.symbol_table_name + constants.BANG + "tty_driver", "tty_drivers"): try: ttys = utility.array_of_pointers(tty.ttys.dereference(), count = tty.num, - subtype = vmlinux.name + constants.BANG + "tty_struct", + subtype = vmlinux.symbol_table_name + constants.BANG + "tty_struct", context = self.context) except exceptions.PagedInvalidAddressException: continue @@ -71,7 +67,7 @@ class tty_check(plugins.PluginInterface): recv_buf = tty_dev.ldisc.ops.receive_buf - module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(self.context, handlers, recv_buf) + module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(vmlinux, handlers, recv_buf) yield (0, (name, format_hints.Hex(recv_buf), module_name, symbol_name))