Files
volatility3/volatility/framework/interfaces/objects.py
T

139 lines
5.0 KiB
Python

"""
Created on 6 May 2013
@author: mike
"""
import collections.abc
from abc import ABCMeta, abstractmethod
from volatility.framework import validity
from volatility.framework.interfaces import context as context_module
class ReadOnlyMapping(validity.ValidityRoutines, collections.abc.Mapping):
"""A read-only mapping of various values that offer attribute access as well"""
def __init__(self, dict):
self._dict = dict
def __getattr__(self, attr):
"""Returns the item as an attribute"""
if attr in self._dict:
return self._dict[attr]
raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + '"')
def __getitem__(self, name):
"""Returns the item requested"""
return self._dict[name]
def __iter__(self):
"""Returns an iterator of the dictionary items"""
return self._dict.__iter__()
def __len__(self):
"""Returns the length of the internal dictionary"""
return len(self._dict)
class ObjectInformation(ReadOnlyMapping):
"""Contains information useful/pertinent only to an individual object (like an instance)"""
def __init__(self, layer_name, offset, member_name = None, parent = None):
self._type_check(offset, int)
if parent:
self._type_check(parent, ObjectInterface)
ReadOnlyMapping.__init__(self, {'layer_name': layer_name,
'offset': offset,
'member_name': member_name,
'parent': parent})
class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta):
""" A base object required to be the ancestor of every object used in volatility """
def __init__(self, context, structure_name, object_info, **kwargs):
# Since objects are likely to be instantiated often,
# we're only checking that context, offset and parent
# Everything else may be wrong, but that will get caught later on
self._type_check(context, context_module.ContextInterface)
self._type_check(object_info, ObjectInformation)
# Add an empty dictionary at the start to allow objects to add their own data to the volinfo object
#
# NOTE:
# This allows objects to MASSIVELY MESS with their own internal representation!!!
# Changes to offset, structure_name, etc should NEVER be done
#
self._volinfo = collections.ChainMap({}, object_info, {'structure_name': structure_name}, kwargs)
self._context = context
@property
def volinfo(self):
"""Returns the volatility specific object information"""
# Wrap the outgoing volinfo in a read-only proxy
return ReadOnlyMapping(self._volinfo)
@abstractmethod
def write(self, value):
"""Writes the new value into the format at the offset the object currently resides at"""
def cast(self, new_structure_name):
"""Returns a new object at the offset and from the layer that the current object inhabits"""
object_template = self._context.symbol_space.get_structure(new_structure_name)
return object_template(context = self._context,
layer_name = self.volinfo.layer_name,
offset = self.volinfo.offset)
@classmethod
@abstractmethod
def _template_replace_child(cls, template, old_child, new_child):
"""Substitutes the old_child for the new_child"""
@classmethod
@abstractmethod
def _template_size(cls, template):
"""Returns the size of the template object"""
@classmethod
@abstractmethod
def _template_children(cls, template):
"""Returns the children of the template"""
@classmethod
@abstractmethod
def _template_relative_child_offset(cls, template, child):
"""Returns the relative offset from the head of the parent data to the child member"""
class Template(validity.ValidityRoutines):
"""Class for all Factories that take offsets, and data layers and produce objects
This is effectively a class for currying object calls
"""
def __init__(self, structure_name, **arguments):
"""Stores the keyword arguments for later use"""
# Allow the updating of template arguments whilst still in template form
self._volinfo = collections.ChainMap(arguments, {'structure_name': structure_name})
@property
def volinfo(self):
"""Returns a volatility information object, much like the ObjectInterface provides"""
return ReadOnlyMapping(self._volinfo)
def update_volinfo(self, **new_arguments):
"""Updates the keyword arguments"""
self._volinfo.update(new_arguments)
def __call__(self, context, object_info):
"""Constructs the object
:type context: framework.interfaces.context.ContextInterface
:type object_info: ObjectInformation
:param context:
:param object_info:
:return O Returns: an object adhereing to the Object interface
"""