Merge pull request #1724 from volatilityfoundation/dgmcdona/windows_timers_raw_dpc_offset

Windows: Fix raw Dpc offset calculation
This commit is contained in:
ikelos
2025-03-20 20:28:18 +00:00
committed by GitHub
4 changed files with 34 additions and 21 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# We use the SemVer 2.0.0 versioning scheme
VERSION_MAJOR = 2 # Number of releases of the library with a breaking change
VERSION_MINOR = 24 # Number of changes that only add to the interface
VERSION_MINOR = 25 # Number of changes that only add to the interface
VERSION_PATCH = 0 # Number of changes that do not change the interface
VERSION_SUFFIX = ""
+25 -3
View File
@@ -402,13 +402,35 @@ class Pointer(Integer):
pointer should be recast. The "pointer" must always live within
the space (even if the data provided is invalid).
"""
mask = context.layers[object_info.native_layer_name].address_mask
new = (
cls._get_raw_value(
context, data_format, object_info.layer_name, object_info.offset
)
& mask
)
return new
@classmethod
def _get_raw_value(
cls,
context: interfaces.context.ContextInterface,
data_format: DataFormatInfo,
layer_name: str,
offset: int,
) -> int:
length, endian, signed = data_format
if signed:
raise ValueError("Pointers cannot have signed values")
mask = context.layers[object_info.native_layer_name].address_mask
data = context.layers.read(object_info.layer_name, object_info.offset, length)
data = context.layers.read(layer_name, offset, length)
value = int.from_bytes(data, byteorder=endian, signed=signed)
return value & mask
return value
def get_raw_value(self) -> int:
raw = self._get_raw_value(
self._context, self.vol.data_format, self.vol.layer_name, self.vol.offset
)
return raw
def dereference(
self, layer_name: Optional[str] = None
@@ -11,6 +11,7 @@ from volatility3.framework import (
interfaces,
constants,
symbols,
exceptions,
)
from volatility3.framework.configuration import requirements
from volatility3.framework.renderers import format_hints
@@ -131,6 +132,7 @@ class Timers(interfaces.plugins.PluginInterface):
):
if not timer.valid_type():
continue
try:
dpc = timer.get_dpc()
if dpc == 0:
@@ -138,7 +140,10 @@ class Timers(interfaces.plugins.PluginInterface):
if dpc.DeferredRoutine == 0:
continue
deferred_routine = dpc.DeferredRoutine
except Exception:
except exceptions.InvalidAddressException as exc:
vollog.debug(
f"Failed to get _KTIMER.Dpc due to {exc.__class__.__name__}"
)
continue
module_symbols = list(
@@ -22,9 +22,8 @@ from volatility3.framework.interfaces.objects import ObjectInterface
from volatility3.framework.layers import intel
from volatility3.framework.objects import utility
from volatility3.framework.renderers import conversion
from volatility3.framework.symbols import generic
from volatility3.framework.symbols import generic, windows
from volatility3.framework.symbols.windows.extensions import pool
from volatility3.framework.symbols import windows
vollog = logging.getLogger(__name__)
@@ -1221,19 +1220,6 @@ class KTIMER(objects.StructType):
return "Yes"
return "-"
def get_raw_dpc(self):
"""Returns the encoded DPC since it may not look like a pointer after encoding"""
symbol_table_name = self.get_symbol_table_name()
pointer_type = self._context.symbol_space.get_type(
symbol_table_name + constants.BANG + "pointer"
)
return self._context.object(
object_type=pointer_type,
layer_name=self.vol.layer_name,
offset=self.Dpc.vol.offset,
)
def valid_type(self):
return self.Header.Type in self.VALID_TYPES
@@ -1268,7 +1254,7 @@ class KTIMER(objects.StructType):
)
low_byte = (wait_never) & 0xFF
entry = utility.rol(self.get_raw_dpc() ^ wait_never, low_byte)
entry = utility.rol(self.Dpc.get_raw_value() ^ wait_never, low_byte)
swap_xor = self._context.layers[self.vol.native_layer_name].canonicalize(
self.vol.offset
)