From 0e0daffc45827f82fdd992f1573e9448987cdd5f Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Sat, 1 Feb 2025 16:33:57 +1100 Subject: [PATCH] linux: Add kernel_symbol object extension --- .../framework/symbols/linux/__init__.py | 1 + .../symbols/linux/extensions/__init__.py | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index 53c7c4c88..f3880e4db 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -88,6 +88,7 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable): self.optional_set_type_class("maple_tree", extensions.maple_tree) self.optional_set_type_class("latch_tree_root", extensions.latch_tree_root) + self.optional_set_type_class("kernel_symbol", extensions.kernel_symbol) class LinuxUtilities(interfaces.configuration.VersionableInterface): diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 24260a798..41a7d9288 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -3100,3 +3100,64 @@ class latch_tree_root(objects.StructType): return None + +class kernel_symbol(objects.StructType): + + def _offset_to_ptr(self, off) -> int: + layer = self._context.layers[self.vol.layer_name] + long_mask = (1 << layer.bits_per_register) - 1 + return (self.vol.offset + off) & long_mask + + @property + def name(self) -> str: + if self.has_member("name_offset"): + # kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y + # See 7290d58095712a89f845e1bca05334796dd49ed2 + name_offset = self._offset_to_ptr(self.name_offset) + elif self.has_member("name"): + # kernel < 4.19 or CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=n + name_offset = self.member("name") + else: + raise AttributeError("Unsupported kernel_symbol type implementation") + + layer = self._context.layers[self.vol.layer_name] + name_bytes = layer.read(name_offset, linux_constants.KSYM_NAME_LEN) + + idx = name_bytes.find(b"\x00") + if idx != -1: + name_bytes = name_bytes[:idx] + + return name_bytes.decode("utf-8", errors="ignore") + + @property + def value(self) -> int: + if self.has_member("value_offset"): + # kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y + # See 7290d58095712a89f845e1bca05334796dd49ed2 + return self._offset_to_ptr(self.value_offset) + elif self.has_member("value"): + # kernel < 4.19 or CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=n + return self.member("value") + + raise AttributeError("Unsupported kernel_symbol type implementation") + + @property + def namespace(self) -> str: + if self.has_member("namespace_offset"): + # kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y + # See 7290d58095712a89f845e1bca05334796dd49ed2 + namespace_offset = self._offset_to_ptr(self.namespace_offset) + elif self.has_member("namespace"): + # kernel < 4.19 or CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=n + namespace_offset = self.member("namespace") + else: + raise AttributeError("Unsupported kernel_symbol type implementation") + + layer = self._context.layers[self.vol.layer_name] + namespace_bytes = layer.read(namespace_offset, linux_constants.KSYM_NAME_LEN) + + idx = namespace_bytes.find(b"\x00") + if idx != -1: + namespace_bytes = namespace_bytes[:idx] + + return namespace_bytes.decode("utf-8", errors="ignore")