mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-23 06:42:21 +02:00
Numerous pycharm warnings resolved
This includes: * Better ways of checking empty lists * Not shadowing builtin functions like filter * Preventing invalid slash warnings by marking strings as regexps * Removing unnecessary brackets * Lowercase variable names * Adding/updating parameters in docstrings * Removing unused code (lines not chunks) * Change in not a member tests * Changing some methods to static * Shorting range membership checks * Missing parameters * Make some exception handlers more specific * Don't define a lambda to a variable * A few more instance checks to help type checkers
This commit is contained in:
@@ -122,7 +122,7 @@ class LinuxUtilities(object):
|
||||
# either 1) smeared out of memory or 2) de-allocated and corresponding structures overwritten
|
||||
# we return an empty string in this case to avoid confusion with something like a handle to the root
|
||||
# directory (e.g., "/")
|
||||
if ret_path == []:
|
||||
if not ret_path:
|
||||
return ""
|
||||
|
||||
ret_val = '/'.join([str(p) for p in ret_path if p != ""])
|
||||
@@ -161,10 +161,10 @@ class LinuxUtilities(object):
|
||||
|
||||
sym_addr = dentry.d_op.d_dname
|
||||
|
||||
symbols = list(dentry.context.symbol_space.get_symbols_by_location(sym_addr))
|
||||
symbs = list(dentry.context.symbol_space.get_symbols_by_location(sym_addr))
|
||||
|
||||
if len(symbols) == 1:
|
||||
sym = symbols[0].split(constants.BANG)[1]
|
||||
if len(symbs) == 1:
|
||||
sym = symbs[0].split(constants.BANG)[1]
|
||||
|
||||
if sym == "sockfs_dname":
|
||||
pre_name = "socket"
|
||||
@@ -271,7 +271,7 @@ class LinuxUtilities(object):
|
||||
"""Determines the offset of the actual DTB in physical space and its symbol offset"""
|
||||
init_task_symbol = symbol_table + constants.BANG + 'init_task'
|
||||
init_task_json_address = context.symbol_space.get_symbol(init_task_symbol).address
|
||||
swapper_signature = b"swapper(\/0|\x00\x00)\x00\x00\x00\x00\x00\x00"
|
||||
swapper_signature = rb"swapper(\/0|\x00\x00)\x00\x00\x00\x00\x00\x00"
|
||||
module = context.module(symbol_table, layer_name, 0)
|
||||
|
||||
for offset in context.memory[layer_name].scan(scanner = scanners.RegExScanner(swapper_signature),
|
||||
@@ -281,7 +281,7 @@ class LinuxUtilities(object):
|
||||
init_task = module.object(type_name = 'task_struct', offset = init_task_address)
|
||||
if init_task.pid != 0:
|
||||
continue
|
||||
elif (init_task.has_member('state') and init_task.state.cast('unsigned int') != 0):
|
||||
elif init_task.has_member('state') and init_task.state.cast('unsigned int') != 0:
|
||||
continue
|
||||
|
||||
# This we get for free
|
||||
|
||||
@@ -124,7 +124,7 @@ class MacUtilities(object):
|
||||
|
||||
@classmethod
|
||||
def _scan_generator(cls, context, layer_name, progress_callback):
|
||||
darwin_signature = b"Darwin Kernel Version \d{1,3}\.\d{1,3}\.\d{1,3}: [^\x00]+\x00"
|
||||
darwin_signature = rb"Darwin Kernel Version \d{1,3}\.\d{1,3}\.\d{1,3}: [^\x00]+\x00"
|
||||
|
||||
for offset in context.memory[layer_name].scan(scanner = scanners.RegExScanner(darwin_signature),
|
||||
context = context, progress_callback = progress_callback):
|
||||
|
||||
@@ -59,9 +59,9 @@ class PdbSignatureScanner(interfaces.layers.ScannerInterface):
|
||||
(g3, g2, g1, g0, g5, g4, g7, g6, g8, g9, ga, gb, gc, gd, ge, gf, a) = \
|
||||
self._RSDS_format.unpack(data[sig + 4:name_offset])
|
||||
|
||||
GUID = (16 * '{:02X}').format(g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, ga, gb, gc, gd, ge, gf)
|
||||
guid = (16 * '{:02X}').format(g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, ga, gb, gc, gd, ge, gf)
|
||||
if sig < self.chunk_size:
|
||||
yield (GUID, a, pdb_name, data_offset + sig)
|
||||
yield (guid, a, pdb_name, data_offset + sig)
|
||||
sig = data.find(b"RSDS", sig + 1)
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
|
||||
context: The context in which the `requirement` lives
|
||||
config_path: The path within the `context` for the `requirement`'s configuration variables
|
||||
requirement: The root of the requirement tree to search for :class:~`volatility.framework.interfaces.layers.TranslationLayerRequirement` objects to scan
|
||||
progress_callback: Means of providing the user with feedback during long processes
|
||||
|
||||
Returns:
|
||||
A list of (layer_name, scan_results)
|
||||
@@ -179,15 +180,14 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
|
||||
|
||||
Args:
|
||||
context: Context on which to operate
|
||||
valid_kernels: A list of offsets where valid kernels have been found
|
||||
"""
|
||||
join = interfaces.configuration.path_join
|
||||
for sub_config_path, requirement in self._symbol_requirements:
|
||||
# TODO: Potentially think about multiple symbol requirements in both the same and different levels of the requirement tree
|
||||
# TODO: Consider whether a single found kernel can fulfill multiple requirements
|
||||
suffix = ".json"
|
||||
if valid_kernels:
|
||||
# TODO: Check that the symbols for this kernel will fulfill the requirement
|
||||
kernel = None
|
||||
for virtual_layer in valid_kernels:
|
||||
_kvo, kernel = valid_kernels[virtual_layer]
|
||||
filter_string = os.path.join(kernel['pdb_name'], kernel['GUID'] + "-" + str(kernel['age']))
|
||||
@@ -220,9 +220,10 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
|
||||
|
||||
Args:
|
||||
context: Context on which to operate and provide the kernel virtual offset
|
||||
valid_kernels: List of valid kernels and offsets
|
||||
"""
|
||||
for virtual_layer in valid_kernels:
|
||||
# Sit the virtual offset under the TranslationLayer it applies to
|
||||
# Set the virtual offset under the TranslationLayer it applies to
|
||||
kvo_path = interfaces.configuration.path_join(context.memory[virtual_layer].config_path,
|
||||
'kernel_virtual_offset')
|
||||
kvo, kernel = valid_kernels[virtual_layer]
|
||||
@@ -253,7 +254,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
|
||||
kvo = kernel['mz_offset'] + (1 << (vlayer.bits_per_register - 1))
|
||||
try:
|
||||
kvp = vlayer.mapping(kvo, 0)
|
||||
if (any([(p == kernel['mz_offset'] and l == physical_layer_name) for (_, p, _, l) in
|
||||
if (any([(p == kernel['mz_offset'] and layer_name == physical_layer_name) for (_, p, _, layer_name) in
|
||||
kvp])):
|
||||
valid_kernels[virtual_layer_name] = (kvo, kernel)
|
||||
# Sit the virtual offset under the TranslationLayer it applies to
|
||||
|
||||
@@ -73,8 +73,7 @@ class LayerStacker(interfaces.automagic.AutomagicInterface):
|
||||
Args:
|
||||
context: Context on which to operate
|
||||
config_path: Configuration path under which to store stacking data
|
||||
location: File URL for the underlying physical layer
|
||||
requirements: List of requirements, each of which has the stack built on the first suitable (sub-)requirement
|
||||
requirement: Requirement that should have layers stacked on it
|
||||
progress_callback: Function to provide callback progress
|
||||
"""
|
||||
# If we're cached, find Now we need to find where to apply the stack configuration
|
||||
|
||||
@@ -296,7 +296,7 @@ class WintelStacker(interfaces.automagic.StackerLayerInterface):
|
||||
base_layer = context.memory[layer_name]
|
||||
if isinstance(base_layer, intel.Intel):
|
||||
return None
|
||||
if (base_layer.metadata.get('os', None) not in ['Windows', 'Unknown']):
|
||||
if base_layer.metadata.get('os', None) not in ['Windows', 'Unknown']:
|
||||
return None
|
||||
layer = config_path = None
|
||||
|
||||
|
||||
@@ -220,7 +220,11 @@ class TranslationLayerRequirement(configuration.ConstructableRequirementInterfac
|
||||
|
||||
Args:
|
||||
name: Name of the configuration requirement
|
||||
layer_name: String detailing the expected name of the required layer, this can be None if it is to be randomly generated
|
||||
description: Description of the configuration requirement
|
||||
default: A default value (should not be used for TranslationLayers)
|
||||
optional: Whether the translation layer is required or not
|
||||
oses: A list of valid operating systems which can satisfy this requirement
|
||||
architectures: A list of valid architectures which can satisfy this requirement
|
||||
"""
|
||||
if oses is None:
|
||||
oses = []
|
||||
|
||||
@@ -146,12 +146,11 @@ class Module(interfaces.context.ModuleInterface):
|
||||
**kwargs) -> interfaces.objects.ObjectInterface:
|
||||
"""Returns an object created using the symbol_table_name and layer_name of the Module
|
||||
|
||||
@param symbol_name: Name of the symbol (within the module) to construct, type_name and offset must not be specified
|
||||
@type symbol_name: str
|
||||
@param type_name: Name of the type (within the module) to construct, offset must be specified and symbol_name must not
|
||||
@type type_name: str
|
||||
@param offset: The location (absolute within memory), type_name must be specified and symbol_name must not
|
||||
@type offset: int
|
||||
Args:
|
||||
symbol_name: Name of the symbol (within the module) to construct, type_name and offset must not be specified
|
||||
type_name: Name of the type (within the module) to construct, offset must be specified and symbol_name must not
|
||||
offset: The location (absolute within memory), type_name must be specified and symbol_name must not
|
||||
native_layer_name: Name of the layer in which constructed objects are made (for pointers)
|
||||
"""
|
||||
type_arg = None # type: Optional[Union[str, interfaces.objects.Template]]
|
||||
if symbol_name is not None:
|
||||
|
||||
@@ -67,7 +67,7 @@ class ResourceAccessor(object):
|
||||
temp_filename = os.path.join(constants.CACHE_PATH,
|
||||
"data_" + hashlib.sha512(bytes(url, 'latin-1')).hexdigest())
|
||||
|
||||
if not temp_filename in self._cached_files or not os.path.exists(temp_filename):
|
||||
if temp_filename not in self._cached_files or not os.path.exists(temp_filename):
|
||||
vollog.info("Caching file at: {}".format(temp_filename))
|
||||
|
||||
try:
|
||||
@@ -154,7 +154,8 @@ class JarHandler(urllib.request.BaseHandler):
|
||||
http://developer.java.sun.com/developer/onlineTraining/protocolhandlers/
|
||||
"""
|
||||
|
||||
def default_open(self, req):
|
||||
@staticmethod
|
||||
def default_open(req):
|
||||
"""Handles the request if it's the jar scheme"""
|
||||
if req.type == 'jar':
|
||||
subscheme, remainder = req.full_url.split(":")[1], ":".join(req.full_url.split(":")[2:])
|
||||
|
||||
@@ -207,7 +207,6 @@ class Intel(interfaces.layers.TranslationLayerInterface):
|
||||
@property
|
||||
def dependencies(self) -> List[str]:
|
||||
"""Returns a list of the lower layer names that this layer is dependent upon"""
|
||||
# TODO: Add in the whole buffalo
|
||||
return [self._base_layer] + self._swap_layers
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -37,7 +37,7 @@ class BufferDataLayer(interfaces.layers.DataLayerInterface):
|
||||
"""Reads the data from the buffer"""
|
||||
if not self.is_valid(address, length):
|
||||
invalid_address = address
|
||||
if self.minimum_address < address and address <= self.maximum_address:
|
||||
if self.minimum_address < address <= self.maximum_address:
|
||||
invalid_address = self.maximum_address + 1
|
||||
raise exceptions.InvalidAddressException(self.name, invalid_address,
|
||||
"Offset outside of the buffer boundaries")
|
||||
@@ -115,7 +115,7 @@ class FileLayer(interfaces.layers.DataLayerInterface):
|
||||
"""Reads from the file at offset for length"""
|
||||
if not self.is_valid(offset, length):
|
||||
invalid_address = offset
|
||||
if self.minimum_address < offset and offset <= self.maximum_address:
|
||||
if self.minimum_address < offset <= self.maximum_address:
|
||||
invalid_address = self.maximum_address + 1
|
||||
raise exceptions.InvalidAddressException(self.name, invalid_address,
|
||||
"Offset outside of the buffer boundaries")
|
||||
@@ -137,7 +137,7 @@ class FileLayer(interfaces.layers.DataLayerInterface):
|
||||
"""
|
||||
if not self.is_valid(offset, len(data)):
|
||||
invalid_address = offset
|
||||
if self.minimum_address < offset and offset <= self.maximum_address:
|
||||
if self.minimum_address < offset <= self.maximum_address:
|
||||
invalid_address = self.maximum_address + 1
|
||||
raise exceptions.InvalidAddressException(self.name, invalid_address,
|
||||
"Data segment outside of the " + self.name + " file boundaries")
|
||||
|
||||
@@ -168,7 +168,7 @@ class RegistryHive(interfaces.layers.TranslationLayerInterface):
|
||||
"""Translates a single cell index to a cell memory offset and the suboffset within it"""
|
||||
|
||||
# Ignore the volatile bit when determining maxaddr validity
|
||||
if (offset & 0x7fffffff > self._maxaddr):
|
||||
if offset & 0x7fffffff > self._maxaddr:
|
||||
raise RegistryInvalidIndex("Mapping request for value greater than maxaddr")
|
||||
|
||||
volatile = self._mask(offset, 31, 31) >> 31
|
||||
@@ -187,7 +187,7 @@ class RegistryHive(interfaces.layers.TranslationLayerInterface):
|
||||
ignore_errors: bool = False) -> Iterable[Tuple[int, int, int, str]]:
|
||||
|
||||
# TODO: Check the offset and offset + length are not outside the norms
|
||||
if (length < 0):
|
||||
if length < 0:
|
||||
raise ValueError("Mapping length of RegistryHive must be positive or zero")
|
||||
|
||||
response = []
|
||||
|
||||
@@ -27,8 +27,7 @@ def convert_data_to_value(data: bytes,
|
||||
float_vals = "zzezfzzzd"
|
||||
if data_format.length > len(float_vals) or float_vals[data_format.length] not in "efd":
|
||||
raise TypeError("Invalid float size")
|
||||
struct_format = ("<" if data_format.byteorder == 'little' else ">") + \
|
||||
float_vals[data_format.length]
|
||||
struct_format = ("<" if data_format.byteorder == 'little' else ">") + float_vals[data_format.length]
|
||||
elif struct_type in [bytes, str]:
|
||||
struct_format = str(data_format.length) + "s"
|
||||
else:
|
||||
@@ -55,8 +54,7 @@ def convert_value_to_data(value: Union[int, float, bytes, str, bool],
|
||||
float_vals = "zzezfzzzd"
|
||||
if data_format.length > len(float_vals) or float_vals[data_format.length] not in "efd":
|
||||
raise TypeError("Invalid float size")
|
||||
struct_format = ("<" if data_format.byteorder == 'little' else ">") + \
|
||||
float_vals[data_format.length]
|
||||
struct_format = ("<" if data_format.byteorder == 'little' else ">") + float_vals[data_format.length]
|
||||
elif struct_type in [bytes, str]:
|
||||
struct_format = str(data_format.length) + "s"
|
||||
else:
|
||||
|
||||
@@ -25,9 +25,9 @@ def run_plugin(context: interfaces.context.ContextInterface,
|
||||
context: The volatility context to operate on
|
||||
automagics: A list of automagic modules to run to augment the context
|
||||
plugin: The plugin to run
|
||||
plugin_config_path: The path within the context's config containing the plugin's configuration
|
||||
write_config: Whether to record the configuration options after processing the automagic but before running
|
||||
quiet: Whether or not to output progress information
|
||||
base_config_path: The path within the context's config containing the plugin's configuration
|
||||
progress_callback: Callback function to provide feedback for ongoing processes
|
||||
file_consumer: Object to pass any generated files to
|
||||
|
||||
Returns:
|
||||
The constructed plugin object
|
||||
|
||||
@@ -249,7 +249,7 @@ class TreeGrid(interfaces.renderers.TreeGrid):
|
||||
newpath = parent_path + str(position)
|
||||
tree_item = TreeNode(newpath, self, parent, values)
|
||||
for node, _ in children[position:]:
|
||||
self.visit(node, lambda child, _: child.path_changed(newpath, True))
|
||||
self.visit(node, lambda child, _: child.path_changed(newpath, True), None)
|
||||
children.insert(position, (tree_item, []))
|
||||
return tree_item
|
||||
|
||||
@@ -259,7 +259,7 @@ class TreeGrid(interfaces.renderers.TreeGrid):
|
||||
|
||||
def max_depth(self):
|
||||
"""Returns the maximum depth of the tree"""
|
||||
return self.visit(None, lambda n, a: max(a, self.path_depth(n)), )
|
||||
return self.visit(None, lambda n, a: max(a, self.path_depth(n)), 0)
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
@@ -253,11 +253,11 @@ class ISFormatTable(interfaces.symbols.SymbolTableInterface, metaclass = ABCMeta
|
||||
# TODO: Check the format and make use of the other metadata
|
||||
|
||||
def _validate_json(self) -> None:
|
||||
if (not 'user_types' in self._json_object or
|
||||
not 'base_types' in self._json_object or
|
||||
not 'metadata' in self._json_object or
|
||||
not 'symbols' in self._json_object or
|
||||
not 'enums' in self._json_object):
|
||||
if ('user_types' not in self._json_object or
|
||||
'base_types' not in self._json_object or
|
||||
'metadata' not in self._json_object or
|
||||
'symbols' not in self._json_object or
|
||||
'enums' not in self._json_object):
|
||||
raise exceptions.SymbolSpaceError("Malformed JSON file provided")
|
||||
|
||||
def metadata(self) -> Optional[interfaces.symbols.MetadataInterface]:
|
||||
@@ -334,7 +334,8 @@ class Version1Format(ISFormatTable):
|
||||
elif type_name == 'enum':
|
||||
update = self._lookup_enum(dictionary['name'])
|
||||
elif type_name == 'bitfield':
|
||||
update = {'start_bit': dictionary['bit_position'], 'end_bit': dictionary['bit_length']}
|
||||
update = {'start_bit': dictionary['bit_position'],
|
||||
'end_bit': dictionary['bit_length']}
|
||||
update['base_type'] = self._interdict_to_template(dictionary['type'])
|
||||
# We do *not* call native_template.clone(), since it slows everything down a lot
|
||||
# We require that the native.get_type method always returns a newly constructed python object
|
||||
|
||||
@@ -50,7 +50,7 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
continue
|
||||
|
||||
proc_layer_name = task.add_process_layer()
|
||||
if proc_layer_name == None:
|
||||
if not proc_layer_name:
|
||||
continue
|
||||
|
||||
proc_layer = self.context.memory[proc_layer_name]
|
||||
@@ -79,7 +79,7 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
yield (0, (task.pid, task_name, hist.get_time_object(), hist.get_command()))
|
||||
|
||||
def run(self):
|
||||
filter = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
filt = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
|
||||
plugin = pslist.PsList.list_tasks
|
||||
|
||||
@@ -91,17 +91,17 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
self._generator(plugin(self.context,
|
||||
self.config['primary'],
|
||||
self.config['vmlinux'],
|
||||
filter = filter)))
|
||||
filter = filt)))
|
||||
|
||||
def generate_timeline(self):
|
||||
filter = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
filt = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
|
||||
plugin = pslist.PsList.list_tasks
|
||||
|
||||
for row in self._generator(plugin(self.context,
|
||||
self.config['primary'],
|
||||
self.config['vmlinux'],
|
||||
filter = filter)):
|
||||
filter = filt)):
|
||||
_depth, row_data = row
|
||||
description = "{} ({}): \"{}\"".format(row_data[0], row_data[1], row_data[3])
|
||||
yield (description, timeliner.TimeLinerType.CREATED, row_data[2])
|
||||
|
||||
@@ -26,7 +26,7 @@ class Elfs(plugins.PluginInterface):
|
||||
def _generator(self, tasks):
|
||||
for task in tasks:
|
||||
proc_layer_name = task.add_process_layer()
|
||||
if proc_layer_name == None:
|
||||
if not proc_layer_name:
|
||||
continue
|
||||
|
||||
proc_layer = self.context.memory[proc_layer_name]
|
||||
@@ -50,7 +50,7 @@ class Elfs(plugins.PluginInterface):
|
||||
))
|
||||
|
||||
def run(self):
|
||||
filter = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
filt = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
|
||||
plugin = pslist.PsList.list_tasks
|
||||
|
||||
@@ -63,4 +63,4 @@ class Elfs(plugins.PluginInterface):
|
||||
self._generator(plugin(self.context,
|
||||
self.config['primary'],
|
||||
self.config['vmlinux'],
|
||||
filter = filter)))
|
||||
filter = filt)))
|
||||
|
||||
@@ -27,7 +27,7 @@ class Malfind(interfaces_plugins.PluginInterface):
|
||||
"""
|
||||
|
||||
proc_layer_name = task.add_process_layer()
|
||||
if proc_layer_name == None:
|
||||
if not proc_layer_name:
|
||||
return
|
||||
|
||||
proc_layer = self.context.memory[proc_layer_name]
|
||||
@@ -64,7 +64,7 @@ class Malfind(interfaces_plugins.PluginInterface):
|
||||
disasm))
|
||||
|
||||
def run(self):
|
||||
filter = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
filt = pslist.PsList.create_filter([self.config.get('pid', None)])
|
||||
|
||||
plugin = pslist.PsList.list_tasks
|
||||
|
||||
@@ -78,4 +78,4 @@ class Malfind(interfaces_plugins.PluginInterface):
|
||||
self._generator(plugin(self.context,
|
||||
self.config['primary'],
|
||||
self.config['vmlinux'],
|
||||
filter = filter)))
|
||||
filter = filt)))
|
||||
|
||||
@@ -20,13 +20,16 @@ class PsList(interfaces_plugins.PluginInterface):
|
||||
|
||||
@classmethod
|
||||
def create_filter(cls, pid_list: List[int] = None) -> Callable[[int], bool]:
|
||||
filter = lambda _: False
|
||||
# FIXME: mypy #4973 or #2608
|
||||
pid_list = pid_list or []
|
||||
filter_list = [x for x in pid_list if x is not None]
|
||||
if filter_list:
|
||||
filter = lambda x: x not in filter_list
|
||||
return filter
|
||||
def filter_func(x):
|
||||
return x not in filter_list
|
||||
|
||||
return filter_func
|
||||
else:
|
||||
return lambda _: False
|
||||
|
||||
def _generator(self):
|
||||
for task in self.list_tasks(self.context,
|
||||
@@ -54,7 +57,8 @@ class PsList(interfaces_plugins.PluginInterface):
|
||||
init_task = vmlinux.object(symbol_name = "init_task")
|
||||
|
||||
for task in init_task.tasks:
|
||||
yield task
|
||||
if not filter(task):
|
||||
yield task
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("PID", int),
|
||||
|
||||
@@ -9,6 +9,7 @@ from volatility.framework.objects import utility
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PsList(interfaces_plugins.PluginInterface):
|
||||
"""Lists the processes present in a particular mac memory image"""
|
||||
|
||||
@@ -35,7 +36,7 @@ class PsList(interfaces_plugins.PluginInterface):
|
||||
self.config['primary'],
|
||||
self.config['darwin'],
|
||||
filter = self.create_filter([self.config.get('pid', None)])):
|
||||
pid = task.p_pid
|
||||
pid = task.p_pid
|
||||
ppid = task.p_ppid
|
||||
name = utility.array_to_string(task.p_comm)
|
||||
yield (0, (pid, ppid, name))
|
||||
@@ -51,7 +52,7 @@ class PsList(interfaces_plugins.PluginInterface):
|
||||
"""Lists all the tasks in the primary layer"""
|
||||
|
||||
aslr_shift = mac.MacUtilities.find_aslr(context, mac_symbols, layer_name)
|
||||
darwin = context.module(mac_symbols, layer_name, aslr_shift)
|
||||
darwin = context.module(mac_symbols, layer_name, aslr_shift)
|
||||
proc = darwin.object(symbol_name = "allproc").lh_first
|
||||
|
||||
seen = {}
|
||||
@@ -61,7 +62,7 @@ class PsList(interfaces_plugins.PluginInterface):
|
||||
break
|
||||
else:
|
||||
seen[proc.vol.offset] = 1
|
||||
|
||||
|
||||
yield proc
|
||||
|
||||
proc = proc.p_list.le_next.dereference()
|
||||
|
||||
@@ -47,9 +47,15 @@ class Timeliner(interfaces.plugins.PluginInterface):
|
||||
plugin_list = list(framework.class_subclasses(TimeLinerInterface))
|
||||
|
||||
# Get the filter from the configuration
|
||||
filter_func = lambda _n, _s: True
|
||||
def passthrough(_n, _s):
|
||||
return True
|
||||
|
||||
filter_func = passthrough
|
||||
if selected_list:
|
||||
filter_func = lambda name, selected: any([s in name for s in selected])
|
||||
def filter_plugins(name, selected):
|
||||
return any([s in name for s in selected])
|
||||
|
||||
filter_func = filter_plugins
|
||||
|
||||
return [plugin_class for plugin_class in plugin_list if filter_func(plugin_class.__name__, selected_list)]
|
||||
|
||||
@@ -99,7 +105,6 @@ class Timeliner(interfaces.plugins.PluginInterface):
|
||||
# Use all the plugins if there's no filter
|
||||
self.usable_plugins = self.usable_plugins or self.get_usable_plugins()
|
||||
self.automagics = self.automagics or automagic.available(self._context)
|
||||
sep = configuration.CONFIG_SEPARATOR
|
||||
runable_plugins = []
|
||||
|
||||
# Identify plugins that we can run which output datetimes
|
||||
@@ -114,7 +119,8 @@ class Timeliner(interfaces.plugins.PluginInterface):
|
||||
self._progress_callback,
|
||||
self._file_consumer)
|
||||
|
||||
runable_plugins.append(plugin)
|
||||
if isinstance(plugin, TimeLinerInterface):
|
||||
runable_plugins.append(plugin)
|
||||
except exceptions.UnsatisfiedException as excp:
|
||||
# Remove the failed plugin from the list and continue
|
||||
vollog.debug("Unable to satisfy {}: {}".format(plugin_class.__name__, excp.unsatisfied))
|
||||
|
||||
@@ -204,7 +204,7 @@ class Handles(interfaces_plugins.PluginInterface):
|
||||
subtype = subtype, count = int(count))
|
||||
|
||||
layer_object = self.context.memory[virtual]
|
||||
masked_offset = layer_object._mask(offset, 0, layer_object._maxvirtaddr)
|
||||
masked_offset = (offset & layer_object.maximum_address)
|
||||
|
||||
for entry in table:
|
||||
|
||||
@@ -251,8 +251,8 @@ class Handles(interfaces_plugins.PluginInterface):
|
||||
layer_name = self.config["primary"],
|
||||
symbol_table = self.config["nt_symbols"])
|
||||
cookie = self.find_cookie(context = self.context,
|
||||
layer_name = self.config["primary"],
|
||||
symbol_table = self.config["nt_symbols"])
|
||||
layer_name = self.config["primary"],
|
||||
symbol_table = self.config["nt_symbols"])
|
||||
|
||||
for proc in procs:
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ class Info(plugins.PluginInterface):
|
||||
|
||||
virtual_layer_name = self.config["primary"]
|
||||
virtual_layer = self.context.memory[virtual_layer_name]
|
||||
if not isinstance(virtual_layer, layers.intel.Intel):
|
||||
raise TypeError("Virtual Layer is not an intel layer")
|
||||
|
||||
native_types = self.context.symbol_space[self.config["nt_symbols"]].natives
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import enum
|
||||
import logging
|
||||
from typing import Optional, Tuple, List, Generator
|
||||
|
||||
import volatility.plugins.windows.handles as handles
|
||||
from volatility.framework import constants, interfaces, renderers, validity, exceptions, symbols
|
||||
from volatility.framework.configuration import requirements
|
||||
from volatility.framework.interfaces import plugins, configuration
|
||||
@@ -9,7 +10,6 @@ from volatility.framework.layers import scanners
|
||||
from volatility.framework.renderers import format_hints
|
||||
from volatility.framework.symbols import intermed
|
||||
from volatility.framework.symbols.windows import extensions
|
||||
import volatility.plugins.windows.handles as handles
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import datetime
|
||||
from typing import Callable, Iterable, List
|
||||
|
||||
import volatility.framework.interfaces.plugins as plugins
|
||||
from volatility.framework import renderers, interfaces
|
||||
from volatility.framework import renderers, interfaces, layers
|
||||
from volatility.framework.configuration import requirements
|
||||
from volatility.framework.renderers import format_hints
|
||||
from volatility.plugins import timeliner
|
||||
@@ -84,6 +84,8 @@ class PsList(plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
else:
|
||||
layer_name = self.config['primary']
|
||||
memory = self.context.memory[layer_name]
|
||||
if not isinstance(memory, layers.intel.Intel):
|
||||
raise TypeError("Primary layer is not an intel layer")
|
||||
(_, offset, _, _) = list(memory.mapping(offset = proc.vol.offset, length = 0))[0]
|
||||
|
||||
yield (0, (proc.UniqueProcessId,
|
||||
|
||||
@@ -6,7 +6,7 @@ import volatility.framework.interfaces.plugins as plugins
|
||||
from volatility.framework import objects, renderers, exceptions
|
||||
from volatility.framework.configuration import requirements
|
||||
from volatility.framework.layers.registry import RegistryHive
|
||||
from volatility.framework.renderers import TreeGrid, conversion
|
||||
from volatility.framework.renderers import TreeGrid, conversion, format_hints
|
||||
from volatility.framework.symbols.windows.extensions.registry import RegValueTypes
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
@@ -97,8 +97,8 @@ class PrintKey(plugins.PluginInterface):
|
||||
reg_config_path = self.make_subconfig(hive_offset = hive_offset,
|
||||
base_layer = self.config['primary'],
|
||||
nt_symbols = self.config['nt_symbols'])
|
||||
hive = RegistryHive(self.context, reg_config_path, name = 'hive' + hex(hive_offset))
|
||||
try:
|
||||
hive = RegistryHive(self.context, reg_config_path, name = 'hive' + hex(hive_offset))
|
||||
self.context.memory.add_layer(hive)
|
||||
|
||||
# Walk it
|
||||
@@ -116,7 +116,7 @@ class PrintKey(plugins.PluginInterface):
|
||||
vollog.debug("Invalid address identified in Hive: {}".format(hex(excp.invalid_address)))
|
||||
result = (0,
|
||||
(renderers.UnreadableValue(),
|
||||
renderers.format_hints.Hex(hive.hive_offset),
|
||||
format_hints.Hex(hive.hive_offset),
|
||||
"Key",
|
||||
self.config.get('key', "ROOT"),
|
||||
renderers.UnreadableValue(),
|
||||
@@ -127,7 +127,7 @@ class PrintKey(plugins.PluginInterface):
|
||||
def run(self):
|
||||
|
||||
return TreeGrid(columns = [('Last Write Time', datetime.datetime),
|
||||
('Hive Offset', renderers.format_hints.Hex),
|
||||
('Hive Offset', format_hints.Hex),
|
||||
('Type', str),
|
||||
('Key', str),
|
||||
('Name', str),
|
||||
|
||||
@@ -69,10 +69,18 @@ class SSDT(plugins.PluginInterface):
|
||||
is_kernel_64 = symbols.symbol_table_is_64bit(self.context, self.config["nt_symbols"])
|
||||
if is_kernel_64:
|
||||
array_subtype = "long"
|
||||
find_address = lambda func: kvo + service_table_address + (func >> 4)
|
||||
|
||||
def kvo_calulator(func):
|
||||
return kvo + service_table_address + (func >> 4)
|
||||
|
||||
find_address = kvo_calulator
|
||||
else:
|
||||
array_subtype = "unsigned long"
|
||||
find_address = lambda func: func
|
||||
|
||||
def passthrough(func):
|
||||
return func
|
||||
|
||||
find_address = passthrough
|
||||
|
||||
functions = ntkrnlmp.object(type_name = "array", offset = kvo + service_table_address,
|
||||
subtype = ntkrnlmp.get_type(array_subtype),
|
||||
|
||||
@@ -62,7 +62,7 @@ class VadDump(interfaces_plugins.PluginInterface):
|
||||
|
||||
self.produce_file(filedata)
|
||||
result_text = "Stored {}".format(filedata.preferred_filename)
|
||||
except Exception:
|
||||
except exceptions.InvalidAddressException:
|
||||
result_text = "Unable to dump {0:#x} - {1:#x}".format(vad.get_start(), vad.get_end())
|
||||
|
||||
yield (0, (proc.UniqueProcessId,
|
||||
|
||||
@@ -76,9 +76,15 @@ class VadInfo(interfaces_plugins.PluginInterface):
|
||||
|
||||
def _generator(self, procs):
|
||||
|
||||
filter_func = lambda _: False
|
||||
def passthrough(_):
|
||||
return False
|
||||
|
||||
filter_func = passthrough
|
||||
if self.config.get('address', None) is not None:
|
||||
filter_func = lambda x: x.get_start() not in [self.config['address']]
|
||||
def filter_function(x):
|
||||
return x.get_start() not in [self.config['address']]
|
||||
|
||||
filter_func = filter_function
|
||||
|
||||
for proc in procs:
|
||||
process_name = utility.array_to_string(proc.ImageFileName)
|
||||
|
||||
@@ -41,6 +41,7 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
"""Get File and Product version information from PE files
|
||||
|
||||
Args:
|
||||
context: volatility context on which to operate
|
||||
pe_table_name: name of the PE table
|
||||
layer_name: name of the layer containing the PE file
|
||||
base_address: base address of the PE (where MZ is found)
|
||||
@@ -69,7 +70,7 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
|
||||
pe_data.close()
|
||||
|
||||
return (major, minor, product, build)
|
||||
return major, minor, product, build
|
||||
|
||||
def _generator(self,
|
||||
procs: Generator[interfaces.objects.ObjectInterface, None, None],
|
||||
@@ -80,7 +81,7 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
Args:
|
||||
procs: <generator> of processes
|
||||
mods: <generator> of modules
|
||||
moddump_plugin: <moddump.ModDump>
|
||||
session_layers: <generator> of layers in the session to be checked
|
||||
"""
|
||||
|
||||
pe_table_name = PEIntermedSymbols.create(self.context,
|
||||
|
||||
Reference in New Issue
Block a user