mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-17 20:35:40 +02:00
Merge branch 'volatilityfoundation:develop' into develop
This commit is contained in:
@@ -25,7 +25,7 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
"""Lists process open handles."""
|
||||
|
||||
_required_framework_version = (2, 0, 0)
|
||||
_version = (1, 0, 1)
|
||||
_version = (1, 0, 2)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -142,6 +142,7 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
pointers in the _HANDLE_TABLE_ENTRY which allows us to find the
|
||||
associated _OBJECT_HEADER.
|
||||
"""
|
||||
DEFAULT_SAR_VALUE = 0x10 # to be used only when decoding fails
|
||||
|
||||
if self._sar_value is None:
|
||||
if not has_capstone:
|
||||
@@ -175,10 +176,11 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
virtual_layer_name, func_addr_to_read, num_bytes_to_read
|
||||
)
|
||||
except exceptions.InvalidAddressException:
|
||||
vollog.debug(
|
||||
f"Failed to read {hex(num_bytes_to_read)} bytes at symbol {hex(func_addr_to_read)}"
|
||||
vollog.warning(
|
||||
f"Failed to read {hex(num_bytes_to_read)} bytes at symbol {hex(func_addr_to_read)}. Unable to decode SAR value. Failing back to a common value of 0x10"
|
||||
)
|
||||
return None
|
||||
self._sar_value = DEFAULT_SAR_VALUE
|
||||
return self._sar_value
|
||||
|
||||
md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64)
|
||||
|
||||
@@ -198,9 +200,10 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
break
|
||||
|
||||
if self._sar_value is None:
|
||||
vollog.debug(
|
||||
f"Failed to to locate SAR value having parsed {instruction_count} instructions"
|
||||
vollog.warning(
|
||||
f"Failed to to locate SAR value having parsed {instruction_count} instructions, failing back to a common value of 0x10"
|
||||
)
|
||||
self._sar_value = DEFAULT_SAR_VALUE
|
||||
|
||||
return self._sar_value
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
##
|
||||
import logging
|
||||
import datetime
|
||||
from typing import Iterable
|
||||
from typing import Callable, Iterable
|
||||
|
||||
from volatility3.framework import renderers, interfaces, exceptions
|
||||
from volatility3.framework.configuration import requirements
|
||||
@@ -19,7 +19,11 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
|
||||
# version 2.6.0 adds support for scanning for 'Ethread' structures by pool tags
|
||||
_required_framework_version = (2, 6, 0)
|
||||
_version = (1, 0, 0)
|
||||
_version = (1, 1, 0)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.implementation = self.scan_threads
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls):
|
||||
@@ -38,8 +42,7 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
def scan_threads(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
symbol_table: str,
|
||||
module_name: str,
|
||||
) -> Iterable[interfaces.objects.ObjectInterface]:
|
||||
"""Scans for threads using the poolscanner module and constraints.
|
||||
|
||||
@@ -52,6 +55,10 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
A list of _ETHREAD objects found by scanning memory for the "Thre" / "Thr\\xE5" pool signatures
|
||||
"""
|
||||
|
||||
module = context.modules[module_name]
|
||||
layer_name = module.layer_name
|
||||
symbol_table = module.symbol_table_name
|
||||
|
||||
constraints = poolscanner.PoolScanner.builtin_constraints(
|
||||
symbol_table, [b"Thr\xe5", b"Thre"]
|
||||
)
|
||||
@@ -76,7 +83,7 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
ethread.get_exit_time()
|
||||
) # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
|
||||
except exceptions.InvalidAddressException:
|
||||
vollog.debug("Thread invalid address {:#x}".format(thread.vol.offset))
|
||||
vollog.debug("Thread invalid address {:#x}".format(ethread.vol.offset))
|
||||
return None
|
||||
|
||||
return (
|
||||
@@ -88,18 +95,19 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
thread_exit_time,
|
||||
)
|
||||
|
||||
def _generator(self):
|
||||
kernel = self.context.modules[self.config["kernel"]]
|
||||
def _generator(self, filter_func: Callable):
|
||||
kernel_name = self.config["kernel"]
|
||||
|
||||
for ethread in self.scan_threads(
|
||||
self.context, kernel.layer_name, kernel.symbol_table_name
|
||||
):
|
||||
for ethread in self.implementation(self.context, kernel_name):
|
||||
info = self.gather_thread_info(ethread)
|
||||
|
||||
if info:
|
||||
yield (0, info)
|
||||
|
||||
def generate_timeline(self):
|
||||
for row in self._generator():
|
||||
filt_func = self.filter_func(self.config)
|
||||
|
||||
for row in self._generator(filt_func):
|
||||
_depth, row_data = row
|
||||
row_dict = {}
|
||||
(
|
||||
@@ -126,7 +134,14 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
row_dict["ExitTime"],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def filter_func(cls, config: interfaces.configuration.HierarchicalDict) -> Callable:
|
||||
"""Returns a function that can filter this plugin's implementation method based on the config"""
|
||||
return lambda x: False
|
||||
|
||||
def run(self):
|
||||
filt_func = self.filter_func(self.config)
|
||||
|
||||
return renderers.TreeGrid(
|
||||
[
|
||||
("Offset", format_hints.Hex),
|
||||
@@ -136,5 +151,5 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
|
||||
("CreateTime", datetime.datetime),
|
||||
("ExitTime", datetime.datetime),
|
||||
],
|
||||
self._generator(),
|
||||
self._generator(filt_func),
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
import logging
|
||||
from typing import List, Generator
|
||||
from typing import Callable, Iterable, List, Generator
|
||||
|
||||
from volatility3.framework import interfaces, constants
|
||||
from volatility3.framework.configuration import requirements
|
||||
@@ -18,6 +18,10 @@ class Threads(thrdscan.ThrdScan):
|
||||
_required_framework_version = (2, 4, 0)
|
||||
_version = (1, 0, 0)
|
||||
|
||||
def __init__(self):
|
||||
self.implementation = self.list_process_threads
|
||||
super().__init__()
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
# Since we're calling the plugin, make sure we have the plugin's requirements
|
||||
@@ -34,7 +38,7 @@ class Threads(thrdscan.ThrdScan):
|
||||
optional=True,
|
||||
),
|
||||
requirements.PluginRequirement(
|
||||
name="thrdscan", plugin=thrdscan.ThrdScan, version=(1, 0, 0)
|
||||
name="thrdscan", plugin=thrdscan.ThrdScan, version=(1, 1, 0)
|
||||
),
|
||||
]
|
||||
|
||||
@@ -60,18 +64,27 @@ class Threads(thrdscan.ThrdScan):
|
||||
seen.add(thread.vol.offset)
|
||||
yield thread
|
||||
|
||||
def _generator(self):
|
||||
kernel = self.context.modules[self.config["kernel"]]
|
||||
@classmethod
|
||||
def filter_func(cls, config: interfaces.configuration.HierarchicalDict) -> Callable:
|
||||
return pslist.PsList.create_pid_filter(config.get("pid", None))
|
||||
|
||||
filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
|
||||
@classmethod
|
||||
def list_process_threads(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
module_name: str,
|
||||
filter_func: Callable,
|
||||
) -> Iterable[interfaces.objects.ObjectInterface]:
|
||||
"""Runs through all processes and lists threads for each process"""
|
||||
module = context.modules[module_name]
|
||||
layer_name = module.layer_name
|
||||
symbol_table_name = module.symbol_table_name
|
||||
|
||||
for proc in pslist.PsList.list_processes(
|
||||
context=self.context,
|
||||
layer_name=kernel.layer_name,
|
||||
symbol_table=kernel.symbol_table_name,
|
||||
context=context,
|
||||
layer_name=layer_name,
|
||||
symbol_table=symbol_table_name,
|
||||
filter_func=filter_func,
|
||||
):
|
||||
for thread in self.list_threads(kernel, proc):
|
||||
info = self.gather_thread_info(thread)
|
||||
if info:
|
||||
yield (0, info)
|
||||
for thread in cls.list_threads(module, proc):
|
||||
yield thread
|
||||
|
||||
Reference in New Issue
Block a user