Initial introduction of ObjectInformation class.

This commit is contained in:
Mike Auty
2015-01-04 03:41:37 +00:00
parent 88afd32158
commit 15b2f6f717
7 changed files with 229 additions and 233 deletions
+5 -2
View File
@@ -38,6 +38,7 @@ def require_version(*args):
from volatility.framework import interfaces, symbols, layers
class Context(interfaces.context.ContextInterface):
"""Maintains the context within which to construct objects
@@ -86,7 +87,7 @@ class Context(interfaces.context.ContextInterface):
# ## Object Factory Functions
def object(self, symbol, layer_name, offset):
def object(self, symbol, layer_name, offset, **kwargs):
"""Object factory, takes a context, symbol, offset and optional layername
Looks up the layername in the context, finds the object template based on the symbol,
@@ -96,7 +97,9 @@ class Context(interfaces.context.ContextInterface):
:rtype: :py:class:`volatility.framework.interfaces.objects.ObjectInterface`
"""
object_template = self._symbol_space.get_structure(symbol)
return object_template(self, layer_name = layer_name, offset = offset)
return object_template(self,
interfaces.objects.ObjectInformation(layer_name = layer_name, offset = offset),
**kwargs)
+69 -46
View File
@@ -4,46 +4,76 @@ Created on 6 May 2013
@author: mike
"""
import copy
import collections.abc
from abc import ABCMeta, abstractmethod
from volatility.framework import validity
from volatility.framework.interfaces import context as context_module
class TemplateInformation(validity.ValidityRoutines):
def __init__(self, structure_name, size, **additional):
self._structure_name = structure_name
self._size = size
self._additional = additional
class ReadOnlyInformation(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(validity.ValidityRoutines):
class ObjectInformation(ReadOnlyInformation):
"""Contains information useful/pertinent only to an individual object (like an instance)"""
def __init__(self, layer_name, offset, member_name = None, parent = None):
self._layer_name = layer_name
self._offset = offset
self._member_name = member_name
self._parent = parent
self._type_check(offset, int)
if parent:
self._type_check(parent, ObjectInterface)
ReadOnlyInformation.__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, layer_name, offset, structure_name, size, parent = None):
def __init__(self, context, object_info, template_info):
# 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(offset, int)
if parent:
self._type_check(parent, ObjectInterface)
self._type_check(template_info, ReadOnlyInformation)
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, template_info)
self._context = context
self._parent = None if not parent else parent
self._offset = offset
self._layer_name = layer_name
self._structure_name = structure_name
self._size = size
@property
def volinfo(self):
"""Returns the volatility specific object information"""
# Wrap the outgoing volinfo in a read-only proxy
return ReadOnlyInformation(self._volinfo)
@abstractmethod
def write(self, value):
@@ -52,65 +82,58 @@ class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta):
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._layer_name, offset = self._offset)
return object_template(context = self._context,
layer_name = self.volinfo.layer_name,
offset = self.volinfo.offset)
@classmethod
@abstractmethod
def template_replace_child(cls, old_child, new_child, arguments):
def template_replace_child(cls, template, old_child, new_child):
"""Substitutes the old_child for the new_child"""
@classmethod
@abstractmethod
def template_size(cls, arguments):
def template_size(cls, template):
"""Returns the size of the template object"""
@classmethod
@abstractmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Returns the children of the template"""
@classmethod
@abstractmethod
def template_relative_child_offset(cls, arguments, child):
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(object):
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 = None, **kwargs):
def __init__(self, structure_name, **kwargs):
"""Stores the keyword arguments for later use"""
self._kwargs = kwargs
self._structure_name = structure_name
# Allow the updating of template arguments whilst still in template form
self._volinfo = collections.ChainMap(kwargs, {'structure_name': structure_name})
@property
def structure_name(self):
"""Returns the name of the particular symbol"""
return self._structure_name
def volinfo(self):
"""Returns a volatility information object, much like the ObjectInterface provides"""
return ReadOnlyInformation(self._volinfo)
@property
def arguments(self):
"""Returns the keyword arguments stored earlier"""
return copy.deepcopy(self._kwargs)
def update_arguments(self, **newargs):
def update_volinfo(self, **newargs):
"""Updates the keyword arguments"""
self._kwargs.update(newargs)
self._volinfo.update(newargs)
def __call__(self, context, layer_name, offset, parent = None):
def __call__(self, context, object_info, **kwargs):
"""Constructs the object
:type context: framework.interfaces.context.ContextInterface
:type layer_name: str
:type offset: int
:type parent: ObjectInterface
:type object_info: ObjectInformation
:param context:
:param layer_name:
:param offset:
:param parent:
:param object_info:
:return O Returns: an object adhereing to the Object interface
"""
+130 -164
View File
@@ -15,21 +15,21 @@ class Void(interfaces.objects.ObjectInterface):
"""Returns an object to represent void/unknown types"""
@classmethod
def template_size(cls, arguments):
def template_size(cls, template):
"""Dummy size for Void objects"""
return 0
@classmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Returns an empty list for Void objects since they can't have children"""
return []
@classmethod
def template_replace_child(cls, old_child, new_child, arguments):
def template_replace_child(cls, template, old_child, new_child):
"""Dummy method that does nothing for Void objects"""
@classmethod
def template_relative_child_offset(cls, arguments, child):
def template_relative_child_offset(cls, template, child):
"""Dummy method that does nothing for Void objects"""
def write(self, value):
@@ -39,132 +39,102 @@ class Void(interfaces.objects.ObjectInterface):
class PrimitiveObject(interfaces.objects.ObjectInterface):
"""PrimitiveObject is an interface for any objects that should simulate a Python primitive"""
_struct_format = '<I'
_struct_type = int
def __init__(self, context, layer_name, offset, structure_name, size = None, parent = None, struct_format = '<I'):
def __init__(self, context, object_info, template_info):
interfaces.objects.ObjectInterface.__init__(self,
context = context,
layer_name = layer_name,
offset = offset,
structure_name = structure_name,
size = size,
parent = parent)
self._struct_format = struct_format
template_info = template_info,
object_info = object_info)
def __new__(cls, context, template_info, object_info, **kwargs):
return cls._struct_type.__new__(cls,
cls._struct_value(context,
object_info.layer_name,
object_info.offset))
@classmethod
def _struct_value(cls, struct_format, context, layer_name, offset, structure_name):
length = struct.calcsize(struct_format)
def _struct_value(cls, context, layer_name, offset):
length = struct.calcsize(cls._struct_format)
data = context.memory.read(layer_name, offset, length)
(value,) = struct.unpack(struct_format, data)
(value,) = struct.unpack(cls._struct_format, data)
return value
@classmethod
def template_size(cls, arguments):
def template_size(cls, template):
"""Returns the size of the templated object"""
return struct.calcsize(arguments.get('struct_format', '<I'))
return struct.calcsize(cls._struct_format)
@classmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Since primitives have no children, this returns an empty list"""
return []
@classmethod
def template_replace_child(cls, old_child, new_child, arguments):
def template_replace_child(cls, old_child, new_child, volinfo):
"""Since this template can't ever have children, this method can be empty"""
@classmethod
def template_relative_child_offset(cls, arguments, child):
def template_relative_child_offset(cls, volinfo, child):
"""Since this template can't ever have children, this method can be empty as well"""
def write(self, value):
"""Writes the object into the layer of the context at the current offset"""
if isinstance(value, self._struct_type):
data = struct.pack(self._struct_format, value)
return self._context.memory.write(self.volinfo.layer_name, self.volinfo.offset, data)
raise TypeError(
repr(self.__class__.__name__) + " objects require a " + repr(type(self._struct_type)) + " to be written")
class Integer(PrimitiveObject, int):
"""Primitive Object that handles standard numeric types"""
def __new__(cls, context, layer_name, offset, structure_name, struct_format, **kwargs):
return int.__new__(cls, cls._struct_value(struct_format, context, layer_name, offset, structure_name))
def write(self, value):
"""Writes the object into the layer of the context at the current offset"""
if isinstance(value, int):
data = struct.pack(self._struct_format, value)
return self._context.memory.write(self._layer_name, self._offset, data)
raise TypeError("Integer objects require an integer to be written")
class Float(PrimitiveObject, float):
"""Primitive Object that handles double or floating point numbers"""
def __new__(cls, context, layer_name, offset, structure_name, struct_format, **kwargs):
return float.__new__(cls, cls._struct_value(struct_format, context, layer_name, offset, structure_name))
def write(self, value):
"""Writes the object into the layer of the context at the current offset"""
if isinstance(value, float):
data = struct.pack(self._struct_format, value)
return self._context.memory.write(self._layer_name, self._offset, data)
raise TypeError("Float objects require a float to be written")
_struct_format = '<f'
_struct_type = float
class Bytes(PrimitiveObject, bytes):
"""Primitive Object that handles specific series of bytes"""
_struct_format = '1s'
_struct_type = bytes
def __init__(self, context, layer_name, offset, structure_name, size = None, parent = None, length = 1):
bytes.__init__(self)
PrimitiveObject.__init__(self, context, layer_name, offset, structure_name,
size, parent, struct_format = str(length) + 's')
self.length = length
def __new__(cls, context, layer_name, offset, structure_name, length = 1, **kwargs):
return bytes.__new__(cls, cls._struct_value(str(length) + "s", context, layer_name, offset, structure_name))
def write(self, value):
"""Writes the object into the layer of the context at the current offset"""
if isinstance(value, bytes):
data = struct.pack(self._struct_format, value)
return self._context.memory.write(self._layer_name, self._offset, data)
raise TypeError("Bytes objects require a bytes type to be written")
def __init__(self, context, template_info, object_info, length = 1):
self._struct_format = str(length) + 's'
self._volinfo['length'] = length
PrimitiveObject.__init__(self, context, template_info, object_info)
# TODO: Fix up strings unpacking to include an encoding
class String(PrimitiveObject, str):
"""Primitive Object that handles string values
length: specifies the maximum possible length that the string could hold in memory
"""
_struct_format = '1s'
_struct_type = str
def __init__(self, context, layer_name, offset, structure_name, size = None, parent = None, length = 1):
str.__init__(self)
PrimitiveObject.__init__(self, context, layer_name, offset, structure_name,
size, parent, struct_format = str(length) + 's')
self.length = length
def __new__(cls, context, layer_name, offset, structure_name, length = 1, **kwargs):
return str.__new__(cls, cls._struct_value(str(length) + "s", context, layer_name, offset, structure_name))
def write(self, value):
"""Writes the object into the layer of the context at the current offset"""
if isinstance(value, str):
data = struct.pack(self._struct_format, value)
return self._context.memory.write(self._layer_name, self._offset, data)
raise TypeError("String objects require a string to be written")
def __init__(self, context, template_info, object_info, length = 1, encoding = 'ascii'):
self._struct_format = str(length) + 's'
self._volinfo['length'] = length
PrimitiveObject.__init__(self, context, template_info, object_info)
class Pointer(Integer):
"""Pointer which points to another object"""
_struct_format = '<I'
def __init__(self, context, layer_name, offset, structure_name, size = None,
parent = None, struct_format = None, target = None):
if not isinstance(target, templates.ObjectTemplate):
raise TypeError("Pointer targets must be an ObjectTemplate")
def __init__(self, context, object_info, template_info, target = None):
self._type_check(target, templates.ObjectTemplate)
Integer.__init__(self,
context,
layer_name = layer_name,
offset = offset,
structure_name = structure_name,
size = size,
parent = parent,
struct_format = struct_format)
self._target = target
self._cache = None
self._cache_layer_name = None
object_info,
template_info)
self._volinfo['target'] = target
def dereference(self, layer_name = None):
"""Dereferences the pointer
@@ -174,52 +144,50 @@ class Pointer(Integer):
"""
if layer_name is None:
layer_name = self._layer_name
# Cache the target
if self._cache is None or (self._cache_layer_name != layer_name):
self._cache_layer_name = self._layer_name
self._cache = self._target(context = self._context,
layer_name = layer_name,
offset = self,
parent = self)
return self._cache
return self._target(context = self._context,
object_info = collections.ChainMap({'layer_name': layer_name,
'offset': self,
'parent': self}, self.volinfo))
def __getattr__(self, attr):
"""Convenience function to access unknown attributes by getting them from the target object"""
return getattr(self.dereference(), attr)
@classmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Returns the children of the template"""
if 'target' in arguments:
return [arguments['target']]
if 'target' in template.volinfo:
return [template.volinfo.target]
return []
@classmethod
def template_replace_child(cls, old_child, new_child, arguments):
def template_replace_child(cls, template, old_child, new_child):
"""Substitutes the old_child for the new_child"""
if 'target' in arguments:
if arguments['target'] == old_child:
arguments['target'] = new_child
if 'target' in template.volinfo:
if template.volinfo.target == old_child:
template.update_volinfo(target = new_child)
class BitField(PrimitiveObject, int):
"""Object containing a field which is made up of bits rather than whole bytes"""
def __new__(cls, context, layer_name, offset, structure_name, size = None,
parent = None, target = None, start_bit = 0, end_bit = 0, **kwargs):
def __new__(cls, context, object_info, template_info, target = None, start_bit = 0, end_bit = 0, **kwargs):
value = target(context = context,
layer_name = layer_name,
offset = offset,
structure_name = structure_name,
size = size,
parent = parent)
return (value >> start_bit) & ((1 << end_bit) - 1)
object_info = object_info,
template_info = template_info)
return cls._struct_type.__new__(cls, (value >> start_bit) & ((1 << end_bit) - 1))
def __init__(self, context, object_info, template_info, target = None, start_bit = 0, end_bit = 0):
PrimitiveObject.__init__(self, context, object_info, template_info)
self._volinfo['target'] = target
self._volinfo['start_bit'] = start_bit
self._volinfo['end_bit'] = end_bit
@classmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Returns the target type"""
if 'target' in arguments:
return [arguments['target']]
if 'target' in template.volinfo:
return [template.volinfo.target]
return []
def write(self, value):
@@ -230,7 +198,7 @@ class Enumeration(interfaces.objects.ObjectInterface):
"""Returns an object made up of choices"""
# FIXME: Add in body for the enumeration object
@classmethod
def template_children(cls, arguments):
def template_children(cls, volinfo):
return []
def write(self, value):
@@ -240,58 +208,53 @@ class Enumeration(interfaces.objects.ObjectInterface):
class Array(interfaces.objects.ObjectInterface, collections.Sequence):
"""Object which can contain a fixed number of an object type"""
def __init__(self, context, layer_name, offset, structure_name, size = None,
parent = None, count = 0, target = None):
if not isinstance(target, templates.ObjectTemplate):
raise TypeError("Array target must be an ObjectTemplate")
def __init__(self, context, object_info, template_info, count = 0, target = None):
self._type_check(target, templates.ObjectTemplate)
interfaces.objects.ObjectInterface.__init__(self,
context = context,
layer_name = layer_name,
offset = offset,
structure_name = structure_name,
size = size,
parent = parent)
self._count = self._type_check(count, int)
self._target = target
object_info = object_info,
template_info = template_info)
self._volinfo['count'] = self._type_check(count, int)
self._volinfo['target'] = target
@classmethod
def template_size(cls, arguments):
def template_size(cls, template):
"""Returns the size of the array, based on the count and the target"""
if 'target' not in arguments and 'count' not in arguments:
if 'target' not in template.volinfo and 'count' not in template.volinfo:
raise TypeError("Array ObjectTemplate must be provided a count and target")
return arguments.get('target', None).size * arguments.get('count', 0)
return template.volinfo.get('target', None).size * template.volinfo.get('count', 0)
@classmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Returns the children of the template"""
if 'target' in arguments:
return [arguments['target']]
if 'target' in template.volinfo:
return [template.volinfo.target]
return []
@classmethod
def template_replace_child(cls, old_child, new_child, arguments):
def template_replace_child(cls, template, old_child, new_child):
"""Substitutes the old_child for the new_child"""
if 'target' in arguments:
if arguments['target'] == old_child:
arguments['target'] = new_child
if 'target' in template.volinfo:
if template.volinfo['target'] == old_child:
template.update_volinfo(target = new_child)
@classmethod
def template_relative_child_offset(cls, arguments, child):
def template_relative_child_offset(cls, template, child):
"""Returns the relative offset from the head of the parent data to the child member"""
if 'target' in arguments and child == 'target':
if 'target' in template and child == 'target':
return 0
raise IndexError("Member " + child + " not present in array template")
def __getitem__(self, i):
"""Returns the i-th item from the array"""
if i >= self._count or 0 > i:
if i >= self.volinfo.count or 0 > i:
raise IndexError
return self._target(context = self._context, layer_name = self._layer_name,
offset = self._offset + (self._target.size * i), parent = self)
return self.volinfo.target(context = self._context, layer_name = self.volinfo.layer_name,
offset = self.volinfo.offset + (self.volinfo.target.size * i), parent = self)
def __len__(self):
"""Returns the length of the array"""
return self._count
return self.volinfo.count
def write(self, value):
raise NotImplementedError("Writing to Arrays is not yet implemented")
@@ -303,53 +266,53 @@ class Struct(interfaces.objects.ObjectInterface):
Keep the number of methods in this class low or very specific, since each one could overload a valid member.
"""
def __init__(self, context, layer_name, offset, structure_name, size = None, members = None, parent = None):
def __init__(self, context, object_info, template_info):
interfaces.objects.ObjectInterface.__init__(self,
context = context,
layer_name = layer_name,
offset = offset,
structure_name = structure_name,
size = size,
parent = parent)
self._check_members(members)
self._members = members
object_info = object_info,
template_info = template_info)
self._check_members(template_info.members)
self._concrete_members = {}
@classmethod
def template_size(cls, arguments):
def template_size(cls, template):
"""Method to return the size of this structure"""
if arguments.get('size', None) is None:
if template.volinfo.get('size', None) is None:
raise TypeError("Struct ObjectTemplate not provided with a size")
return arguments['size']
return template.volinfo['size']
@classmethod
def template_children(cls, arguments):
def template_children(cls, template):
"""Method to list children of a template"""
return [member for _, member in cls._template_members(arguments).values()]
return [member for _, member in cls._template_members(template).values()]
@classmethod
def template_replace_child(cls, old_child, new_child, arguments):
def template_replace_child(cls, template, old_child, new_child):
"""Replace a child elements within the arguments handed to the template"""
for member in arguments.get('members', {}):
relative_offset, member_template = arguments['members'][member]
for member in cls._template_members(template).get('members', {}):
relative_offset, member_template = template.volinfo.members[member]
if member_template == old_child:
arguments['members'][member] = (relative_offset, new_child)
# Members will give access to the mutable members list,
# but in case that ever changes, do the update correctly
tmp_list = template.volinfo.members
tmp_list[member] = (relative_offset, new_child)
template.update_volinfo(members = tmp_list)
@classmethod
def template_relative_child_offset(cls, arguments, child):
def template_relative_child_offset(cls, template, child):
"""Returns the relative offset of a child to its parent"""
retlist = cls._template_members(arguments).get(child, None)
retlist = cls._template_members(template).get(child, None)
if retlist is None:
raise IndexError("Member " + child + " not present in template")
return retlist[0]
@classmethod
def _template_members(cls, arguments):
def _template_members(cls, template):
"""Returns the dictionary of member_names to (relative_offset, member) as provided in the template arguments"""
if 'members' not in arguments:
if 'members' not in template.volinfo:
raise TypeError("Members not found in template arguments")
cls._check_members(arguments.get('members', None))
return arguments['members']
cls._check_members(template.volinfo.members)
return template.volinfo.members.copy()
@classmethod
def _check_members(cls, members):
@@ -368,13 +331,16 @@ class Struct(interfaces.objects.ObjectInterface):
"""Method for accessing members of the structure"""
if attr in self._concrete_members:
return self._concrete_members[attr]
elif attr in self._members:
relative_offset, member = self._members[attr]
member = member(context = self._context, layer_name = self._layer_name,
offset = self._offset + relative_offset, parent = self)
elif attr in self.volinfo.members:
relative_offset, member = self.volinfo.members[attr]
member = member(context = self._context,
object_info = interfaces.objects.ObjectInformation(layer_name = self.volinfo.layer_name,
offset = self.volinfo.offset + relative_offset,
member_name = attr,
parent = self))
self._concrete_members[attr] = member
return member
raise AttributeError("'" + self._structure_name + "' Struct has no attribute '" + attr + "'")
raise AttributeError("'" + self.volinfo.structure_name + "' Struct has no attribute '" + attr + "'")
def write(self, value):
raise TypeError("Structs cannot be written to directly, individual members must be written instead")
+14 -12
View File
@@ -18,9 +18,11 @@ class ObjectTemplate(interfaces.objects.Template, validity.ValidityRoutines):
"""
def __init__(self, object_class = None, structure_name = None, **kwargs):
interfaces.objects.Template.__init__(self, structure_name = structure_name, **kwargs)
interfaces.objects.Template.__init__(self,
structure_name = structure_name,
**kwargs)
self._class_check(object_class, interfaces.objects.ObjectInterface)
self.object_class = object_class
self.update_volinfo(object_class = object_class)
@classmethod
def template_children(cls, **kwargs):
@@ -33,7 +35,7 @@ class ObjectTemplate(interfaces.objects.Template, validity.ValidityRoutines):
@property
def size(self):
"""Returns the size of the template"""
return self.object_class.template_size(self._kwargs)
return self.volinfo.object_class.template_size(self)
@property
def children(self):
@@ -41,33 +43,33 @@ class ObjectTemplate(interfaces.objects.Template, validity.ValidityRoutines):
This is used to traverse the template tree
"""
return self.object_class.template_children(self._kwargs)
return self.volinfo.object_class.template_children(self)
def relative_child_offset(self, child):
"""A function that returns the relative offset of a child from its parent offset
This may throw exceptions including ChildNotFoundException and NotImplementedError
"""
return self.object_class.template_relative_child_offset(self._kwargs, child)
return self.volinfo.object_class.template_relative_child_offset(self, child)
def replace_child(self, old_child, new_child):
"""A function for replacing one child with another
We pass in the kwargs directly so they can be changed
"""
self.object_class.template_replace_child(old_child, new_child, self._kwargs)
self.volinfo.object_class.template_replace_child(self, old_child, new_child)
def __call__(self, context, layer_name, offset, parent = None):
def __call__(self, context, object_info, **kwargs):
"""Constructs the object
Returns: an object adhereing to the Object interface
"""
# We always use the template size (as calculated by the object class)
# over the one passed in by an argument
self._kwargs['size'] = self.size
self._kwargs['structure_name'] = self.structure_name
return self.object_class(context = context, layer_name = layer_name, offset = offset, parent = parent,
**self._kwargs)
return self.volinfo.object_class(context = context,
object_info = object_info,
template_info = self.volinfo,
**kwargs)
class ReferenceTemplate(interfaces.objects.Template):
@@ -77,5 +79,5 @@ class ReferenceTemplate(interfaces.objects.Template):
"""
def __call__(self, context, *args, **kwargs):
template = context.symbol_space.get_structure(self._structure_name)
template = context.symbol_space.get_structure(self.volinfo.structure_name)
return template(context = context, *args, **kwargs)
+5 -5
View File
@@ -97,16 +97,16 @@ class SymbolSpace(collections.Mapping):
if isinstance(child, objects.templates.ReferenceTemplate):
# If we haven't seen it before, subresolve it and also add it
# to the "symbols that still need traversing" list
if child.structure_name not in self._resolved:
traverse_list.append(child.structure_name)
self._resolved[child.structure_name] = self._weak_resolve(SymbolType.STRUCTURE,
child.structure_name)
if child.volinfo.structure_name not in self._resolved:
traverse_list.append(child.volinfo.structure_name)
self._resolved[child.volinfo.structure_name] = self._weak_resolve(SymbolType.STRUCTURE,
child.volinfo.structure_name)
# Stash the replacement
replacements.add((traverser, child))
elif child.children:
template_traverse_list.append(child)
for (parent, child) in replacements:
parent.replace_child(child, self._resolved[child.structure_name])
parent.replace_child(child, self._resolved[child.volinfo.structure_name])
return self._resolved[structure_name]
def get_constant(self, constant_name):
+5 -3
View File
@@ -79,7 +79,7 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
elif structure_name == 'BitField':
update = dictionary[1]
update['target'] = self._vtypedict_to_template([update['native_type']])
native_template.update_arguments(**update) # pylint: disable=W0142
native_template.update_volinfo(**update) # pylint: disable=W0142
return native_template
# Otherwise
@@ -104,5 +104,7 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
member = (relative_offset, self._vtypedict_to_template(vtypedict))
members[member_name] = member
object_class = self.get_structure_class(structure_name)
return objects.templates.ObjectTemplate(object_class = object_class, structure_name = structure_name,
size = size, members = members)
return objects.templates.ObjectTemplate(structure_name = structure_name,
object_class = object_class,
size = size,
members = members)
+1 -1
View File
@@ -4144,7 +4144,7 @@ ntkrnlmp_types = {
'_IO_STATUS_BLOCK': [0x8, {
'Status': [0x0, ['long']],
'Pointer': [0x0, ['pointer', ['void']]],
'Information': [0x4, ['unsigned long']],
'ReadOnlyInformation': [0x4, ['unsigned long']],
}],
'_LPCP_MESSAGE': [0x30, {
'Entry': [0x0, ['_LIST_ENTRY']],