Files
volatility3/volatility/framework/symbols/linux/extensions/__init__.py
T

144 lines
4.3 KiB
Python

import collections.abc
import typing
from volatility.framework import constants
from volatility.framework import objects, interfaces
from volatility.framework.objects import utility
from volatility.framework.symbols import generic
# Keep these in a basic module, to prevent import cycles when symbol providers require them
class task_struct(generic.GenericIntelProcess):
def add_process_layer(self,
config_prefix: str = None,
preferred_name: str = None) -> typing.Optional[str]:
"""Constructs a new layer based on the process's DTB.
Returns the name of the Layer or None.
"""
parent_layer = self._context.memory[self.vol.layer_name]
pgd = self.mm.pgd
if not pgd:
return None
dtb, layer_name = parent_layer.translate(pgd)
if not dtb:
return None
# Add the constructed layer and return the name
return self._add_process_layer(self._context, dtb, config_prefix, preferred_name)
class mm_struct(objects.Struct):
@property
def mmap_iter(self) -> typing.Iterable[interfaces.objects.ObjectInterface]:
"""Returns an iterator for the mmap list member of an mm_struct."""
if not self.mmap:
return
yield self.mmap
seen = {self.mmap.vol.offset}
link = self.mmap.vm_next
while link != 0 and link.vol.offset not in seen:
yield link
seen.add(link.vol.offset)
link = link.vm_next
class super_block(objects.Struct):
# include/linux/kdev_t.h
MINORBITS = 20
@property
def major(self) -> int:
return self.s_dev >> self.MINORBITS
@property
def minor(self) -> int:
return self.s_dev & ((1 << self.MINORBITS) - 1)
class vm_area_struct(objects.Struct):
# include/linux/mm.h
VM_READ = 0x00000001
VM_WRITE = 0x00000002
VM_EXEC = 0x00000004
@property
def flags(self) -> str:
"""Returns an rwx string representation of the flags in a vm_area_struct."""
retval = ""
vm_flags = self.vm_flags
for (bit, char) in ((self.VM_READ, 'r'), (self.VM_WRITE, 'w'), (self.VM_EXEC, 'x')):
if (vm_flags & bit) == bit:
retval = retval + char
else:
retval = retval + '-'
return retval
def page_offset(self) -> int:
if self.vm_file == 0:
return 0
return self.vm_pgoff << constants.linux.PAGE_SHIFT
class struct_file(objects.Struct):
@property
def full_path(self) -> str:
parts = [] # type: typing.List[str]
path = self.f_path
path_dentry = path.dentry
seen = set() # type: typing.Set[int]
while path_dentry != 0 and path_dentry.vol.offset not in seen:
name = utility.pointer_to_string(path_dentry.d_name.name, path_dentry.d_name.len)
if name == "/":
break
parts.insert(0, name)
seen.add(path_dentry.vol.offset)
path_dentry = path_dentry.d_parent
return "/" + "/".join(parts)
class list_head(objects.Struct, collections.abc.Iterable):
def to_list(self,
symbol_type: str,
member: str,
forward: bool = True,
sentinel: bool = True,
layer: typing.Optional[str] = None) -> typing.Iterator[interfaces.objects.ObjectInterface]:
"""Returns an iterator of the entries in the list."""
if layer is None:
layer = self.vol.layer_name
relative_offset = self._context.symbol_space.get_type(symbol_type).relative_child_offset(member)
direction = 'prev'
if forward:
direction = 'next'
link = getattr(self, direction).dereference()
if not sentinel:
yield self._context.object(symbol_type, layer, offset = self.vol.offset - relative_offset)
seen = {self.vol.offset}
while link.vol.offset not in seen:
obj = self._context.object(symbol_type, layer, offset = link.vol.offset - relative_offset)
yield obj
seen.add(link.vol.offset)
link = getattr(link, direction).dereference()
def __iter__(self) -> typing.Iterator[interfaces.objects.ObjectInterface]:
return self.to_list(self.vol.parent.vol.type_name, self.vol.member_name)