mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-13 05:07:38 +02:00
1774: consolidate module helpers
This commit is contained in:
@@ -38,56 +38,11 @@ vollog = logging.getLogger(__name__)
|
||||
class ModuleExtract(interfaces.configuration.VersionableInterface):
|
||||
"""Extracts Linux kernel module structures into an analyzable ELF file"""
|
||||
|
||||
_version = (1, 0, 1)
|
||||
_version = (1, 0, 2)
|
||||
_required_framework_version = (2, 25, 0)
|
||||
|
||||
framework.require_interface_version(*_required_framework_version)
|
||||
|
||||
@classmethod
|
||||
def _get_module_section_count(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
vmlinux_name: str,
|
||||
module: extensions.module,
|
||||
grp: interfaces.objects.ObjectInterface,
|
||||
) -> int:
|
||||
"""
|
||||
Used to manually determine the section count for kernels that do not track
|
||||
this count directly within the attribute structures
|
||||
"""
|
||||
kernel = context.modules[vmlinux_name]
|
||||
|
||||
count = 0
|
||||
|
||||
try:
|
||||
if grp.has_member("bin_attrs"):
|
||||
arr_offset = grp.bin_attrs
|
||||
else:
|
||||
arr_offset = grp.attrs
|
||||
|
||||
array = kernel.object(
|
||||
object_type="array",
|
||||
offset=arr_offset,
|
||||
sub_type=kernel.get_type("pointer"),
|
||||
count=50,
|
||||
absolute=True,
|
||||
)
|
||||
|
||||
# Walk up to 50 sections counting until we reach the end or a page fault
|
||||
for sect in array:
|
||||
if sect.vol.offset == 0:
|
||||
break
|
||||
|
||||
count += 1
|
||||
|
||||
except exceptions.InvalidAddressException:
|
||||
# Use whatever count we reached before the error
|
||||
vollog.debug(
|
||||
f"Exception hit counting sections for module at {module.vol.offset:#x}"
|
||||
)
|
||||
|
||||
return count
|
||||
|
||||
@classmethod
|
||||
def _find_section(
|
||||
cls, section_lookups: List[Tuple[str, int, int, int]], sym_address: int
|
||||
@@ -266,54 +221,6 @@ class ModuleExtract(interfaces.configuration.VersionableInterface):
|
||||
|
||||
return sym_table_data
|
||||
|
||||
@classmethod
|
||||
def _enumerate_original_sections(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
vmlinux_name: str,
|
||||
module: extensions.module,
|
||||
) -> Optional[Dict[int, str]]:
|
||||
"""
|
||||
Enumerates the module's sections as maintained by the kernel after load time
|
||||
'Early' sections like .init.text and .init.data are discarded after module
|
||||
initialization, so they are not expected to be in memory during extraction
|
||||
"""
|
||||
if hasattr(module.sect_attrs, "nsections"):
|
||||
num_sections = module.sect_attrs.nsections
|
||||
else:
|
||||
num_sections = cls._get_module_section_count(
|
||||
context, vmlinux_name, module.sect_attrs.grp
|
||||
)
|
||||
|
||||
if num_sections > 1024 or num_sections == 0:
|
||||
vollog.debug(
|
||||
f"Invalid number of sections ({num_sections}) for module at offset {module.vol.offset:#x}"
|
||||
)
|
||||
return None
|
||||
|
||||
vmlinux = context.modules[vmlinux_name]
|
||||
|
||||
# This is declared as a zero sized array, so we create ourselves
|
||||
attribute_type = module.sect_attrs.attrs.vol.subtype
|
||||
|
||||
sect_array = vmlinux.object(
|
||||
object_type="array",
|
||||
subtype=attribute_type,
|
||||
offset=module.sect_attrs.attrs.vol.offset,
|
||||
count=num_sections,
|
||||
absolute=True,
|
||||
)
|
||||
|
||||
sections: Dict[int, str] = {}
|
||||
|
||||
# for each section, gather its name and address
|
||||
for index, section in enumerate(sect_array):
|
||||
name = section.get_name()
|
||||
|
||||
sections[section.address] = name
|
||||
|
||||
return sections
|
||||
|
||||
@classmethod
|
||||
def _parse_sections(
|
||||
cls,
|
||||
@@ -330,10 +237,12 @@ class ModuleExtract(interfaces.configuration.VersionableInterface):
|
||||
The data of .strtab is read directly off the module structure and not its section
|
||||
as the section from the original module has no meaning after loading as the kernel does not reference it.
|
||||
"""
|
||||
original_sections = cls._enumerate_original_sections(
|
||||
context, vmlinux_name, module
|
||||
)
|
||||
if original_sections is None:
|
||||
original_sections = {}
|
||||
for index, section in enumerate(module.get_sections()):
|
||||
name = section.get_name()
|
||||
original_sections[section.address] = name
|
||||
|
||||
if not original_sections:
|
||||
return None
|
||||
|
||||
kernel = context.modules[vmlinux_name]
|
||||
|
||||
Reference in New Issue
Block a user