From 8c76a25b2d0fbc79e42eca56ef123fef91b42f10 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Wed, 17 Apr 2019 23:50:31 +0100 Subject: [PATCH] Allow VolTemplateProxies to include additional useful methods. --- volatility/framework/interfaces/objects.py | 11 ++++++++--- volatility/framework/objects/__init__.py | 1 - volatility/framework/objects/templates.py | 8 +++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/volatility/framework/interfaces/objects.py b/volatility/framework/interfaces/objects.py index 31d11291d..750519370 100644 --- a/volatility/framework/interfaces/objects.py +++ b/volatility/framework/interfaces/objects.py @@ -19,7 +19,7 @@ # """Objects are the core of volatility, and provide pythonic access to interpreted values of data from a layer. """ - +import abc import collections import collections.abc import logging @@ -166,8 +166,8 @@ class ObjectInterface(metaclass = ABCMeta): """Returns whether the object would contain a member called member_name""" return False - class VolTemplateProxy(object): - """A container for proxied methods that the ObjectTemplate of this object will call. This primarily to keep + class VolTemplateProxy(metaclass = abc.ABCMeta): + """A container for proxied methods that the ObjectTemplate of this object will call. This is primarily to keep methods together for easy organization/management, there is no significant need for it to be a separate class. The methods of this class *must* be class methods rather than standard methods, to allow for code reuse. @@ -176,25 +176,30 @@ class ObjectInterface(metaclass = ABCMeta): new templates for each and every potental object type.""" @classmethod + @abc.abstractmethod def size(cls, template: 'Template') -> int: """Returns the size of the template object""" @classmethod + @abc.abstractmethod def children(cls, template: 'Template') -> List['Template']: """Returns the children of the template""" return [] @classmethod + @abc.abstractmethod def replace_child(cls, template: 'Template', old_child: 'Template', new_child: 'Template') -> None: """Substitutes the old_child for the new_child""" raise KeyError("Template does not contain any children to replace: {}".format(template.vol.type_name)) @classmethod + @abc.abstractmethod def relative_child_offset(cls, template: 'Template', child: str) -> int: """Returns the relative offset from the head of the parent data to the child member""" raise KeyError("Template does not contain any children: {}".format(template.vol.type_name)) @classmethod + @abc.abstractmethod def has_member(cls, template: 'Template', member_name: str) -> bool: """Returns whether the object would contain a member called member_name""" return False diff --git a/volatility/framework/objects/__init__.py b/volatility/framework/objects/__init__.py index 0b3469fcf..ba1046759 100644 --- a/volatility/framework/objects/__init__.py +++ b/volatility/framework/objects/__init__.py @@ -413,7 +413,6 @@ class Enumeration(interfaces.objects.ObjectInterface, int): self._vol['base_type'] = base_type @classmethod - @functools.lru_cache(maxsize = 128) def _generate_inverse_choices(cls, choices: Dict[str, int]) -> Dict[int, str]: """Generates the inverse choices for the object""" inverse_choices = {} # type: Dict[int, str] diff --git a/volatility/framework/objects/templates.py b/volatility/framework/objects/templates.py index 32e6dd707..6a0c05b52 100644 --- a/volatility/framework/objects/templates.py +++ b/volatility/framework/objects/templates.py @@ -17,7 +17,7 @@ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the # specific language governing rights and limitations under the License. # - +import functools import logging from typing import Any, ClassVar, Dict, List, Type @@ -41,6 +41,12 @@ class ObjectTemplate(interfaces.objects.Template): super().__init__(type_name = type_name, **arguments) self._arguments['object_class'] = object_class + proxy_cls = self.vol.object_class.VolTemplateProxy + for method_name in dir(proxy_cls): + if (method_name not in dir(interfaces.objects.ObjectInterface.VolTemplateProxy) + and callable(getattr(proxy_cls, method_name)) and not method_name.startswith('_')): + setattr(self, method_name, functools.partial(getattr(proxy_cls, method_name), self)) + @property def size(self) -> int: """Returns the children of the templated object (see :class:`~volatility.framework.interfaces.objects.ObjectInterface.VolTemplateProxy`)"""