mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-17 20:35:40 +02:00
Enhance symbol listing and templates, add in gitignore and test rig.
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
__pycache__
|
||||
*.pyc
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
'''
|
||||
Created on 10 Mar 2013
|
||||
|
||||
@author: mike
|
||||
'''
|
||||
|
||||
from volatility.framework import xp_sp2_x86_vtypes, symbols
|
||||
|
||||
if __name__ == '__main__':
|
||||
vtypes = xp_sp2_x86_vtypes.ntkrnlmp_types
|
||||
|
||||
ntkrnlmp = symbols.VTypeSymbolList('ntkrnlmp', vtypes)
|
||||
sspace = symbols.SymbolSpace()
|
||||
sspace.append(ntkrnlmp)
|
||||
sspace.resolve('ntkrnlmp!_FXSAVE_FORMAT')
|
||||
|
||||
@@ -15,19 +15,18 @@ _current = 3 # Number of releases of the library with any change
|
||||
_revision = 0 # Number of changes that don't affect the interface
|
||||
_age = 0 # Number of consecutive versions of the interface the current version supports
|
||||
|
||||
import volatility.framework.exceptions as exceptions
|
||||
|
||||
@property
|
||||
def version():
|
||||
"""Provides the so version number of the library"""
|
||||
return _current - _age, _age, _revision
|
||||
|
||||
def require_version(*args):
|
||||
"""Checks the required version of a plugin"""
|
||||
if len(args):
|
||||
if args[0] != version[0]:
|
||||
raise exceptions.VolatilityException("Framework version " + str(version[0]) + " is incompatible with required version " + str(args[0]))
|
||||
if args[0] != version()[0]:
|
||||
raise Exception("Framework version " + str(version()[0]) + " is incompatible with required version " + str(args[0]))
|
||||
if len(args) > 1:
|
||||
if args[1] > version[1]:
|
||||
raise exceptions.VolatilityException("Framework version " + ".".join([str(x) for x in version[0:1]]) + " is an older revision than the required version " + ".".join([str(x) for x in args[0:2]]))
|
||||
if args[1] > version()[1]:
|
||||
raise Exception("Framework version " + ".".join([str(x) for x in version()[0:1]]) + " is an older revision than the required version " + ".".join([str(x) for x in args[0:2]]))
|
||||
|
||||
|
||||
|
||||
|
||||
+20
-13
@@ -6,6 +6,7 @@ Created on 17 Feb 2013
|
||||
|
||||
import struct
|
||||
import collections
|
||||
import volatility.framework.templates as templates
|
||||
|
||||
class ObjectInterface(object):
|
||||
""" A base object required to be the ancestor of every object used in volatility """
|
||||
@@ -30,23 +31,25 @@ class PrimitiveObject(ObjectInterface):
|
||||
class Integer(PrimitiveObject, int):
|
||||
"""Primitive Object that handles standard numeric types"""
|
||||
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, size, struct_format, **kwargs):
|
||||
struct_format = context.get_primitive_struct_type("int", symbol_name)
|
||||
return cls._struct_value(struct_format, context, layer_name, offset, symbol_name)
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, struct_format, **kwargs):
|
||||
struct_format, struct_size = context.get_primitive_struct_type("int", symbol_name)
|
||||
struct_size = struct.calcsize(struct_format)
|
||||
return cls._struct_value(struct_format, context, layer_name, offset, symbol_name, size = struct_size)
|
||||
|
||||
class Float(PrimitiveObject, float):
|
||||
"""Primitive Object that handles double or floating point numbers"""
|
||||
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, **kwargs):
|
||||
struct_format = context.get_primitive_struct_type("float", symbol_name)
|
||||
return cls._struct_value(struct_format, context, layer_name, offset, symbol_name)
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, size, **kwargs):
|
||||
struct_format, struct_size = context.get_primitive_struct_type("float", symbol_name)
|
||||
struct_size = struct.calcsize(struct_format)
|
||||
return cls._struct_value(struct_format, context, layer_name, offset, symbol_name, size = struct_size)
|
||||
|
||||
class Bytes(PrimitiveObject, bytes):
|
||||
"""Primitive Object that handles specific series of bytes
|
||||
"""
|
||||
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, **kwargs):
|
||||
return cls._struct_value(str(length) + "s", context, layer_name, offset, symbol_name)
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, size, **kwargs):
|
||||
return cls._struct_value(str(size) + "s", context, layer_name, offset, symbol_name, size)
|
||||
|
||||
class String(PrimitiveObject, str):
|
||||
"""Primitive Object that handles string values
|
||||
@@ -54,21 +57,25 @@ class String(PrimitiveObject, str):
|
||||
length: specifies the maximum possible length that the string could hold in memory
|
||||
"""
|
||||
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, length = 1):
|
||||
return cls._struct_value(str(length) + "s", context, layer_name, offset, symbol_name)
|
||||
def __new__(cls, context, layer_name, offset, symbol_name, size = None, length = 1):
|
||||
return cls._struct_value(str(length) + "s", context, layer_name, offset, symbol_name, size)
|
||||
|
||||
class Struct(ObjectInterface):
|
||||
"""Object which can contain members that are other objects"""
|
||||
|
||||
def __init__(self, context, layer_name, offset, symbol_name, size = None, members = None):
|
||||
super(Struct).__init__(self, context, layer_name, offset, symbol_name, size)
|
||||
# Members should be an iterable mapping of symbol names to callable Object Templates
|
||||
# An object template is a callable that when called with a context, offset, layer_name and symbol_name
|
||||
if not isinstance(members, collections.Iterable):
|
||||
raise
|
||||
if struct_size is None:
|
||||
raise TypeError("Struct members parameter must be iterable not " + type(members))
|
||||
if not all([isinstance(members, templates.MemberTemplate)]):
|
||||
raise TypeError("Struct members must be derived from MemberTemplate objects")
|
||||
if size is None:
|
||||
# Attempt to determine the maximum size by asking
|
||||
for i in members:
|
||||
|
||||
pass
|
||||
|
||||
self._members = members
|
||||
|
||||
def __getattr__(self, attr):
|
||||
|
||||
@@ -5,8 +5,10 @@ Created on 7 Feb 2013
|
||||
'''
|
||||
|
||||
import volatility.framework.exceptions as exceptions
|
||||
from volatility.framework import templates
|
||||
from volatility.framework import obj
|
||||
|
||||
class SymbolSpace(dict):
|
||||
class SymbolSpace(list):
|
||||
"""Handles a collection of SymbolLists"""
|
||||
|
||||
def resolve(self, symbol):
|
||||
@@ -14,11 +16,12 @@ class SymbolSpace(dict):
|
||||
if len(symarr) == 2:
|
||||
listname = symarr[0]
|
||||
symname = symarr[1]
|
||||
if listname in [value.name for value in self]:
|
||||
if symname in self[listname]:
|
||||
return self[listname].resolve(symname)
|
||||
else:
|
||||
raise exceptions.SymbolNotFoundException("Symbol " + symname + " could not be found in the " + listname + " list")
|
||||
for symlist in self:
|
||||
if symlist.name == listname:
|
||||
if symname in symlist:
|
||||
return symlist[symname]
|
||||
else:
|
||||
raise exceptions.SymbolNotFoundException("Symbol " + symname + " could not be found in the " + listname + " list")
|
||||
else:
|
||||
raise exceptions.SymbolNotFoundException("Symbol list " + listname + " was not present in the symbol space")
|
||||
elif len(symarr) == 1:
|
||||
@@ -33,20 +36,69 @@ class SymbolSpace(dict):
|
||||
# Consider maintaining a list of symbollist names
|
||||
# A list of potentially conflicting symbols (for when no listname is provided)
|
||||
|
||||
|
||||
class SymbolList(object):
|
||||
class SymbolListInterface(object):
|
||||
"""Handles a list of symbols"""
|
||||
|
||||
def __init__(self, name):
|
||||
def __init__(self, name, *args, **kwargs):
|
||||
super(SymbolListInterface).__init__(*args, **kwargs)
|
||||
if not isinstance(name, str) or not name:
|
||||
raise exceptions.SymbolSpaceError("Symbol lists cannot be nameless")
|
||||
self.name = name
|
||||
|
||||
def resolve(self, symbolname):
|
||||
def __len__(self):
|
||||
"""Returns the number of items in the symbol list"""
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Resolves a symbol name into an object template"""
|
||||
|
||||
def __contains__(self, symbol):
|
||||
return symbol in self.get_symbols()
|
||||
def __setitem__(self, key, value):
|
||||
# TODO: Determine whether this is an appropriate design decision
|
||||
"""Overrides a symbol's class from a Struct to the value"""
|
||||
|
||||
def get_symbols(self):
|
||||
"""Returns a list of all available symbols"""
|
||||
def __delitem__(self, key):
|
||||
# TODO: Determine whether this is an appropriate design decision
|
||||
"""Removes the class override back to a Struct"""
|
||||
|
||||
def __iter__(self):
|
||||
"""Returns an iterator of the symbol names"""
|
||||
|
||||
def __contains__(self, symbol):
|
||||
"""Determines whether a symbol exists in the list or not"""
|
||||
|
||||
class VTypeSymbolList(SymbolListInterface):
|
||||
"""Symbol List that handles"""
|
||||
|
||||
def __init__(self, name, vtype_dictionary):
|
||||
super(VTypeSymbolList, self).__init__(name)
|
||||
self._vtypedict = vtype_dictionary
|
||||
self._classdict = {}
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Resolves a symbol name into an object template"""
|
||||
size, curdict = self._vtypedict[key]
|
||||
for item in curdict:
|
||||
relative_offset, vtypedict = curdict[item]
|
||||
self._vtypedict_to_template(vtypedict)
|
||||
templates.MemberTemplate(self._classdict.get(key, obj.Struct), symbol_name = item, size = None, relative_offset = relative_offset)
|
||||
members = [self._vtypedict_to_template(curdict[item]) for item in curdict]
|
||||
return templates.ObjectTemplate(self._classdict.get(key, obj.Struct), symbol_name = key, size = size, members = members)
|
||||
|
||||
def _vtypedict_to_template(self, dictionary):
|
||||
"""Converts a vtypedict into an object template"""
|
||||
print(repr(dictionary))
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Overrides a symbol's class from a Struct to the value"""
|
||||
self._classdict[key] = value
|
||||
|
||||
def __iter__(self):
|
||||
"""Returns an iterator of the symbol names"""
|
||||
return set(self._classdict.keys() + self._vtypedict.keys())
|
||||
|
||||
def __contains__(self, value):
|
||||
"""Determines whether a symbol exists in the list or not"""
|
||||
return (value in self._vtypedict or value in self._classdict)
|
||||
|
||||
def resolve(self, symbolname):
|
||||
if symbolname not in self._vtypedict:
|
||||
raise exceptions.SymbolNotFoundException
|
||||
|
||||
@@ -4,8 +4,6 @@ Created on 1 Mar 2013
|
||||
@author: mike
|
||||
'''
|
||||
|
||||
import volatility.framework.obj as obj
|
||||
|
||||
class ObjectTemplate(object):
|
||||
"""Factory class that produces objects that adhere to the Object interface on demand
|
||||
|
||||
@@ -15,21 +13,29 @@ class ObjectTemplate(object):
|
||||
* Members, etc
|
||||
etc.
|
||||
"""
|
||||
def __init__(self, objclass, **kwargs):
|
||||
def __init__(self, objclass, symbol_name = None, size = None, **kwargs):
|
||||
self._objclass = objclass
|
||||
self._size = None
|
||||
if not isinstance(size, int):
|
||||
raise TypeError("ObjectTemplate size must be numeric, not " + str(type(size)))
|
||||
self._size = size
|
||||
self._symbol_name = symbol_name
|
||||
self._kwargs = kwargs
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self._size
|
||||
|
||||
def __call__(self, context, symbol_name, offset, layer_name):
|
||||
@property
|
||||
def symbol_name(self):
|
||||
"""Returns the name of the symbol if one was provided"""
|
||||
return self._symbol_name
|
||||
|
||||
def __call__(self, context, offset, layer_name, parent = None):
|
||||
"""Constructs the object
|
||||
|
||||
Returns: an object adhereing to the Object interface
|
||||
"""
|
||||
return self._objclass(context, layer_name, offset, symbol_name, self.size, **self._kwargs)
|
||||
return self._objclass(context, layer_name, offset, self.symbol_name, self.size, parent, **self._kwargs)
|
||||
|
||||
class MemberTemplate(ObjectTemplate):
|
||||
"""Factory class that produces members of Structs
|
||||
@@ -37,11 +43,13 @@ class MemberTemplate(ObjectTemplate):
|
||||
This is just like a normal ObjectTemplate, but contains the relative offset
|
||||
fron the parent object.
|
||||
"""
|
||||
def __init__(self, objclass, relative_offset, **kwargs):
|
||||
self._objclass = objclass
|
||||
def __init__(self, objclass, symbol_name = None, size = None, relative_offset = None, *args, **kwargs):
|
||||
if not isinstance(relative_offset, int):
|
||||
raise TypeError("MemberTemplate relative_offset must be numeric, not " + str(type(relative_offset)))
|
||||
self._reloffset = relative_offset
|
||||
self._kwargs = kwargs
|
||||
ObjectTemplate.__init__(self, objclass, symbol_name, size, *args, **kwargs)
|
||||
|
||||
@property
|
||||
def relative_offset(self):
|
||||
return self._reloffset
|
||||
|
||||
|
||||
Reference in New Issue
Block a user