diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 0f7ddfac3..5364fcbda 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -176,37 +176,43 @@ class module(generic.GenericIntelProcess): """Get the name of the module as a string""" return utility.array_to_string(self.name) - def _get_sect_count(self, grp): + def _get_sect_count(self, grp) -> int: """Try to determine the number of valid sections""" + symbol_table_name = self.get_symbol_table_name() arr = self._context.object( - self.get_symbol_table_name() + constants.BANG + "array", + symbol_table_name + constants.BANG + "array", layer_name=self.vol.layer_name, offset=grp.attrs, subtype=self._context.symbol_space.get_type( - self.get_symbol_table_name() + constants.BANG + "pointer" + symbol_table_name + constants.BANG + "pointer" ), count=25, ) idx = 0 - while arr[idx]: + while arr[idx] and arr[idx].is_readable(): idx = idx + 1 return idx - def get_sections(self): - """Get sections of the module""" + @functools.cached_property + def number_of_sections(self) -> int: if self.sect_attrs.has_member("nsections"): - num_sects = self.sect_attrs.nsections - else: - num_sects = self._get_sect_count(self.sect_attrs.grp) + return self.sect_attrs.nsections + + return self._get_sect_count(self.sect_attrs.grp) + + def get_sections(self) -> Iterable[interfaces.objects.ObjectInterface]: + """Get a list of section attributes for the given module.""" + + symbol_table_name = self.get_symbol_table_name() arr = self._context.object( - self.get_symbol_table_name() + constants.BANG + "array", + symbol_table_name + constants.BANG + "array", layer_name=self.vol.layer_name, offset=self.sect_attrs.attrs.vol.offset, subtype=self._context.symbol_space.get_type( - self.get_symbol_table_name() + constants.BANG + "module_sect_attr" + symbol_table_name + constants.BANG + "module_sect_attr" ), - count=num_sects, + count=self.number_of_sections, ) yield from arr @@ -309,6 +315,27 @@ class module(generic.GenericIntelProcess): raise AttributeError("Unable to get strtab") + @property + def section_typetab(self): + if self.has_member("kallsyms") and self.kallsyms.has_member("typetab"): + # kernels >= 4.5 8244062ef1e54502ef55f54cced659913f244c3e: kallsyms was added + # kernels >= 5.2 1c7651f43777cdd59c1aaa82c87324d3e7438c7b: types have its own array + return self.kallsyms.typetab + + raise AttributeError("Unable to get typetab section, it needs a kernel >= 5.2") + + def get_symbol_type(self, symbol, symbol_index): + if self.has_member("kallsyms") and self.kallsyms.has_member("typetab"): + # kernels >= 5.2 1c7651f43777cdd59c1aaa82c87324d3e7438c7b types have its own array + layer = self._context.layers[self.vol.layer_name] + sym_type = layer.read(self.section_typetab + symbol_index, 1) + sym_type = sym_type.decode("utf-8", errors="ignore") + else: + # kernels < 5.2 the type was stored in the st_info + sym_type = chr(symbol.st_info) + + return sym_type + class task_struct(generic.GenericIntelProcess): def is_valid(self) -> bool: