mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-13 13:17:38 +02:00
Merge branch 'master' of github.com:volatilityfoundation/volatility3
This commit is contained in:
+8
-8
@@ -26,8 +26,8 @@ def utils_load_as():
|
||||
|
||||
virtual_types = xp_sp2_x86_vtypes.ntkrnlmp_types
|
||||
ntkrnlmp = vtypes.VTypeSymbolTable('ntkrnlmp', virtual_types, ctx.symbol_space.natives)
|
||||
ntkrnlmp.set_structure_class('_ETHREAD', volatility.framework.symbols.windows.extensions._ETHREAD)
|
||||
ntkrnlmp.set_structure_class('_LIST_ENTRY', volatility.framework.symbols.windows.extensions._LIST_ENTRY)
|
||||
ntkrnlmp.set_type_class('_ETHREAD', volatility.framework.symbols.windows.extensions._ETHREAD)
|
||||
ntkrnlmp.set_type_class('_LIST_ENTRY', volatility.framework.symbols.windows.extensions._LIST_ENTRY)
|
||||
ctx.symbol_space.append(ntkrnlmp)
|
||||
# contexts.windows.WindowsContextModifier(ctx.config).modify_context(ctx)
|
||||
|
||||
@@ -36,7 +36,7 @@ def utils_load_as():
|
||||
|
||||
def test_symbols():
|
||||
ctx = utils_load_as()
|
||||
print("Symbols,", ctx.symbol_space.natives.structures)
|
||||
print("Symbols,", ctx.symbol_space.natives.types)
|
||||
|
||||
virtual_types = xp_sp2_x86_vtypes.ntkrnlmp_types
|
||||
virtual_types['TEST_POINTER'] = [0x4, {'point1': [0x0, ['pointer', ['TEST_SYMBOL']]]}]
|
||||
@@ -45,11 +45,11 @@ def test_symbols():
|
||||
|
||||
ctx.symbol_space.append(ntkrnlmp)
|
||||
|
||||
for i in list(ctx.symbol_space['ntkrnlmp'].structures):
|
||||
symbol = ctx.symbol_space.get_structure('ntkrnlmp!' + i)
|
||||
print(symbol.vol.structure_name, symbol, symbol.vol.size)
|
||||
for i in list(ctx.symbol_space['ntkrnlmp'].types):
|
||||
symbol = ctx.symbol_space.get_type('ntkrnlmp!' + i)
|
||||
print(symbol.vol.type_name, symbol, symbol.vol.size)
|
||||
_ = symbol(ctx, objects.ObjectInformation(layer_name = '', offset = 0))
|
||||
symbol = ctx.symbol_space.get_structure('ntkrnlmp!_EPROCESS')
|
||||
symbol = ctx.symbol_space.get_type('ntkrnlmp!_EPROCESS')
|
||||
return symbol
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ def test_translation():
|
||||
a, b = intel._translate(val)
|
||||
print(hex(val), hex(a), hex(b))
|
||||
# print(bin(0x39000), bin(0xffab8020))
|
||||
# print(hex(intel.translate(0xffab8020)))
|
||||
# print(hex(intel.mapping(0xffab8020, 0)))
|
||||
|
||||
|
||||
def test_plugin():
|
||||
|
||||
@@ -6,3 +6,4 @@ This includes default scanning block sizes, etc."""
|
||||
import os.path
|
||||
|
||||
PLUGINS_PATH = [os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "plugins"))]
|
||||
BANG = "!"
|
||||
|
||||
@@ -73,7 +73,7 @@ class Context(interfaces.context.ContextInterface):
|
||||
:return: A fully constructed object
|
||||
:rtype: :py:class:`volatility.framework.interfaces.objects.ObjectInterface`
|
||||
"""
|
||||
object_template = self._symbol_space.get_structure(symbol)
|
||||
object_template = self._symbol_space.get_type(symbol)
|
||||
object_template.update_vol(**arguments)
|
||||
return object_template(context = self,
|
||||
object_info = interfaces.objects.ObjectInformation(layer_name = layer_name,
|
||||
|
||||
@@ -93,10 +93,6 @@ class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta):
|
||||
# Unfortunately class attributes can't easily be inheritted from parent classes
|
||||
provides = {"type": "interface"}
|
||||
|
||||
@abstractmethod
|
||||
def translate(self, offset):
|
||||
"""Returns a tuple of (offset, layer) indicating the translation of input domain to the output range"""
|
||||
|
||||
@abstractmethod
|
||||
def mapping(self, offset, length):
|
||||
"""Returns a sorted list of (offset, mapped_offset, length, layer) mappings
|
||||
|
||||
@@ -53,7 +53,7 @@ class ObjectInformation(ReadOnlyMapping):
|
||||
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):
|
||||
def __init__(self, context, type_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
|
||||
@@ -64,9 +64,9 @@ class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta):
|
||||
#
|
||||
# NOTE:
|
||||
# This allows objects to MASSIVELY MESS with their own internal representation!!!
|
||||
# Changes to offset, structure_name, etc should NEVER be done
|
||||
# Changes to offset, type_name, etc should NEVER be done
|
||||
#
|
||||
self._vol = collections.ChainMap({}, object_info, {'structure_name': structure_name}, kwargs)
|
||||
self._vol = collections.ChainMap({}, object_info, {'type_name': type_name}, kwargs)
|
||||
self._context = context
|
||||
|
||||
@property
|
||||
@@ -79,10 +79,10 @@ class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta):
|
||||
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, **additional):
|
||||
def cast(self, new_type_name, **additional):
|
||||
"""Returns a new object at the offset and from the layer that the current object inhabits"""
|
||||
# TODO: Carefully consider the implications of casting and how it should work
|
||||
object_template = self._context.symbol_space.get_structure(new_structure_name)
|
||||
object_template = self._context.symbol_space.get_type(new_type_name)
|
||||
object_template.update_vol(**additional)
|
||||
object_info = ObjectInformation(layer_name = self.vol.layer_name,
|
||||
offset = self.vol.offset,
|
||||
@@ -112,7 +112,7 @@ class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta):
|
||||
@classmethod
|
||||
def relative_child_offset(cls, template, child):
|
||||
"""Returns the relative offset from the head of the parent data to the child member"""
|
||||
raise KeyError(repr(template.vol.structure_name) + " does not contain any children.")
|
||||
raise KeyError(repr(template.vol.type_name) + " does not contain any children.")
|
||||
|
||||
|
||||
class Template(validity.ValidityRoutines):
|
||||
@@ -121,10 +121,10 @@ class Template(validity.ValidityRoutines):
|
||||
This is effectively a class for currying object calls
|
||||
"""
|
||||
|
||||
def __init__(self, structure_name, **arguments):
|
||||
def __init__(self, type_name, **arguments):
|
||||
"""Stores the keyword arguments for later use"""
|
||||
# Allow the updating of template arguments whilst still in template form
|
||||
self._vol = collections.ChainMap(arguments, {'structure_name': structure_name})
|
||||
self._vol = collections.ChainMap(arguments, {'type_name': type_name})
|
||||
|
||||
@property
|
||||
def vol(self):
|
||||
|
||||
@@ -3,92 +3,144 @@ Created on 4 May 2013
|
||||
|
||||
@author: mike
|
||||
"""
|
||||
import bisect
|
||||
|
||||
from volatility.framework import validity, exceptions
|
||||
from volatility.framework import validity, exceptions, constants
|
||||
from volatility.framework.interfaces import configuration
|
||||
|
||||
|
||||
class Symbol(validity.ValidityRoutines):
|
||||
def __init__(self, name, offset, type_name = None):
|
||||
self._name = self._check_type(name, str)
|
||||
if constants.BANG in self._name:
|
||||
raise ValueError("Symbol names cannot contain the symbol differentiator (" + constants.BANG + ")")
|
||||
self._location = None
|
||||
self._offset = self._check_type(offset, int)
|
||||
if type_name is None:
|
||||
type_name = name
|
||||
self._type_name = self._check_type(type_name, str)
|
||||
# Scope and location can be added at a later date
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Returns the name of the symbol"""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def type_name(self):
|
||||
"""Returns the name of the type that the symbol represents"""
|
||||
return self._type_name
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
"""Returns the relative offset of the symbol within the compilation unit"""
|
||||
return self._offset
|
||||
|
||||
|
||||
class SymbolTableInterface(validity.ValidityRoutines):
|
||||
"""Handles a table of symbols"""
|
||||
|
||||
def __init__(self, name, native_structures = None):
|
||||
self._check_type(native_structures, NativeTableInterface)
|
||||
def __init__(self, name, native_types = None):
|
||||
self._check_type(native_types, NativeTableInterface)
|
||||
if name:
|
||||
self._check_type(name, str)
|
||||
self.name = name or None
|
||||
self._native_structures = native_structures
|
||||
self._native_types = native_types
|
||||
|
||||
# ## Required Constant symbol functions
|
||||
# ## Required Symbol functions
|
||||
|
||||
def get_constant(self, name):
|
||||
"""Resolves a symbol name into a constant
|
||||
def get_symbol(self, name):
|
||||
"""Resolves a symbol name into a symbol object
|
||||
|
||||
If the symbol isn't found, it raises a SymbolError exception
|
||||
"""
|
||||
raise NotImplementedError("Abstract property get_constant not implemented by subclass.")
|
||||
raise NotImplementedError("Abstract property get_symbol not implemented by subclass.")
|
||||
|
||||
@property
|
||||
def constants(self):
|
||||
"""Returns an iterator of the constant symbols"""
|
||||
raise NotImplementedError("Abstract property constants not implemented by subclass.")
|
||||
def symbols(self):
|
||||
"""Returns an iterator of the Symbols"""
|
||||
raise NotImplementedError("Abstract property symbols not implemented by subclass.")
|
||||
|
||||
# ## Required Structure symbol functions
|
||||
# ## Required Symbol type functions
|
||||
|
||||
def get_structure(self, name):
|
||||
def get_type(self, name):
|
||||
"""Resolves a symbol name into an object template
|
||||
|
||||
If the symbol isn't found it raises a SymbolError exception
|
||||
"""
|
||||
raise NotImplementedError("Abstract method get_structure not implemented by subclass.")
|
||||
raise NotImplementedError("Abstract method get_type not implemented by subclass.")
|
||||
|
||||
@property
|
||||
def structures(self):
|
||||
"""Returns an iterator of the structure symbols"""
|
||||
raise NotImplementedError("Abstract property structures not implemented by subclass.")
|
||||
def types(self):
|
||||
"""Returns an iterator of the Symbol types"""
|
||||
raise NotImplementedError("Abstract property types not implemented by subclass.")
|
||||
|
||||
# ## Native Type Handler
|
||||
|
||||
@property
|
||||
def natives(self):
|
||||
"""Returns None or a symbol_space for handling space specific native types"""
|
||||
return self._native_structures
|
||||
"""Returns None or a NativeTable for handling space specific native types"""
|
||||
return self._native_types
|
||||
|
||||
@natives.setter
|
||||
def natives(self, value):
|
||||
"""Checks the natives value and then applies it internally
|
||||
|
||||
WARNING: This allows changing the underlying size of all the other structures referenced in the symbolspace
|
||||
WARNING: This allows changing the underlying size of all the other types referenced in the SymbolTable
|
||||
"""
|
||||
self._check_type(value, NativeTableInterface)
|
||||
self._native_structures = value
|
||||
self._native_types = value
|
||||
|
||||
# ## Functions for overriding classes
|
||||
|
||||
def set_structure_class(self, name, clazz):
|
||||
"""Overrides the object class for a specific structure symbol
|
||||
def set_type_class(self, name, clazz):
|
||||
"""Overrides the object class for a specific Symbol type
|
||||
|
||||
Name *must* be present in self.structures
|
||||
Name *must* be present in self.types
|
||||
"""
|
||||
raise NotImplementedError("Abstract method set_structure_class not implemented yet.")
|
||||
raise NotImplementedError("Abstract method set_type_class not implemented yet.")
|
||||
|
||||
def get_structure_class(self, name):
|
||||
"""Returns the class associated with a structure symbol"""
|
||||
raise NotImplementedError("Abstract method get_structure_class not implemented yet.")
|
||||
def get_type_class(self, name):
|
||||
"""Returns the class associated with a Symbol type"""
|
||||
raise NotImplementedError("Abstract method get_type_class not implemented yet.")
|
||||
|
||||
def del_structure_class(self, name):
|
||||
"""Removes the associated class override for a specific structure symbol"""
|
||||
raise NotImplementedError("Abstract method del_structure_class not implemented yet.")
|
||||
def del_type_class(self, name):
|
||||
"""Removes the associated class override for a specific Symbol type"""
|
||||
raise NotImplementedError("Abstract method del_type_class not implemented yet.")
|
||||
|
||||
# ## Convenience functions for location symbols
|
||||
|
||||
def get_symbol_type(self, name):
|
||||
"""Resolves a symbol name into a symbol and then resolves the symbol's type"""
|
||||
return self.get_type(self.get_symbol(name).type_name)
|
||||
|
||||
def get_symbols_by_type(self, type_name):
|
||||
"""Returns the name of all symbols in this table that have type matching type_name"""
|
||||
for symbol in self.symbols:
|
||||
# This allows for searching with and without the table name (in case multiple tables contain
|
||||
# the same symbol name and we've not specifically been told which one)
|
||||
if symbol.type_name == type_name or (symbol.type_name.endswith(constants.BANG + type_name)):
|
||||
yield symbol.name
|
||||
|
||||
def get_symbols_by_location(self, offset):
|
||||
"""Returns the name of all symbols in this table that have type matching type_name"""
|
||||
sort_symbols = [(s.offset, s) for s in sorted(self.symbols, key = lambda x: x.offset)]
|
||||
result = bisect.bisect_left(sort_symbols, offset)
|
||||
if result == len(sort_symbols):
|
||||
raise StopIteration
|
||||
closest_symbol = sort_symbols[result][1]
|
||||
if closest_symbol.offset == offset:
|
||||
yield closest_symbol.name
|
||||
|
||||
|
||||
class NativeTableInterface(SymbolTableInterface):
|
||||
"""Class to distinguish NativeSymbolLists from other symbol lists"""
|
||||
|
||||
@staticmethod
|
||||
def constant():
|
||||
raise exceptions.SymbolError("NativeTables never hold constants")
|
||||
def get_symbol(self, name):
|
||||
raise exceptions.SymbolError("NativeTables never hold symbols")
|
||||
|
||||
@property
|
||||
def constants(self):
|
||||
def symbols(self):
|
||||
return []
|
||||
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ class Intel(interfaces.layers.TranslationLayerInterface):
|
||||
|
||||
def __init__(self, context, config_path, name, page_map_offset, memory_layer, swap_layer = None):
|
||||
interfaces.layers.TranslationLayerInterface.__init__(self, context, config_path, name)
|
||||
self._base_layer = memory_layer
|
||||
self._page_map_offset = page_map_offset
|
||||
self._base_layer = self._check_type(memory_layer, str)
|
||||
self._page_map_offset = self._check_type(page_map_offset, int)
|
||||
# All Intel address spaces work on 4096 byte pages
|
||||
self._page_size_in_bits = 12
|
||||
|
||||
@@ -91,7 +91,7 @@ class Intel(interfaces.layers.TranslationLayerInterface):
|
||||
entry, = struct.unpack(self._entry_format, self._context.memory.read(self._base_layer, table_offset,
|
||||
struct.calcsize(self._entry_format)))
|
||||
|
||||
# Now we're do
|
||||
# Now we're done
|
||||
if not self._page_is_valid(entry):
|
||||
raise exceptions.InvalidAddressException("Page Fault at entry " + hex(entry) + " in page entry")
|
||||
page = self._mask(entry, self._maxphyaddr - 1, position + 1) | self._mask(offset, position, 0)
|
||||
@@ -105,16 +105,14 @@ class Intel(interfaces.layers.TranslationLayerInterface):
|
||||
except exceptions.InvalidAddressException:
|
||||
return False
|
||||
|
||||
def translate(self, offset):
|
||||
"""Translates a specific offset based on the paging tables"""
|
||||
result, _ = self._translate(offset)
|
||||
return result
|
||||
|
||||
def mapping(self, offset, length):
|
||||
"""Returns a sorted list of (offset, mapped_offset, length, layer) mappings
|
||||
|
||||
This allows translation layers to provide maps of contiguous regions in one layer
|
||||
"""
|
||||
if length == 0:
|
||||
mapped_offset, _ = self._translate(offset)
|
||||
return [(offset, mapped_offset, length, self._base_layer)]
|
||||
result = []
|
||||
while length > 0:
|
||||
chunk_offset, page_size = self._translate(offset)
|
||||
@@ -126,19 +124,22 @@ class Intel(interfaces.layers.TranslationLayerInterface):
|
||||
|
||||
@property
|
||||
def dependencies(self):
|
||||
"""Returns a list of the lower layers that this layer is dependent upon"""
|
||||
"""Returns a list of the lower layer names that this layer is dependent upon"""
|
||||
# TODO: Add in the whole buffalo
|
||||
return [self._base_layer]
|
||||
|
||||
@classmethod
|
||||
def get_schema(cls):
|
||||
return [volatility.framework.configuration.requirements.TranslationLayerRequirement(name = 'memory_layer',
|
||||
constraints = {"type": "physical"},
|
||||
constraints = {
|
||||
"type": "physical"},
|
||||
optional = False),
|
||||
volatility.framework.configuration.requirements.TranslationLayerRequirement(name = 'swap_layer',
|
||||
constraints = {"type": "physical"},
|
||||
constraints = {
|
||||
"type": "physical"},
|
||||
optional = True),
|
||||
volatility.framework.configuration.requirements.IntRequirement(name = 'page_map_offset', optional = False)]
|
||||
volatility.framework.configuration.requirements.IntRequirement(name = 'page_map_offset',
|
||||
optional = False)]
|
||||
|
||||
|
||||
class IntelPAE(Intel):
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
Created on 6 Apr 2016
|
||||
|
||||
@author: npetroni@volexity.com
|
||||
"""
|
||||
|
||||
import struct
|
||||
|
||||
from volatility.framework import interfaces, exceptions
|
||||
from volatility.framework.configuration import requirements
|
||||
|
||||
class LimeFormatException(exceptions.LayerException):
|
||||
"""Thrown when an error occurs with the underlying Lime file format"""
|
||||
|
||||
class LimeLayer(interfaces.layers.TranslationLayerInterface):
|
||||
"""A Lime format TranslationLayer. Lime is generally used to store
|
||||
physical memory images where there are large holes in the physical
|
||||
address space"""
|
||||
|
||||
provides = {"type": "physical"}
|
||||
priority = 21
|
||||
|
||||
MAGIC = 0x4c694d45
|
||||
VERSION = 1
|
||||
|
||||
# Magic[4], Version[4], Start[8], End[8], Reserved[8]
|
||||
# XXX move this to a custom SymbolSpace?
|
||||
_header_struct = struct.Struct('<IIQQQ')
|
||||
|
||||
def __init__(self, context, config_path, name, base_layer):
|
||||
interfaces.layers.TranslationLayerInterface.__init__(self, context, config_path, name)
|
||||
|
||||
self._base_layer = base_layer
|
||||
|
||||
# list of tuples (logical start, base start, size)
|
||||
# loaded by _load_segments() on first access
|
||||
self._segments = []
|
||||
self._minaddr = 0
|
||||
self._maxaddr = 0
|
||||
|
||||
@property
|
||||
def minimum_address(self):
|
||||
return self._minaddr
|
||||
|
||||
@property
|
||||
def maximum_address(self):
|
||||
return self._maxaddr
|
||||
|
||||
def _load_segments(self):
|
||||
base_layer = self._context.memory[self._base_layer]
|
||||
base_maxaddr = base_layer.maximum_address
|
||||
maxaddr = 0
|
||||
offset = 0
|
||||
header_size = self._header_struct.size
|
||||
segments = []
|
||||
|
||||
while offset < base_maxaddr:
|
||||
header_data = base_layer.read(offset, header_size)
|
||||
|
||||
(magic, version, start, end, reserved) = self._header_struct.unpack(header_data)
|
||||
if magic != self.MAGIC:
|
||||
raise LimeFormatException("bad magic 0x%x at file offset 0x%x" % (magic, offset))
|
||||
|
||||
if version != self.VERSION:
|
||||
raise LimeFormatException("unexpected version %d at file offset 0x%x" % (version, offset))
|
||||
|
||||
if start < maxaddr or end < start:
|
||||
raise LimeFormatException("bad start/end 0x%x/0x%x at file offset 0x%x" % (start, end, offset))
|
||||
|
||||
segment_length = end - start + 1
|
||||
segments.append((start, offset + header_size, segment_length))
|
||||
maxaddr = end
|
||||
offset = offset + header_size + segment_length
|
||||
|
||||
if len(segments) == 0:
|
||||
raise LimeFormatException("No LiME segments defined in " + self._base_layer)
|
||||
|
||||
self._segments = segments
|
||||
self._minaddr = segments[0][0]
|
||||
self._maxaddr = maxaddr
|
||||
|
||||
|
||||
def _find_segment(self, offset):
|
||||
"""Finds the segment containing a given offset
|
||||
|
||||
Returns the segment tuple
|
||||
"""
|
||||
|
||||
if not self._segments:
|
||||
self._load_segments()
|
||||
|
||||
for logical_start, base_start, size in self._segments:
|
||||
if offset >= logical_start and offset < (logical_start + size):
|
||||
return (logical_start, base_start, size)
|
||||
|
||||
raise exceptions.InvalidAddressException("Lime fault at address " + hex(offset))
|
||||
|
||||
|
||||
def is_valid(self, offset, length = 1):
|
||||
"""Returns whether the address offset can be translated to a valid address"""
|
||||
try:
|
||||
return all([self._context.memory[self._base_layer].is_valid(mapped_offset) for _, mapped_offset, _, _ in
|
||||
self.mapping(offset, length)])
|
||||
except exceptions.InvalidAddressException:
|
||||
return False
|
||||
|
||||
def mapping(self, offset, length):
|
||||
"""Returns a sorted list of (offset, mapped_offset, length, layer) mappings"""
|
||||
if length == 0:
|
||||
logical_start, base_start, size = self._find_segment(offset)
|
||||
mapped_offset = offset - logical_start + base_start
|
||||
return [(offset, mapped_offset, 0, self._base_layer)]
|
||||
result = []
|
||||
while length > 0:
|
||||
logical_start, base_start, size = self._find_segment(offset)
|
||||
chunk_offset = offset - logical_start + base_start
|
||||
chunk_size = min(size - (offset - logical_start), length)
|
||||
result.append((offset, chunk_offset, chunk_size, self._base_layer))
|
||||
length -= chunk_size
|
||||
offset += chunk_size
|
||||
return result
|
||||
|
||||
@property
|
||||
def dependencies(self):
|
||||
"""Returns a list of the lower layers that this layer is dependent upon"""
|
||||
return [self._base_layer]
|
||||
|
||||
@classmethod
|
||||
def get_schema(cls):
|
||||
return [requirements.TranslationLayerRequirement(name = 'base_layer',
|
||||
constraints = {"type": "physical"},
|
||||
optional = False)]
|
||||
@@ -62,7 +62,9 @@ class FileLayer(interfaces.layers.DataLayerInterface):
|
||||
def __init__(self, context, config_path, name, filename):
|
||||
interfaces.layers.DataLayerInterface.__init__(self, context, config_path, name)
|
||||
|
||||
self._file = open(filename, "r+b")
|
||||
# FIXME: Add "+" to the mode once we've determined whether write mode is enabled
|
||||
mode = "rb"
|
||||
self._file = open(filename, mode)
|
||||
self._size = os.path.getsize(filename)
|
||||
|
||||
@property
|
||||
@@ -78,6 +80,8 @@ class FileLayer(interfaces.layers.DataLayerInterface):
|
||||
|
||||
def is_valid(self, offset, length = 1):
|
||||
"""Returns whether the offset is valid or not"""
|
||||
if length <= 0:
|
||||
raise TypeError("Length must be positive")
|
||||
return (self.minimum_address <= offset <= self.maximum_address and
|
||||
self.minimum_address <= offset + length - 1 <= self.maximum_address)
|
||||
|
||||
@@ -85,8 +89,6 @@ class FileLayer(interfaces.layers.DataLayerInterface):
|
||||
"""Reads from the file at offset for length"""
|
||||
if not self.is_valid(offset, length):
|
||||
raise exceptions.InvalidAddressException("Offset outside of the " + self.name + " file boundaries")
|
||||
if length < 0:
|
||||
raise TypeError("Length must be positive")
|
||||
self._file.seek(offset)
|
||||
data = self._file.read(length)
|
||||
if len(data) < length:
|
||||
|
||||
@@ -26,19 +26,23 @@ class Void(interfaces.objects.ObjectInterface):
|
||||
raise TypeError("Cannot write data to a void, recast as another object")
|
||||
|
||||
|
||||
class Function(interfaces.objects.ObjectInterface):
|
||||
""""""
|
||||
|
||||
|
||||
class PrimitiveObject(interfaces.objects.ObjectInterface):
|
||||
"""PrimitiveObject is an interface for any objects that should simulate a Python primitive"""
|
||||
_struct_type = int
|
||||
|
||||
def __init__(self, context, structure_name, object_info, struct_format):
|
||||
def __init__(self, context, type_name, object_info, struct_format):
|
||||
interfaces.objects.ObjectInterface.__init__(self,
|
||||
context = context,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
struct_format = struct_format)
|
||||
self._struct_format = struct_format
|
||||
|
||||
def __new__(cls, context, structure_name, object_info, struct_format, **kwargs):
|
||||
def __new__(cls, context, type_name, object_info, struct_format, **kwargs):
|
||||
"""Creates the appropriate class and returns it so that the native type is inherritted
|
||||
|
||||
The only reason the **kwargs is added, is so that the inherriting types can override __init__
|
||||
@@ -84,15 +88,15 @@ class Bytes(PrimitiveObject, bytes):
|
||||
"""Primitive Object that handles specific series of bytes"""
|
||||
_struct_type = bytes
|
||||
|
||||
def __init__(self, context, structure_name, object_info, length = 1):
|
||||
def __init__(self, context, type_name, object_info, length = 1):
|
||||
interfaces.objects.ObjectInterface.__init__(self,
|
||||
context = context,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
struct_format = str(length) + "s")
|
||||
self._vol['length'] = length
|
||||
|
||||
def __new__(cls, context, structure_name, object_info, length = 1, **kwargs):
|
||||
def __new__(cls, context, type_name, object_info, length = 1, **kwargs):
|
||||
"""Creates the appropriate class and returns it so that the native type is inherritted
|
||||
|
||||
The only reason the **kwargs is added, is so that the inherriting types can override __init__
|
||||
@@ -112,17 +116,17 @@ class String(PrimitiveObject, str):
|
||||
"""
|
||||
_struct_type = str
|
||||
|
||||
def __init__(self, context, structure_name, object_info, max_length = 1, encoding = "utf-8", errors = None):
|
||||
def __init__(self, context, type_name, object_info, max_length = 1, encoding = "utf-8", errors = None):
|
||||
PrimitiveObject.__init__(self,
|
||||
context = context,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
struct_format = str(max_length) + 's')
|
||||
self._vol["max_length"] = max_length
|
||||
self._vol['encoding'] = encoding
|
||||
self._vol['errors'] = errors
|
||||
|
||||
def __new__(cls, context, structure_name, object_info, max_length = 1, encoding = "utf-8", errors = None, **kwargs):
|
||||
def __new__(cls, context, type_name, object_info, max_length = 1, encoding = "utf-8", errors = None, **kwargs):
|
||||
"""Creates the appropriate class and returns it so that the native type is inherited
|
||||
|
||||
The only reason the **kwargs is added, is so that the inherriting types can override __init__
|
||||
@@ -145,12 +149,12 @@ class String(PrimitiveObject, str):
|
||||
class Pointer(Integer):
|
||||
"""Pointer which points to another object"""
|
||||
|
||||
def __init__(self, context, structure_name, object_info, struct_format, target = None):
|
||||
def __init__(self, context, type_name, object_info, struct_format, target = None):
|
||||
self._check_type(target, templates.ObjectTemplate)
|
||||
Integer.__init__(self,
|
||||
context = context,
|
||||
object_info = object_info,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
struct_format = struct_format)
|
||||
self._vol['target'] = target
|
||||
|
||||
@@ -195,16 +199,16 @@ class Pointer(Integer):
|
||||
class BitField(PrimitiveObject, int):
|
||||
"""Object containing a field which is made up of bits rather than whole bytes"""
|
||||
|
||||
def __new__(cls, context, structure_name, object_info, struct_format, target = None, start_bit = 0, end_bit = 0):
|
||||
def __new__(cls, context, type_name, object_info, struct_format, target = None, start_bit = 0, end_bit = 0):
|
||||
cls._check_type(target, Integer)
|
||||
value = target(context = context,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
struct_format = struct_format)
|
||||
return cls._struct_type.__new__(cls, (value >> start_bit) & ((1 << end_bit) - 1))
|
||||
|
||||
def __init__(self, context, structure_name, object_info, struct_format, target = None, start_bit = 0, end_bit = 0):
|
||||
PrimitiveObject.__init__(self, context, structure_name, object_info, struct_format)
|
||||
def __init__(self, context, type_name, object_info, struct_format, target = None, start_bit = 0, end_bit = 0):
|
||||
PrimitiveObject.__init__(self, context, type_name, object_info, struct_format)
|
||||
self._vol['target'] = target
|
||||
self._vol['start_bit'] = start_bit
|
||||
self._vol['end_bit'] = end_bit
|
||||
@@ -232,11 +236,11 @@ 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, structure_name, object_info, count = 0, target = None):
|
||||
def __init__(self, context, type_name, object_info, count = 0, target = None):
|
||||
self._check_type(target, templates.ObjectTemplate)
|
||||
interfaces.objects.ObjectInterface.__init__(self,
|
||||
context = context,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
object_info = object_info)
|
||||
self._vol['count'] = self._check_type(count, int)
|
||||
self._vol['target'] = target
|
||||
@@ -293,10 +297,10 @@ 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, structure_name, object_info, size, members):
|
||||
def __init__(self, context, type_name, object_info, size, members):
|
||||
interfaces.objects.ObjectInterface.__init__(self,
|
||||
context = context,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
size = size,
|
||||
members = members)
|
||||
@@ -306,7 +310,7 @@ class Struct(interfaces.objects.ObjectInterface):
|
||||
class VolTemplateProxy(interfaces.objects.ObjectInterface.VolTemplateProxy):
|
||||
@classmethod
|
||||
def size(cls, template):
|
||||
"""Method to return the size of this structure"""
|
||||
"""Method to return the size of this type"""
|
||||
if template.vol.get('size', None) is None:
|
||||
raise TypeError("Struct ObjectTemplate not provided with a size")
|
||||
return template.vol.size
|
||||
@@ -339,7 +343,7 @@ class Struct(interfaces.objects.ObjectInterface):
|
||||
@classmethod
|
||||
def _check_members(cls, members):
|
||||
# Members should be an iterable mapping of symbol names to tuples of (relative_offset, ObjectTemplate)
|
||||
# An object template is a callable that when called with a context, offset, layer_name and structure_name
|
||||
# An object template is a callable that when called with a context, offset, layer_name and type_name
|
||||
if not isinstance(members, collections.Mapping):
|
||||
raise TypeError("Struct members parameter must be a mapping not " + type(members))
|
||||
if not all([(isinstance(member, tuple) and len(member) == 2) for member in members.values()]):
|
||||
@@ -350,7 +354,7 @@ class Struct(interfaces.objects.ObjectInterface):
|
||||
return self.__getattr__(attr)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
"""Method for accessing members of the structure"""
|
||||
"""Method for accessing members of the type"""
|
||||
if attr in self._concrete_members:
|
||||
return self._concrete_members[attr]
|
||||
elif attr in self.vol.members:
|
||||
@@ -362,7 +366,16 @@ class Struct(interfaces.objects.ObjectInterface):
|
||||
parent = self))
|
||||
self._concrete_members[attr] = member
|
||||
return member
|
||||
raise AttributeError("'" + self.vol.structure_name + "' Struct has no attribute '" + attr + "'")
|
||||
raise AttributeError("'" + self.vol.type_name + "' Struct has no attribute '" + attr + "'")
|
||||
|
||||
def write(self, value):
|
||||
raise TypeError("Structs cannot be written to directly, individual members must be written instead")
|
||||
|
||||
|
||||
# Nice way of duplicating the class, but *could* causes problems with isintance
|
||||
class Union(Struct):
|
||||
pass
|
||||
|
||||
# Really nasty way of duplicating the class
|
||||
# WILL cause problems with any mutable class/static variables
|
||||
# Union = type('Union', Struct.__bases__, dict(Struct.__dict__))
|
||||
|
||||
@@ -12,14 +12,14 @@ class ObjectTemplate(interfaces.objects.Template, validity.ValidityRoutines):
|
||||
|
||||
This is effectively a method of currying, but adds more structure to avoid abuse.
|
||||
It also allows inspection of information that should already be known:
|
||||
* Structure size
|
||||
* Type size
|
||||
* Members, etc
|
||||
etc.
|
||||
"""
|
||||
|
||||
def __init__(self, object_class = None, structure_name = None, **arguments):
|
||||
def __init__(self, object_class = None, type_name = None, **arguments):
|
||||
interfaces.objects.Template.__init__(self,
|
||||
structure_name = structure_name,
|
||||
type_name = type_name,
|
||||
**arguments)
|
||||
self._check_class(object_class, interfaces.objects.ObjectInterface)
|
||||
self.update_vol(object_class = object_class)
|
||||
@@ -71,5 +71,5 @@ class ReferenceTemplate(interfaces.objects.Template):
|
||||
"""
|
||||
|
||||
def __call__(self, context, object_info):
|
||||
template = context.symbol_space.get_structure(self.vol.structure_name)
|
||||
template = context.symbol_space.get_type(self.vol.type_name)
|
||||
return template(context = context, object_info = object_info)
|
||||
|
||||
@@ -8,14 +8,14 @@ import collections
|
||||
import collections.abc
|
||||
import warnings
|
||||
|
||||
from volatility.framework import objects, interfaces, exceptions
|
||||
from volatility.framework import objects, interfaces, exceptions, constants
|
||||
from volatility.framework.symbols import native, vtypes, windows
|
||||
|
||||
|
||||
class SymbolType(object):
|
||||
# Suitably random values until we make this an Enum and require python >= 3.4
|
||||
STRUCTURE = 143534545
|
||||
CONSTANT = 28293045
|
||||
TYPE = 143534545
|
||||
SYMBOL = 28293045
|
||||
|
||||
|
||||
class SymbolSpace(collections.abc.Mapping):
|
||||
@@ -25,25 +25,43 @@ class SymbolSpace(collections.abc.Mapping):
|
||||
proceed down through the ranks if a namespace isn't specified.
|
||||
"""
|
||||
|
||||
def __init__(self, native_structures = None):
|
||||
if not isinstance(native_structures, interfaces.symbols.NativeTableInterface):
|
||||
raise TypeError("SymbolSpace native_structures must be NativeSymbolInterface")
|
||||
def __init__(self, native_types = None):
|
||||
if not isinstance(native_types, interfaces.symbols.NativeTableInterface):
|
||||
raise TypeError("SymbolSpace native_types must be NativeSymbolInterface")
|
||||
self._dict = collections.OrderedDict()
|
||||
self._native_structures = native_structures
|
||||
self._native_types = native_types
|
||||
# Permanently cache all resolved symbols
|
||||
self._resolved = {}
|
||||
|
||||
def get_symbols_by_type(self, type_name):
|
||||
"""Returns all symbols based """
|
||||
for table in self._dict.keys():
|
||||
for symbol_name in self._dict[table].get_symbols_by_type(type_name):
|
||||
yield table + constants.BANG + symbol_name
|
||||
|
||||
def get_symbols_by_location(self, offset, table_name = None):
|
||||
"""Returns all symbols that exist at a specific relative offset"""
|
||||
table_list = self._dict.values()
|
||||
if table_name is not None:
|
||||
if table_name in self._dict:
|
||||
table_list = [self._dict[table_name]]
|
||||
else:
|
||||
table_list = []
|
||||
for table in table_list:
|
||||
for symbol_name in self._dict[table].get_symbols_by_location(offset = offset):
|
||||
yield table + constants.BANG + symbol_name
|
||||
|
||||
@property
|
||||
def natives(self):
|
||||
"""Returns the native_types for this symbol space"""
|
||||
return self._native_structures
|
||||
return self._native_types
|
||||
|
||||
@natives.setter
|
||||
def natives(self, native_structures):
|
||||
if native_structures is not None:
|
||||
def natives(self, native_types):
|
||||
if native_types is not None:
|
||||
warnings.warn(
|
||||
"Resetting the native type can cause have drastic effects on memory analysis using this space")
|
||||
self._native_structures = native_structures
|
||||
self._native_types = native_types
|
||||
|
||||
def __len__(self):
|
||||
"""Returns the number of tables within the space"""
|
||||
@@ -73,32 +91,32 @@ class SymbolSpace(collections.abc.Mapping):
|
||||
|
||||
def _weak_resolve(self, resolve_type, name):
|
||||
"""Takes a symbol name and resolves it with ReferentialTemplates"""
|
||||
if resolve_type == SymbolType.STRUCTURE:
|
||||
get_function = 'get_structure'
|
||||
elif resolve_type == SymbolType.CONSTANT:
|
||||
get_function = 'get_constant'
|
||||
if resolve_type == SymbolType.TYPE:
|
||||
get_function = 'get_type'
|
||||
elif resolve_type == SymbolType.SYMBOL:
|
||||
get_function = 'get_symbol'
|
||||
else:
|
||||
raise ValueError("Weak_resolve called without a proper SymbolType.")
|
||||
|
||||
name_array = name.split("!")
|
||||
name_array = name.split(constants.BANG)
|
||||
if len(name_array) == 2:
|
||||
table_name = name_array[0]
|
||||
component_name = name_array[1]
|
||||
return getattr(self._dict[table_name], get_function)(component_name)
|
||||
elif name in self.natives.structures:
|
||||
elif name in self.natives.types:
|
||||
return getattr(self.natives, get_function)(name)
|
||||
raise exceptions.SymbolError("Malformed symbol name")
|
||||
|
||||
def get_structure(self, structure_name):
|
||||
def get_type(self, type_name):
|
||||
"""Takes a symbol name and resolves it
|
||||
|
||||
This method ensures that all referenced templates (including self-referential templates)
|
||||
are satisfied as ObjectTemplates
|
||||
"""
|
||||
# Traverse down any resolutions
|
||||
if structure_name not in self._resolved:
|
||||
self._resolved[structure_name] = self._weak_resolve(SymbolType.STRUCTURE, structure_name)
|
||||
traverse_list = [structure_name]
|
||||
if type_name not in self._resolved:
|
||||
self._resolved[type_name] = self._weak_resolve(SymbolType.TYPE, type_name)
|
||||
traverse_list = [type_name]
|
||||
replacements = set()
|
||||
# Whole Symbols that still need traversing
|
||||
while traverse_list:
|
||||
@@ -110,18 +128,18 @@ class SymbolSpace(collections.abc.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.vol.structure_name not in self._resolved:
|
||||
traverse_list.append(child.vol.structure_name)
|
||||
self._resolved[child.vol.structure_name] = self._weak_resolve(SymbolType.STRUCTURE,
|
||||
child.vol.structure_name)
|
||||
if child.vol.type_name not in self._resolved:
|
||||
traverse_list.append(child.vol.type_name)
|
||||
self._resolved[child.vol.type_name] = self._weak_resolve(SymbolType.TYPE,
|
||||
child.vol.type_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.vol.structure_name])
|
||||
return self._resolved[structure_name]
|
||||
parent.replace_child(child, self._resolved[child.vol.type_name])
|
||||
return self._resolved[type_name]
|
||||
|
||||
def get_constant(self, constant_name):
|
||||
"""Look-up a constant name across all the contained symbol spaces"""
|
||||
return self._weak_resolve(SymbolType.CONSTANT, constant_name)
|
||||
def get_symbol(self, symbol_name):
|
||||
"""Look-up a symbol name across all the contained symbol spaces"""
|
||||
return self._weak_resolve(SymbolType.SYMBOL, symbol_name)
|
||||
|
||||
@@ -19,19 +19,19 @@ class NativeTable(interfaces.symbols.NativeTableInterface):
|
||||
native_class, _native_struct = self._native_dictionary[native_type]
|
||||
self._overrides[native_type] = native_class
|
||||
# Create this once early, because it may get used a lot
|
||||
self._structures = set(self._native_dictionary).union(
|
||||
self._types = set(self._native_dictionary).union(
|
||||
{'Enumeration', 'array', 'BitField', 'void', 'pointer', 'String', 'Bytes'})
|
||||
|
||||
def get_structure_class(self, name):
|
||||
def get_type_class(self, name):
|
||||
ntype, fmt = native_types.get(name, (objects.Integer, ''))
|
||||
return ntype
|
||||
|
||||
@property
|
||||
def structures(self):
|
||||
"""Returns an iterator of the structure symbol names"""
|
||||
return self._structures
|
||||
def types(self):
|
||||
"""Returns an iterator of the symbol type names"""
|
||||
return self._types
|
||||
|
||||
def get_structure(self, structure_name):
|
||||
def get_type(self, type_name):
|
||||
"""Resolves a symbol name into an object template
|
||||
|
||||
symbol_space is used to resolve any target symbols if they don't exist in this list
|
||||
@@ -39,31 +39,31 @@ class NativeTable(interfaces.symbols.NativeTableInterface):
|
||||
# NOTE: These need updating whenever the object init signatures change
|
||||
additional = {}
|
||||
obj = None
|
||||
if structure_name == 'void':
|
||||
if type_name == 'void':
|
||||
obj = objects.Void
|
||||
elif structure_name == 'array':
|
||||
elif type_name == 'array':
|
||||
obj = objects.Array
|
||||
additional = {"count": 0, "target": self.get_structure('void')}
|
||||
elif structure_name == 'Enumeration':
|
||||
additional = {"count": 0, "target": self.get_type('void')}
|
||||
elif type_name == 'Enumeration':
|
||||
obj = objects.Enumeration
|
||||
additional = {"target": self.get_structure('void'), "choices": {}}
|
||||
elif structure_name == 'BitField':
|
||||
additional = {"target": self.get_type('void'), "choices": {}}
|
||||
elif type_name == 'BitField':
|
||||
obj = objects.BitField
|
||||
additional = {"start_bit": 0, "end_bit": 0}
|
||||
elif structure_name == 'String':
|
||||
elif type_name == 'String':
|
||||
obj = objects.String
|
||||
additional = {"max_length": 0}
|
||||
elif structure_name == 'Bytes':
|
||||
elif type_name == 'Bytes':
|
||||
obj = objects.Bytes
|
||||
additional = {"length": 0}
|
||||
if obj is not None:
|
||||
return objects.templates.ObjectTemplate(obj, structure_name = structure_name, **additional)
|
||||
return objects.templates.ObjectTemplate(obj, type_name = type_name, **additional)
|
||||
|
||||
_native_type, native_format = self._native_dictionary[structure_name]
|
||||
if structure_name == 'pointer':
|
||||
additional = {'target': self.get_structure('void')}
|
||||
return objects.templates.ObjectTemplate(self.get_structure_class(structure_name), # pylint: disable=W0142
|
||||
structure_name = structure_name,
|
||||
_native_type, native_format = self._native_dictionary[type_name]
|
||||
if type_name == 'pointer':
|
||||
additional = {'target': self.get_type('void')}
|
||||
return objects.templates.ObjectTemplate(self.get_type_class(type_name), # pylint: disable=W0142
|
||||
type_name = type_name,
|
||||
struct_format = native_format,
|
||||
**additional)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Created on 10 Apr 2013
|
||||
|
||||
import copy
|
||||
|
||||
from volatility.framework import exceptions, objects, interfaces
|
||||
from volatility.framework import exceptions, objects, interfaces, constants
|
||||
|
||||
|
||||
# ## TODO
|
||||
@@ -36,22 +36,22 @@ from volatility.framework import exceptions, objects, interfaces
|
||||
# vtype list and a struct dictionary
|
||||
|
||||
class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
|
||||
"""Symbol Table that handles vtype datastructures"""
|
||||
"""Symbol Table that handles vtype datatypes"""
|
||||
|
||||
def __init__(self, name, vtype_dictionary, native_structures = None):
|
||||
interfaces.symbols.SymbolTableInterface.__init__(self, name, native_structures)
|
||||
def __init__(self, name, vtype_dictionary, native_types = None):
|
||||
interfaces.symbols.SymbolTableInterface.__init__(self, name, native_types)
|
||||
self._vtypedict = vtype_dictionary
|
||||
self._overrides = {}
|
||||
|
||||
def get_structure_class(self, name):
|
||||
def get_type_class(self, name):
|
||||
return self._overrides.get(name, objects.Struct)
|
||||
|
||||
def set_structure_class(self, name, clazz):
|
||||
if name not in self.structures:
|
||||
raise ValueError("Symbol " + name + " not in " + self.name + " SymbolTable")
|
||||
def set_type_class(self, name, clazz):
|
||||
if name not in self.types:
|
||||
raise ValueError("Symbol type " + name + " not in " + self.name + " SymbolTable")
|
||||
self._overrides[name] = clazz
|
||||
|
||||
def del_structure_class(self, name):
|
||||
def del_type_class(self, name):
|
||||
if name in self._overrides:
|
||||
del self._overrides[name]
|
||||
|
||||
@@ -60,23 +60,23 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
|
||||
if not dictionary:
|
||||
raise exceptions.SymbolSpaceError("Invalid vtype dictionary: " + repr(dictionary))
|
||||
|
||||
structure_name = dictionary[0]
|
||||
type_name = dictionary[0]
|
||||
|
||||
if structure_name in self.natives.structures:
|
||||
if type_name in self.natives.types:
|
||||
# The symbol is a native type
|
||||
native_template = self.natives.get_structure(structure_name)
|
||||
native_template = self.natives.get_type(type_name)
|
||||
|
||||
# Add specific additional parameters, etc
|
||||
update = {}
|
||||
if structure_name == 'array':
|
||||
if type_name == 'array':
|
||||
update['count'] = dictionary[1]
|
||||
update['target'] = self._vtypedict_to_template(dictionary[2])
|
||||
elif structure_name == 'pointer':
|
||||
elif type_name == 'pointer':
|
||||
update["target"] = self._vtypedict_to_template(dictionary[1])
|
||||
elif structure_name == 'Enumeration':
|
||||
elif type_name == 'Enumeration':
|
||||
update = copy.deepcopy(dictionary[1])
|
||||
update["target"] = self._vtypedict_to_template([update['target']])
|
||||
elif structure_name == 'BitField':
|
||||
elif type_name == 'BitField':
|
||||
update = dictionary[1]
|
||||
update['target'] = self._vtypedict_to_template([update['native_type']])
|
||||
native_template.update_vol(**update) # pylint: disable=W0142
|
||||
@@ -86,25 +86,25 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
|
||||
if len(dictionary) > 1:
|
||||
raise exceptions.SymbolSpaceError("Unknown vtype format: " + repr(dictionary))
|
||||
|
||||
return objects.templates.ReferenceTemplate(structure_name = self.name + "!" + structure_name)
|
||||
return objects.templates.ReferenceTemplate(type_name = self.name + constants.BANG + type_name)
|
||||
|
||||
@property
|
||||
def structures(self):
|
||||
def types(self):
|
||||
"""Returns an iterator of the symbol names"""
|
||||
return self._vtypedict.keys()
|
||||
|
||||
def get_structure(self, structure_name):
|
||||
def get_type(self, type_name):
|
||||
"""Resolves an individual symbol"""
|
||||
if structure_name not in self._vtypedict:
|
||||
if type_name not in self._vtypedict:
|
||||
raise exceptions.SymbolError
|
||||
size, curdict = self._vtypedict[structure_name]
|
||||
size, curdict = self._vtypedict[type_name]
|
||||
members = {}
|
||||
for member_name in curdict:
|
||||
relative_offset, vtypedict = curdict[member_name]
|
||||
member = (relative_offset, self._vtypedict_to_template(vtypedict))
|
||||
members[member_name] = member
|
||||
object_class = self.get_structure_class(structure_name)
|
||||
return objects.templates.ObjectTemplate(structure_name = self.name + "!" + structure_name,
|
||||
object_class = self.get_type_class(type_name)
|
||||
return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + type_name,
|
||||
object_class = object_class,
|
||||
size = size,
|
||||
members = members)
|
||||
|
||||
@@ -12,13 +12,13 @@ class _ETHREAD(objects.Struct):
|
||||
|
||||
|
||||
class _LIST_ENTRY(objects.Struct, collections.abc.Iterable):
|
||||
def to_list(self, structure, member, forward = True, sentinel = True, layer = None):
|
||||
def to_list(self, symbol_type, member, forward = True, sentinel = True, layer = None):
|
||||
"""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_structure(structure).relative_child_offset(member)
|
||||
relative_offset = self._context.symbol_space.get_type(symbol_type).relative_child_offset(member)
|
||||
|
||||
direction = 'Blink'
|
||||
if forward:
|
||||
@@ -26,16 +26,16 @@ class _LIST_ENTRY(objects.Struct, collections.abc.Iterable):
|
||||
link = getattr(self, direction).dereference()
|
||||
|
||||
if not sentinel:
|
||||
yield self._context.object(structure, layer, offset = self.vol.offset - relative_offset)
|
||||
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(structure, layer, offset = link.vol.offset - relative_offset)
|
||||
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):
|
||||
return self.to_list(self.vol.parent.vol.structure_name, self.vol.member_name)
|
||||
return self.to_list(self.vol.parent.vol.type_name, self.vol.member_name)
|
||||
|
||||
@@ -38,8 +38,8 @@ class WindowsKernelSymbolProvider(interfaces.symbols.SymbolTableProviderInterfac
|
||||
vtype_table = vtypes.VTypeSymbolTable(cls.space_name, virtual_types, context.symbol_space.natives)
|
||||
|
||||
# Set-up windows specific types
|
||||
vtype_table.set_structure_class('_ETHREAD', extensions._ETHREAD)
|
||||
vtype_table.set_structure_class('_LIST_ENTRY', extensions._LIST_ENTRY)
|
||||
vtype_table.set_type_class('_ETHREAD', extensions._ETHREAD)
|
||||
vtype_table.set_type_class('_LIST_ENTRY', extensions._LIST_ENTRY)
|
||||
|
||||
context.symbol_space.append(vtype_table)
|
||||
context.config[config_path] = cls.space_name
|
||||
|
||||
@@ -27,7 +27,7 @@ class PsList(plugins.PluginInterface):
|
||||
# Get the process in the physical space
|
||||
flateproc = ctx.object("ntkrnlmp!_EPROCESS", physical_layer, offset = offset)
|
||||
# Determine the relative offset from the Thread head to the ThreadListEntry
|
||||
reloff = ctx.symbol_space.get_structure("ntkrnlmp!_ETHREAD").relative_child_offset("ThreadListEntry")
|
||||
reloff = ctx.symbol_space.get_type("ntkrnlmp!_ETHREAD").relative_child_offset("ThreadListEntry")
|
||||
# Get the thread object in kernel space from the
|
||||
ethread = ctx.object("ntkrnlmp!_ETHREAD", kernel_layer, offset = flateproc.ThreadListHead.Flink - reloff)
|
||||
# Get the process from the thread object in kernel space
|
||||
|
||||
Reference in New Issue
Block a user