Merge branch 'volatilityfoundation:develop' into develop

This commit is contained in:
Arcuri Davide
2024-07-22 13:56:34 +02:00
committed by GitHub
31 changed files with 6670 additions and 158 deletions
+21
View File
@@ -7,6 +7,27 @@ from typing import Optional, Union
from volatility3.framework import interfaces, objects, constants
def rol(value: int, count: int, max_bits: int = 64) -> int:
"""A rotate-left instruction in Python"""
max_bits_mask = (1 << max_bits) - 1
return (value << count % max_bits) & max_bits_mask | (
(value & max_bits_mask) >> (max_bits - (count % max_bits))
)
def bswap_32(value: int) -> int:
value = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0x00FF00FF)
return ((value << 16) | (value >> 16)) & 0xFFFFFFFF
def bswap_64(value: int) -> int:
low = bswap_32((value >> 32))
high = bswap_32((value & 0xFFFFFFFF))
return ((high << 32) | low) & 0xFFFFFFFFFFFFFFFF
def array_to_string(
array: "objects.Array", count: Optional[int] = None, errors: str = "replace"
) -> interfaces.objects.ObjectInterface:
@@ -1,10 +1,9 @@
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import contextlib
import datetime
import logging
import ntpath
import re
from typing import List, Optional, Type
@@ -14,7 +13,7 @@ from volatility3.framework.renderers import conversion, format_hints
from volatility3.framework.symbols import intermed
from volatility3.framework.symbols.windows.extensions import pe
from volatility3.plugins import timeliner
from volatility3.plugins.windows import info, pslist, psscan
from volatility3.plugins.windows import info, pslist, psscan, pedump
vollog = logging.getLogger(__name__)
@@ -23,7 +22,7 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
"""Lists the loaded modules in a particular windows memory image."""
_required_framework_version = (2, 0, 0)
_version = (2, 0, 1)
_version = (3, 0, 0)
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -76,67 +75,11 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
default=False,
optional=True,
),
requirements.VersionRequirement(
name="pedump", component=pedump.PEDump, version=(1, 0, 0)
),
]
@classmethod
def dump_pe(
cls,
context: interfaces.context.ContextInterface,
pe_table_name: str,
dll_entry: interfaces.objects.ObjectInterface,
open_method: Type[interfaces.plugins.FileHandlerInterface],
layer_name: str = None,
prefix: str = "",
) -> Optional[interfaces.plugins.FileHandlerInterface]:
"""Extracts the complete data for a process as a FileInterface
Args:
context: the context to operate upon
pe_table_name: the name for the symbol table containing the PE format symbols
dll_entry: the object representing the module
layer_name: the layer that the DLL lives within
open_method: class for constructing output files
Returns:
An open FileHandlerInterface object containing the complete data for the DLL or None in the case of failure
"""
try:
try:
name = dll_entry.FullDllName.get_string()
except exceptions.InvalidAddressException:
name = "UnreadableDLLName"
if layer_name is None:
layer_name = dll_entry.vol.layer_name
file_handle = open_method(
"{}{}.{:#x}.{:#x}.dmp".format(
prefix,
ntpath.basename(name),
dll_entry.vol.offset,
dll_entry.DllBase,
)
)
dos_header = context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset=dll_entry.DllBase,
layer_name=layer_name,
)
for offset, data in dos_header.reconstruct():
file_handle.seek(offset)
file_handle.write(data)
except (
IOError,
exceptions.VolatilityException,
OverflowError,
ValueError,
) as excp:
vollog.debug(f"Unable to dump dll at offset {dll_entry.DllBase}: {excp}")
return None
return file_handle
def _generator(self, procs):
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types=pe.class_types
@@ -204,7 +147,7 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
file_output = "Disabled"
if self.config["dump"]:
file_handle = self.dump_pe(
file_output = pedump.PEDump.dump_ldr_entry(
self.context,
pe_table_name,
entry,
@@ -212,10 +155,10 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
proc_layer_name,
prefix=f"pid.{proc_id}.",
)
file_output = "Error outputting file"
if file_handle:
file_handle.close()
file_output = file_handle.preferred_filename
if not file_output:
file_output = "Error outputting file"
try:
dllbase = format_hints.Hex(entry.DllBase)
except exceptions.InvalidAddressException:
@@ -0,0 +1,106 @@
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
from typing import Iterator, List, Tuple
from volatility3.framework import (
renderers,
interfaces,
constants,
)
from volatility3.framework.configuration import requirements
from volatility3.framework.objects import utility
from volatility3.framework.renderers import format_hints
vollog = logging.getLogger(__name__)
class KPCRs(interfaces.plugins.PluginInterface):
"""Print KPCR structure for each processor"""
_required_framework_version = (2, 0, 0)
_version = (1, 0, 0)
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
]
@classmethod
def list_kpcrs(
cls,
context: interfaces.context.ContextInterface,
kernel_module_name: str,
layer_name: str,
symbol_table: str,
) -> interfaces.objects.ObjectInterface:
"""Returns the KPCR structure for each processor
Args:
context: The context to retrieve required elements (layers, symbol tables) from
kernel_module_name: The name of the kernel module on which to operate
layer_name: The name of the layer on which to operate
symbol_table: The name of the table containing the kernel symbols
Returns:
The _KPCR structure for each processor
"""
kernel = context.modules[kernel_module_name]
cpu_count_offset = kernel.get_symbol("KeNumberProcessors").address
cpu_count = kernel.object(
object_type="unsigned int", layer_name=layer_name, offset=cpu_count_offset
)
processor_block = kernel.object(
object_type="pointer",
layer_name=layer_name,
offset=kernel.get_symbol("KiProcessorBlock").address,
)
processor_pointers = utility.array_of_pointers(
context=context,
array=processor_block,
count=cpu_count,
subtype=symbol_table + constants.BANG + "_KPRCB",
)
for pointer in processor_pointers:
kprcb = pointer.dereference()
reloff = kernel.get_type("_KPCR").relative_child_offset("Prcb")
kpcr = context.object(
symbol_table + constants.BANG + "_KPCR",
offset=kprcb.vol.offset - reloff,
layer_name=layer_name,
)
yield kpcr
def _generator(self) -> Iterator[Tuple]:
kernel = self.context.modules[self.config["kernel"]]
layer_name = kernel.layer_name
symbol_table = kernel.symbol_table_name
for kpcr in self.list_kpcrs(
self.context, self.config["kernel"], layer_name, symbol_table
):
yield (
0,
(
format_hints.Hex(kpcr.vol.offset),
format_hints.Hex(kpcr.CurrentPrcb),
),
)
def run(self):
return renderers.TreeGrid(
[
("Offset", format_hints.Hex),
("PRCB Offset", format_hints.Hex),
],
self._generator(),
)
@@ -6,7 +6,7 @@ from typing import Iterable
from volatility3.framework import interfaces
from volatility3.framework.configuration import requirements
from volatility3.plugins.windows import poolscanner, dlllist, pslist, modules
from volatility3.plugins.windows import poolscanner, modules, pedump
vollog = logging.getLogger(__name__)
@@ -35,12 +35,6 @@ class ModScan(modules.Modules):
requirements.VersionRequirement(
name="modules", component=modules.Modules, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="pslist", component=pslist.PsList, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="dlllist", component=dlllist.DllList, version=(2, 0, 0)
),
requirements.BooleanRequirement(
name="dump",
description="Extract listed modules",
@@ -58,6 +52,9 @@ class ModScan(modules.Modules):
optional=True,
default=None,
),
requirements.VersionRequirement(
name="pedump", component=pedump.PEDump, version=(1, 0, 0)
),
]
@classmethod
@@ -9,7 +9,7 @@ from volatility3.framework.configuration import requirements
from volatility3.framework.renderers import format_hints
from volatility3.framework.symbols import intermed
from volatility3.framework.symbols.windows.extensions import pe
from volatility3.plugins.windows import pslist, dlllist
from volatility3.plugins.windows import pslist, pedump
vollog = logging.getLogger(__name__)
@@ -35,9 +35,6 @@ class Modules(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="pslist", component=pslist.PsList, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="dlllist", component=dlllist.DllList, version=(2, 0, 0)
),
requirements.BooleanRequirement(
name="dump",
description="Extract listed modules",
@@ -55,6 +52,9 @@ class Modules(interfaces.plugins.PluginInterface):
optional=True,
default=None,
),
requirements.VersionRequirement(
name="pedump", component=pedump.PEDump, version=(1, 0, 0)
),
]
def dump_module(self, session_layers, pe_table_name, mod):
@@ -63,16 +63,15 @@ class Modules(interfaces.plugins.PluginInterface):
)
file_output = f"Cannot find a viable session layer for {mod.DllBase:#x}"
if session_layer_name:
file_handle = dlllist.DllList.dump_pe(
file_output = pedump.PEDump.dump_ldr_entry(
self.context,
pe_table_name,
mod,
self.open,
layer_name=session_layer_name,
)
file_output = "Error outputting file"
if file_handle:
file_output = file_handle.preferred_filename
if not file_output:
file_output = "Error outputting file"
return file_output
@@ -0,0 +1,270 @@
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
import ntpath
from typing import List, Type, Optional
from volatility3.framework import constants, exceptions, interfaces, renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.symbols import intermed
from volatility3.framework.symbols.windows.extensions import pe
from volatility3.plugins.windows import pslist, modules
vollog = logging.getLogger(__name__)
class PEDump(interfaces.plugins.PluginInterface):
"""Allows extracting PE Files from a specific address in a specific address space"""
_required_framework_version = (2, 0, 0)
_version = (1, 0, 0)
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.VersionRequirement(
name="pslist", component=pslist.PsList, version=(2, 0, 0)
),
requirements.ListRequirement(
name="pid",
element_type=int,
description="Process IDs to include (all other processes are excluded)",
optional=True,
),
requirements.IntRequirement(
name="base",
description="Base address to reconstruct a PE file",
optional=False,
),
requirements.BooleanRequirement(
name="kernel_module",
description="Extract from kernel address space.",
default=False,
optional=True,
),
]
@classmethod
def dump_pe(
cls,
context: interfaces.context.ContextInterface,
pe_table_name: str,
layer_name: str,
open_method: Type[interfaces.plugins.FileHandlerInterface],
file_name: str,
base: int,
) -> Optional[str]:
"""
Returns the filename of the dump file or None
"""
try:
file_handle = open_method(file_name)
dos_header = context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset=base,
layer_name=layer_name,
)
for offset, data in dos_header.reconstruct():
file_handle.seek(offset)
file_handle.write(data)
except (
IOError,
exceptions.VolatilityException,
OverflowError,
ValueError,
) as excp:
vollog.debug(f"Unable to dump PE file at offset {base}: {excp}")
return None
finally:
file_handle.close()
return file_handle.preferred_filename
@classmethod
def dump_ldr_entry(
cls,
context: interfaces.context.ContextInterface,
pe_table_name: str,
ldr_entry: interfaces.objects.ObjectInterface,
open_method: Type[interfaces.plugins.FileHandlerInterface],
layer_name: str = None,
prefix: str = "",
) -> Optional[str]:
"""Extracts the PE file referenced an LDR_DATA_TABLE_ENTRY (DLL, kernel module) instance
Args:
context: the context to operate upon
pe_table_name: the name for the symbol table containing the PE format symbols
ldr_entry: the object representing the module
open_method: class for constructing output files
layer_name: the layer that the DLL lives within
prefix: optional string to prepend to filename
Returns:
The output file name or None in the case of failure
"""
try:
name = ldr_entry.FullDllName.get_string()
except exceptions.InvalidAddressException:
name = "UnreadableDLLName"
if layer_name is None:
layer_name = ldr_entry.vol.layer_name
file_name = "{}{}.{:#x}.{:#x}.dmp".format(
prefix,
ntpath.basename(name),
ldr_entry.vol.offset,
ldr_entry.DllBase,
)
return cls.dump_pe(
context,
pe_table_name,
layer_name,
open_method,
file_name,
ldr_entry.DllBase,
)
@classmethod
def dump_pe_at_base(
cls,
context: interfaces.context.ContextInterface,
pe_table_name: str,
layer_name: str,
open_method: Type[interfaces.plugins.FileHandlerInterface],
proc_offset: int,
pid: int,
base: int,
) -> Optional[str]:
file_name = "PE.{:#x}.{:d}.{:#x}.dmp".format(
proc_offset,
pid,
base,
)
return PEDump.dump_pe(
context, pe_table_name, layer_name, open_method, file_name, base
)
@classmethod
def dump_kernel_pe_at_base(cls, context, kernel, pe_table_name, open_method, base):
session_layers = modules.Modules.get_session_layers(
context, kernel.layer_name, kernel.symbol_table_name
)
session_layer_name = modules.Modules.find_session_layer(
context, session_layers, base
)
if session_layer_name:
system_pid = 4
file_output = PEDump.dump_pe_at_base(
context,
pe_table_name,
session_layer_name,
open_method,
0,
system_pid,
base,
)
if file_output:
yield system_pid, "Kernel", file_output
else:
vollog.warning(
"Unable to find a session layer with the provided base address mapped in the kernel."
)
@classmethod
def dump_processes(
cls, context, kernel, pe_table_name, open_method, filter_func, base
):
""" """
for proc in pslist.PsList.list_processes(
context=context,
layer_name=kernel.layer_name,
symbol_table=kernel.symbol_table_name,
filter_func=filter_func,
):
pid = proc.UniqueProcessId
proc_name = proc.ImageFileName.cast(
"string",
max_length=proc.ImageFileName.vol.count,
errors="replace",
)
proc_layer_name = proc.add_process_layer()
file_output = PEDump.dump_pe_at_base(
context,
pe_table_name,
proc_layer_name,
open_method,
proc.vol.offset,
pid,
base,
)
if file_output:
yield pid, proc_name, file_output
def _generator(self):
kernel = self.context.modules[self.config["kernel"]]
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types=pe.class_types
)
if self.config["kernel_module"] and self.config["pid"]:
vollog.error("Only --kernel_module or --pid should be set. Not both")
return
if not self.config["kernel_module"] and not self.config["pid"]:
vollog.error("--kernel_module or --pid must be set")
return
if self.config["kernel_module"]:
pe_files = self.dump_kernel_pe_at_base(
self.context, kernel, pe_table_name, self.open, self.config["base"]
)
else:
filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
pe_files = self.dump_processes(
self.context,
kernel,
pe_table_name,
self.open,
filter_func,
self.config["base"],
)
for pid, proc_name, file_output in pe_files:
yield (
0,
(
pid,
proc_name,
file_output,
),
)
def run(self):
return renderers.TreeGrid(
[
("PID", int),
("Process", str),
("File output", str),
],
self._generator(),
)
@@ -0,0 +1,104 @@
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
import contextlib
from volatility3.framework import interfaces, exceptions
from volatility3.framework import renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.objects import utility
from volatility3.framework.renderers import format_hints
from volatility3.plugins.windows import pslist
vollog = logging.getLogger(__name__)
class ProcessGhosting(interfaces.plugins.PluginInterface):
"""Lists processes whose DeletePending bit is set or whose FILE_OBJECT is set to 0"""
_required_framework_version = (2, 4, 0)
@classmethod
def get_requirements(cls):
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.VersionRequirement(
name="pslist", component=pslist.PsList, version=(2, 0, 0)
),
]
def _generator(self, procs):
kernel = self.context.modules[self.config["kernel"]]
if not kernel.get_type("_EPROCESS").has_member("ImageFilePointer"):
vollog.warning(
"This plugin only supports Windows 10 builds when the ImageFilePointer member of _EPROCESS is present"
)
return
for proc in procs:
delete_pending = renderers.UnreadableValue()
process_name = utility.array_to_string(proc.ImageFileName)
# if it is 0 then its a side effect of process ghosting
if proc.ImageFilePointer.vol.offset != 0:
try:
file_object = proc.ImageFilePointer
delete_pending = file_object.DeletePending
except exceptions.InvalidAddressException:
file_object = 0
# ImageFilePointer equal to 0 means process ghosting or similar techniques were used
else:
file_object = 0
if isinstance(delete_pending, int) and delete_pending not in [0, 1]:
vollog.debug(
f"Invalid delete_pending value {delete_pending} found for {process_name} {proc.UniqueProcessId}"
)
# delete_pending besides 0 or 1 = smear
if file_object == 0 or delete_pending == 1:
path = renderers.UnreadableValue()
if file_object:
with contextlib.suppress(exceptions.InvalidAddressException):
path = file_object.FileName.String
yield (
0,
(
proc.UniqueProcessId,
process_name,
format_hints.Hex(file_object),
delete_pending,
path,
),
)
def run(self):
filter_func = pslist.PsList.create_active_process_filter()
kernel = self.context.modules[self.config["kernel"]]
return renderers.TreeGrid(
[
("PID", int),
("Process", str),
("FILE_OBJECT", format_hints.Hex),
("DeletePending", str),
("Path", str),
],
self._generator(
pslist.PsList.list_processes(
context=self.context,
layer_name=kernel.layer_name,
symbol_table=kernel.symbol_table_name,
filter_func=filter_func,
)
),
)
@@ -136,6 +136,29 @@ class PsList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
filter_func = lambda x: x.UniqueProcessId not in filter_list
return filter_func
@classmethod
def create_active_process_filter(
cls,
) -> Callable[[interfaces.objects.ObjectInterface], bool]:
"""A factory for producing a filter function that only returns
active, userland processes. This prevents plugins from operating on terminated
processes that are still in the process list due to smear or handle leaks as well
as kernel processes (System, Registry, etc.). Use of this filter for plugins searching
for system state anomalies significantly reduces false positive in smeared and terminated
processes.
Returns:
Filter function for passing to the `list_processes` method
"""
return lambda x: not (
x.is_valid()
and x.ActiveThreads > 0
and x.UniqueProcessId != 4
and x.InheritedFromUniqueProcessId != 4
and x.ExitTime.QuadPart == 0
and x.get_handle_count() != renderers.UnreadableValue()
)
@classmethod
def create_name_filter(
cls, name_list: List[str] = None, exclude: bool = False
@@ -17,11 +17,12 @@ from volatility3.framework.layers.registry import RegistryHive
from volatility3.framework.renderers import conversion, format_hints
from volatility3.framework.symbols import intermed
from volatility3.plugins.windows.registry import hivelist
from volatility3.plugins import timeliner
vollog = logging.getLogger(__name__)
class UserAssist(interfaces.plugins.PluginInterface):
class UserAssist(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
"""Print userassist registry keys and information."""
_required_framework_version = (2, 0, 0)
@@ -285,6 +286,10 @@ class UserAssist(interfaces.plugins.PluginInterface):
hive_offsets = [self.config.get("offset", None)]
kernel = self.context.modules[self.config["kernel"]]
self._reg_table_name = intermed.IntermediateSymbolTable.create(
self.context, self._config_path, "windows", "registry"
)
# get all the user hive offsets or use the one specified
for hive in hivelist.HiveList.list_hives(
context=self.context,
@@ -335,11 +340,17 @@ class UserAssist(interfaces.plugins.PluginInterface):
)
yield result
def run(self):
self._reg_table_name = intermed.IntermediateSymbolTable.create(
self.context, self._config_path, "windows", "registry"
)
def generate_timeline(self):
for row in self._generator():
_depth, row_data = row
# check the name and the timestamp to not be empty
if isinstance(row_data[5], str) and not isinstance(
row_data[10], renderers.NotApplicableValue
):
description = f"UserAssist: {row_data[5]} {row_data[2]} ({row_data[7]})"
yield (description, timeliner.TimeLinerType.MODIFIED, row_data[10])
def run(self):
return renderers.TreeGrid(
[
("Hive Offset", renderers.format_hints.Hex),
@@ -0,0 +1,610 @@
# This file is Copyright 2020 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
import os
from datetime import datetime
from itertools import count
from typing import Iterator, List, Optional, Tuple
from volatility3.framework import constants, exceptions, interfaces, renderers, symbols
from volatility3.framework.configuration import requirements
from volatility3.framework.objects.utility import array_to_string
from volatility3.framework.renderers import format_hints
from volatility3.framework.symbols import intermed
from volatility3.framework.symbols.windows import versions
from volatility3.framework.symbols.windows.extensions import pe, shimcache
from volatility3.plugins import timeliner
from volatility3.plugins.windows import modules, pslist, vadinfo
# from volatility3.plugins.windows import pslist, vadinfo, modules
vollog = logging.getLogger(__name__)
class ShimcacheMem(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
"""Reads Shimcache entries from the ahcache.sys AVL tree"""
_required_framework_version = (2, 0, 0)
# These checks must be completed from newest -> oldest OS version.
_win_version_file_map: List[Tuple[versions.OsDistinguisher, bool, str]] = [
(versions.is_win10, True, "shimcache-win10-x64"),
(versions.is_win10, False, "shimcache-win10-x86"),
(versions.is_windows_8_or_later, True, "shimcache-win8-x64"),
(versions.is_windows_8_or_later, False, "shimcache-win8-x86"),
(versions.is_windows_7, True, "shimcache-win7-x64"),
(versions.is_windows_7, False, "shimcache-win7-x86"),
(versions.is_vista_or_later, True, "shimcache-vista-x64"),
(versions.is_vista_or_later, False, "shimcache-vista-x86"),
(versions.is_2003, False, "shimcache-2003-x86"),
(versions.is_2003, True, "shimcache-2003-x64"),
(versions.is_windows_xp_sp3, False, "shimcache-xp-sp3-x86"),
(versions.is_windows_xp_sp2, False, "shimcache-xp-sp2-x86"),
(versions.is_xp_or_2003, True, "shimcache-xp-2003-x64"),
(versions.is_xp_or_2003, False, "shimcache-xp-2003-x86"),
]
NT_KRNL_MODS = ["ntoskrnl.exe", "ntkrnlpa.exe", "ntkrnlmp.exe", "ntkrpamp.exe"]
def generate_timeline(
self,
) -> Iterator[Tuple[str, timeliner.TimeLinerType, datetime]]:
for _, (_, last_modified, last_update, _, _, file_path) in self._generator():
if isinstance(last_update, datetime):
yield f"Shimcache: File {file_path} executed", timeliner.TimeLinerType.ACCESSED, last_update
if isinstance(last_modified, datetime):
yield f"Shimcache: File {file_path} modified", timeliner.TimeLinerType.MODIFIED, last_modified
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.PluginRequirement(
name="pslist", plugin=pslist.PsList, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="vadinfo", component=vadinfo.VadInfo, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="modules", component=modules.Modules, version=(2, 0, 0)
),
]
@staticmethod
def create_shimcache_table(
context: interfaces.context.ContextInterface,
symbol_table: str,
config_path: str,
) -> str:
"""Creates a shimcache symbol table
Args:
context: The context to retrieve required elements (layers, symbol tables) from
symbol_table: The name of an existing symbol table containing the kernel symbols
config_path: The configuration path within the context of the symbol table to create
Returns:
The name of the constructed shimcache table
"""
native_types = context.symbol_space[symbol_table].natives
is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
table_mapping = {"nt_symbols": symbol_table}
try:
symbol_filename = next(
filename
for version_check, for_64bit, filename in ShimcacheMem._win_version_file_map
if is_64bit == for_64bit
and version_check(context=context, symbol_table=symbol_table)
)
except StopIteration:
raise NotImplementedError("This version of Windows is not supported!")
vollog.debug(f"Using shimcache table {symbol_filename}")
return intermed.IntermediateSymbolTable.create(
context,
config_path,
os.path.join("windows", "shimcache"),
symbol_filename,
class_types=shimcache.class_types,
native_types=native_types,
table_mapping=table_mapping,
)
@classmethod
def find_shimcache_win_xp(
cls,
context: interfaces.context.ContextInterface,
layer_name: str,
kernel_symbol_table: str,
shimcache_symbol_table: str,
) -> Iterator[shimcache.SHIM_CACHE_ENTRY]:
"""Attempts to find the shimcache in a Windows XP memory image
:param context: The context to retrieve required elements (layers, symbol tables) from
:param layer_name: The name of the memory layer on which to operate.
:param kernel_symbol_table: The name of an existing symbol table containing the kernel symbols
:param shimcache_symbol_table: The name of a symbol table containing the hand-crafted shimcache symbols
"""
SHIM_NUM_ENTRIES_OFFSET = 0x8
SHIM_MAX_ENTRIES = 0x60 # 96 max entries in XP shim cache
SHIM_LRU_OFFSET = 0x10
SHIM_HEADER_SIZE = 0x190
SHIM_CACHE_ENTRY_SIZE = 0x228
seen = set()
for process in pslist.PsList.list_processes(
context, layer_name, kernel_symbol_table
):
pid = process.UniqueProcessId
vollog.debug("checking process %d" % pid)
for vad in vadinfo.VadInfo.list_vads(
process, lambda x: x.get_tag() == b"Vad " and x.Protection == 4
):
try:
proc_layer_name = process.add_process_layer()
proc_layer = context.layers[proc_layer_name]
except exceptions.InvalidAddressException:
continue
try:
if proc_layer.read(vad.get_start(), 4) != b"\xEF\xBE\xAD\xDE":
if pid == 624:
vollog.debug("VAD magic bytes don't match DEADBEEF")
continue
except exceptions.InvalidAddressException:
continue
num_entries = context.object(
shimcache_symbol_table + constants.BANG + "unsigned int",
proc_layer_name,
vad.get_start() + SHIM_NUM_ENTRIES_OFFSET,
)
if num_entries > SHIM_MAX_ENTRIES:
continue
cache_idx_ptr = vad.get_start() + SHIM_LRU_OFFSET
for _ in range(num_entries):
cache_idx_val = proc_layer.context.object(
shimcache_symbol_table + constants.BANG + "unsigned long",
proc_layer_name,
cache_idx_ptr,
)
cache_idx_ptr += 4
if cache_idx_val > SHIM_MAX_ENTRIES - 1:
continue
shim_entry_offset = (
vad.get_start()
+ SHIM_HEADER_SIZE
+ (SHIM_CACHE_ENTRY_SIZE * cache_idx_val)
)
if not proc_layer.is_valid(shim_entry_offset):
continue
physical_addr = proc_layer.translate(shim_entry_offset)
if physical_addr in seen:
continue
seen.add(physical_addr)
shim_entry = proc_layer.context.object(
shimcache_symbol_table + constants.BANG + "SHIM_CACHE_ENTRY",
proc_layer_name,
shim_entry_offset,
)
if not proc_layer.is_valid(shim_entry.vol.offset):
continue
if not shim_entry.is_valid():
continue
yield shim_entry
@classmethod
def find_shimcache_win_2k3_to_7(
cls,
context: interfaces.context.ContextInterface,
config_path: str,
kernel_layer_name: str,
nt_symbol_table: str,
shimcache_symbol_table: str,
) -> Iterator[shimcache.SHIM_CACHE_ENTRY]:
"""Implements the algorithm to search for the shim cache on Windows 2000
(x64) through Windows 7 / 2008 R2. The algorithm consists of the following:
1) Find the NT kernel module's .data and PAGE sections
2) Iterate over every 4/8 bytes (depending on OS bitness) in the .data
section and test for the following:
a) offset represents a valid RTL_AVL_TABLE object
b) RTL_AVL_TABLE is preceeded by an ERESOURCE object
c) RTL_AVL_TABLE is followed by the beginning of the SHIM LRU list
:param context: The context to retrieve required elements (layers, symbol tables) from
:param layer_name: The name of the memory layer on which to operate.
:param kernel_symbol_table: The name of an existing symbol table containing the kernel symbols
:param shimcache_symbol_table: The name of a symbol table containing the hand-crafted shimcache symbols
"""
data_sec = cls.get_module_section_range(
context,
config_path,
kernel_layer_name,
nt_symbol_table,
cls.NT_KRNL_MODS,
".data",
)
mod_page = cls.get_module_section_range(
context,
config_path,
kernel_layer_name,
nt_symbol_table,
cls.NT_KRNL_MODS,
"PAGE",
)
# We require both in order to accurately handle AVL table
if not (data_sec and mod_page):
return None
data_sec_offset, data_sec_size = data_sec
mod_page_offset, mod_page_size = mod_page
addr_size = 8 if symbols.symbol_table_is_64bit(context, nt_symbol_table) else 4
shim_head = None
for offset in range(
data_sec_offset, data_sec_offset + data_sec_size, addr_size
):
shim_head = cls.try_get_shim_head_at_offset(
context,
shimcache_symbol_table,
nt_symbol_table,
kernel_layer_name,
mod_page_offset,
mod_page_offset + mod_page_size,
offset,
)
if shim_head:
break
if not shim_head:
return
for shim_entry in shim_head.ListEntry.to_list(
shimcache_symbol_table + constants.BANG + "SHIM_CACHE_ENTRY", "ListEntry"
):
yield shim_entry
@classmethod
def try_get_shim_head_at_offset(
cls,
context: interfaces.context.ContextInterface,
symbol_table: str,
kernel_symbol_table: str,
layer_name: str,
mod_page_start: int,
mod_page_end: int,
offset: int,
) -> Optional[shimcache.SHIM_CACHE_ENTRY]:
"""Attempts to construct a SHIM_CACHE_HEAD within a layer of the given context,
using the provided offset within that layer, as well as the start and end offsets
of the kernel module's `PAGE` section start and end offsets.
If a number of validity checks are passed, this method will return the `SHIM_CACHE_HEAD`
object. Otherwise, `None` is returned.
"""
# print("checking RTL_AVL_TABLE at offset %s" % hex(offset))
rtl_avl_table = context.object(
symbol_table + constants.BANG + "_RTL_AVL_TABLE", layer_name, offset
)
if not rtl_avl_table.is_valid(mod_page_start, mod_page_end):
return None
vollog.debug(f"Candidate RTL_AVL_TABLE found at offset {hex(offset)}")
ersrc_size = context.symbol_space.get_type(
kernel_symbol_table + constants.BANG + "_ERESOURCE"
).size
ersrc_alignment = (
0x20
if symbols.symbol_table_is_64bit(context, kernel_symbol_table)
else 0x10
# 0x20 if context.symbol_space.get_type("pointer").size == 8 else 0x10
)
vollog.debug(
f"ERESOURCE size: {hex(ersrc_size)}, ERESOURCE alignment: {hex(ersrc_alignment)}"
)
eresource_rel_off = ersrc_size + ((offset - ersrc_size) % ersrc_alignment)
eresource_offset = offset - eresource_rel_off
vollog.debug("Constructing ERESOURCE at %s" % hex(eresource_offset))
eresource = context.object(
kernel_symbol_table + constants.BANG + "_ERESOURCE",
layer_name,
eresource_offset,
)
if not eresource.is_valid():
vollog.debug("ERESOURCE Invalid")
return None
shim_head_offset = offset + rtl_avl_table.vol.size
if not context.layers[layer_name].is_valid(shim_head_offset):
return None
shim_head = context.object(
symbol_table + constants.BANG + "SHIM_CACHE_ENTRY",
layer_name,
shim_head_offset,
)
if not shim_head.is_valid():
vollog.debug("shim head invalid")
return None
else:
vollog.debug("returning shim head")
return shim_head
@classmethod
def find_shimcache_win_8_or_later(
cls,
context: interfaces.context.ContextInterface,
config_path: str,
kernel_layer_name: str,
nt_symbol_table: str,
shimcache_symbol_table: str,
) -> Iterator[shimcache.SHIM_CACHE_ENTRY]:
"""Attempts to locate and yield shimcache entries from a Windows 8 or later memory image.
:param context: The context to retrieve required elements (layers, symbol tables) from
:param layer_name: The name of the memory layer on which to operate.
:param kernel_symbol_table: The name of an existing symbol table containing the kernel symbols
:param shimcache_symbol_table: The name of a symbol table containing the hand-crafted shimcache symbols
"""
is_8_1_or_later = versions.is_windows_8_1_or_later(
context, nt_symbol_table
) or versions.is_win10(context, nt_symbol_table)
module_names = ["ahcache.sys"] if is_8_1_or_later else cls.NT_KRNL_MODS
vollog.debug(f"Searching for modules {module_names}")
data_sec = cls.get_module_section_range(
context,
config_path,
kernel_layer_name,
nt_symbol_table,
module_names,
".data",
)
mod_page = cls.get_module_section_range(
context,
config_path,
kernel_layer_name,
nt_symbol_table,
module_names,
"PAGE",
)
if not (data_sec and mod_page):
return None
mod_page_offset, mod_page_size = mod_page
data_sec_offset, data_sec_size = data_sec
# iterate over ahcache kernel module's .data section in search of *two* SHIM handles
shim_heads = []
vollog.debug(f"PAGE offset: {hex(mod_page_offset)}")
vollog.debug(f".data offset: {hex(data_sec_offset)}")
handle_type = context.symbol_space.get_type(
shimcache_symbol_table + constants.BANG + "SHIM_CACHE_HANDLE"
)
for offset in range(
data_sec_offset,
data_sec_offset + data_sec_size,
8 if symbols.symbol_table_is_64bit(context, nt_symbol_table) else 4,
):
vollog.debug(f"Building shim handle pointer at {hex(offset)}")
shim_handle = context.object(
object_type=shimcache_symbol_table + constants.BANG + "pointer",
layer_name=kernel_layer_name,
subtype=handle_type,
offset=offset,
)
if shim_handle.is_valid(mod_page_offset, mod_page_offset + mod_page_size):
if shim_handle.head is not None:
vollog.debug(
f"Found valid shim handle @ {hex(shim_handle.vol.offset)}"
)
shim_heads.append(shim_handle.head)
if len(shim_heads) == 2:
break
if len(shim_heads) != 2:
vollog.debug("Failed to identify two valid SHIM_CACHE_HANDLE structures")
return
# On Windows 8 x64, the frist cache contains the shim cache
# On Windows 8 x86, 8.1 x86/x64, and 10, the second cache contains the shim cache.
if (
not symbols.symbol_table_is_64bit(context, nt_symbol_table)
and not is_8_1_or_later
):
valid_head = shim_heads[1]
elif not is_8_1_or_later:
valid_head = shim_heads[0]
else:
valid_head = shim_heads[1]
for shim_entry in valid_head.ListEntry.to_list(
shimcache_symbol_table + constants.BANG + "SHIM_CACHE_ENTRY", "ListEntry"
):
if shim_entry.is_valid():
yield shim_entry
def _generator(self):
kernel = self.context.modules[self.config["kernel"]]
shimcache_table_name = self.create_shimcache_table(
self.context, kernel.symbol_table_name, self.config_path
)
c = count()
if versions.is_windows_8_or_later(self._context, kernel.symbol_table_name):
vollog.info("Finding shimcache entries for Windows 8.0+")
entries = self.find_shimcache_win_8_or_later(
self.context,
self.config_path,
kernel.layer_name,
kernel.symbol_table_name,
shimcache_table_name,
)
elif (
versions.is_2003(self.context, kernel.symbol_table_name)
or versions.is_vista_or_later(self.context, kernel.symbol_table_name)
or versions.is_windows_7(self.context, kernel.symbol_table_name)
):
vollog.info("Finding shimcache entries for Windows 2k3/Vista/7")
entries = self.find_shimcache_win_2k3_to_7(
self.context,
self.config_path,
kernel.layer_name,
kernel.symbol_table_name,
shimcache_table_name,
)
elif versions.is_windows_xp_sp2(
self._context, kernel.symbol_table_name
) or versions.is_windows_xp_sp3(self.context, kernel.symbol_table_name):
vollog.info("Finding shimcache entries for WinXP")
entries = self.find_shimcache_win_xp(
self._context,
kernel.layer_name,
kernel.symbol_table_name,
shimcache_table_name,
)
else:
vollog.warn("Cannot parse shimcache entries for this version of Windows")
return
for entry in entries:
try:
vollog.debug(f"SHIM_CACHE_ENTRY type: {entry.__class__}")
shim_entry = (
entry.last_modified,
entry.last_update,
entry.exec_flag,
(
format_hints.Hex(entry.file_size)
if isinstance(entry.file_size, int)
else entry.file_size
),
entry.file_path,
)
except exceptions.InvalidAddressException:
continue
yield (
0,
(next(c), *shim_entry),
)
def run(self):
return renderers.TreeGrid(
[
("Order", int),
("Last Modified", datetime),
("Last Update", datetime),
("Exec Flag", bool),
("File Size", format_hints.Hex),
("File Path", str),
],
self._generator(),
)
@classmethod
def get_module_section_range(
cls,
context: interfaces.context.ContextInterface,
config_path: str,
layer_name: str,
symbol_table: str,
module_list: List[str],
section_name: str,
) -> Optional[Tuple[int, int]]:
"""Locates the size and offset of the first found module section
specified by name from the list of modules.
:param context: The context to operate on
:param layer_name: The memory layer to read from
:param module_list: A list of module names to search for the given section
:param section_name: The name of the section to search for.
:return: The offset and size of the module, if found; Otherwise, returns `None`
"""
try:
krnl_mod = next(
module
for module in modules.Modules.list_modules(
context, layer_name, symbol_table
)
if module.BaseDllName.String in module_list
)
except StopIteration:
return None
pe_table_name = intermed.IntermediateSymbolTable.create(
context,
interfaces.configuration.path_join(config_path, "pe"),
"windows",
"pe",
class_types=pe.class_types,
)
# code taken from Win32KBase._section_chunks (win32_core.py)
dos_header = context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
layer_name,
offset=krnl_mod.DllBase,
)
if not dos_header:
return None
nt_header = dos_header.get_nt_header()
try:
section = next(
sec
for sec in nt_header.get_sections()
if section_name.lower() == array_to_string(sec.Name).lower()
)
except StopIteration:
return None
section_offset = krnl_mod.DllBase + section.VirtualAddress
section_size = section.Misc.VirtualSize
return section_offset, section_size
@@ -0,0 +1,103 @@
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
# This module attempts to locate skeleton-key like function hooks.
# It does this by locating the CSystems array through a variety of methods,
# and then validating the entry for RC4 HMAC (0x17 / 23)
#
# For a thorough walkthrough on how the R&D was performed to develop this plugin,
# please see our blogpost here:
#
# https://volatility-labs.blogspot.com/2021/10/memory-forensics-r-illustrated.html
import logging
from volatility3.framework import symbols, interfaces
from volatility3.framework.configuration import requirements
from volatility3.plugins.windows import svclist, svcscan
from volatility3.framework.symbols.windows import versions
vollog = logging.getLogger(__name__)
class SvcDiff(svcscan.SvcScan):
"""Compares services found through list walking versus scanning to find rootkits"""
_required_framework_version = (2, 4, 0)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._enumeration_method = self.service_diff
@classmethod
def get_requirements(cls):
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.VersionRequirement(
name="svclist", component=svclist.SvcList, version=(1, 0, 0)
),
requirements.VersionRequirement(
name="svcscan", component=svcscan.SvcScan, version=(3, 0, 0)
),
]
@classmethod
def service_diff(
cls,
context: interfaces.context.ContextInterface,
layer_name: str,
symbol_table: str,
service_table_name: str,
service_binary_dll_map,
filter_func,
):
"""
On Windows 10 version 15063+ 64bit Windows memory samples, walk the services list
and scan for services then report differences
"""
if not symbols.symbol_table_is_64bit(
context, symbol_table
) or not versions.is_win10_15063_or_later(
context=context, symbol_table=symbol_table
):
vollog.warning(
"This plugin only supports Windows 10 version 15063+ 64bit Windows memory samples"
)
return
from_scan = set()
from_list = set()
records = {}
# collect unique service names from scanning
for service in svcscan.SvcScan.service_scan(
context,
layer_name,
symbol_table,
service_table_name,
service_binary_dll_map,
filter_func,
):
from_scan.add(service[6])
records[service[6]] = service
# collect services from listing walking
for service in svclist.SvcList.service_list(
context,
layer_name,
symbol_table,
service_table_name,
service_binary_dll_map,
filter_func,
):
from_list.add(service[6])
# report services found from scanning but not list walking
for hidden_service in from_scan - from_list:
yield records[hidden_service]
@@ -0,0 +1,115 @@
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
from typing import List, Optional, Tuple
from volatility3.framework import interfaces, exceptions, symbols
from volatility3.framework.configuration import requirements
from volatility3.framework.symbols.windows import versions
from volatility3.plugins.windows import svcscan, pslist
from volatility3.framework.layers import scanners
vollog = logging.getLogger(__name__)
class SvcList(svcscan.SvcScan):
"""Lists services contained with the services.exe doubly linked list of services"""
_version = (1, 0, 0)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._enumeration_method = self.service_list
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.PluginRequirement(
name="svcscan", plugin=svcscan.SvcScan, version=(3, 0, 0)
),
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
]
@classmethod
def _get_exe_range(cls, proc) -> Optional[Tuple[int, int]]:
"""
Returns a tuple of starting,ending address for
the VAD containing services.exe
"""
vad_root = proc.get_vad_root()
for vad in vad_root.traverse():
filename = vad.get_file_name()
if isinstance(filename, str) and filename.lower().endswith(
"\\services.exe"
):
return [(vad.get_start(), vad.get_size())]
return None
@classmethod
def service_list(
cls,
context: interfaces.context.ContextInterface,
layer_name: str,
symbol_table: str,
service_table_name: str,
service_binary_dll_map,
filter_func,
):
if not symbols.symbol_table_is_64bit(
context, symbol_table
) or not versions.is_win10_15063_or_later(
context=context, symbol_table=symbol_table
):
vollog.warning(
"This plugin only supports Windows 10 version 15063+ 64bit Windows memory samples"
)
return
for proc in pslist.PsList.list_processes(
context=context,
layer_name=layer_name,
symbol_table=symbol_table,
filter_func=filter_func,
):
try:
layer_name = proc.add_process_layer()
except exceptions.InvalidAddressException:
vollog.warning(
"Unable to access memory of services.exe running with PID: {}".format(
proc.UniqueProcessId
)
)
continue
layer = context.layers[layer_name]
exe_range = cls._get_exe_range(proc)
if not exe_range:
vollog.warning(
"Could not find the application executable VAD for services.exe. Unable to proceed."
)
continue
for offset in layer.scan(
context=context,
scanner=scanners.BytesScanner(needle=b"Sc27"),
sections=exe_range,
):
for record in cls.enumerate_vista_or_later_header(
context,
service_table_name,
service_binary_dll_map,
layer_name,
offset,
):
yield record
+113 -58
View File
@@ -19,7 +19,7 @@ from volatility3.framework.layers import scanners
from volatility3.framework.renderers import format_hints
from volatility3.framework.symbols import intermed
from volatility3.framework.symbols.windows import versions
from volatility3.framework.symbols.windows.extensions import services
from volatility3.framework.symbols.windows.extensions import services as services_types
from volatility3.plugins.windows import poolscanner, pslist, vadyarascan
from volatility3.plugins.windows.registry import hivelist
@@ -39,7 +39,11 @@ class SvcScan(interfaces.plugins.PluginInterface):
"""Scans for windows services."""
_required_framework_version = (2, 0, 0)
_version = (2, 0, 0)
_version = (3, 0, 0)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._enumeration_method = self.service_scan
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -106,7 +110,7 @@ class SvcScan(interfaces.plugins.PluginInterface):
]
@staticmethod
def create_service_table(
def _create_service_table(
context: interfaces.context.ContextInterface,
symbol_table: str,
config_path: str,
@@ -140,18 +144,21 @@ class SvcScan(interfaces.plugins.PluginInterface):
config_path,
os.path.join("windows", "services"),
symbol_filename,
class_types=services.class_types,
class_types=services_types.class_types,
native_types=native_types,
)
def _get_service_key(self, kernel) -> Optional[objects.StructType]:
@staticmethod
def _get_service_key(
context, config_path: str, layer_name: str, symbol_table: str
) -> Optional[objects.StructType]:
for hive in hivelist.HiveList.list_hives(
context=self.context,
context=context,
base_config_path=interfaces.configuration.path_join(
self.config_path, "hivelist"
config_path, "hivelist"
),
layer_name=kernel.layer_name,
symbol_table=kernel.symbol_table_name,
layer_name=layer_name,
symbol_table=symbol_table,
filter_string="machine\\system",
):
# Get ControlSet\Services.
@@ -232,30 +239,55 @@ class SvcScan(interfaces.plugins.PluginInterface):
for service_key in services
}
def _generator(self):
kernel = self.context.modules[self.config["kernel"]]
@classmethod
def enumerate_vista_or_later_header(
cls,
context,
service_table_name,
service_binary_dll_map,
proc_layer_name,
offset,
):
if offset % 8:
return
service_table_name = self.create_service_table(
self.context, kernel.symbol_table_name, self.config_path
service_header = context.object(
service_table_name + constants.BANG + "_SERVICE_HEADER",
offset=offset,
layer_name=proc_layer_name,
)
# Building the dictionary ahead of time is much better for performance
# vs looking up each service's DLL individually.
services_key = self._get_service_key(kernel)
service_binary_dll_map = (
self._get_service_binary_map(services_key)
if services_key is not None
else {}
)
if not service_header.is_valid():
return
relative_tag_offset = self.context.symbol_space.get_type(
# since we walk the s-list backwards, if we've seen
# an object, then we've also seen all objects that
# exist before it, thus we can break at that time.
for service_record in service_header.ServiceRecord.traverse():
service_info = service_binary_dll_map.get(
service_record.get_name(),
ServiceBinaryInfo(
renderers.UnreadableValue(), renderers.UnreadableValue()
),
)
yield cls.get_record_tuple(service_record, service_info)
@classmethod
def service_scan(
cls,
context: interfaces.context.ContextInterface,
layer_name: str,
symbol_table: str,
service_table_name: str,
service_binary_dll_map,
filter_func,
):
relative_tag_offset = context.symbol_space.get_type(
service_table_name + constants.BANG + "_SERVICE_RECORD"
).relative_child_offset("Tag")
filter_func = pslist.PsList.create_name_filter(["services.exe"])
is_vista_or_later = versions.is_vista_or_later(
context=self.context, symbol_table=kernel.symbol_table_name
context=context, symbol_table=symbol_table
)
if is_vista_or_later:
@@ -266,9 +298,9 @@ class SvcScan(interfaces.plugins.PluginInterface):
seen = []
for task 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,
filter_func=filter_func,
):
proc_id = "Unknown"
@@ -283,15 +315,15 @@ class SvcScan(interfaces.plugins.PluginInterface):
)
continue
layer = self.context.layers[proc_layer_name]
layer = context.layers[proc_layer_name]
for offset in layer.scan(
context=self.context,
context=context,
scanner=scanners.BytesScanner(needle=service_tag),
sections=vadyarascan.VadYaraScan.get_vad_maps(task),
):
if not is_vista_or_later:
service_record = self.context.object(
service_record = context.object(
service_table_name + constants.BANG + "_SERVICE_RECORD",
offset=offset - relative_tag_offset,
layer_name=proc_layer_name,
@@ -306,37 +338,60 @@ class SvcScan(interfaces.plugins.PluginInterface):
renderers.UnreadableValue(), renderers.UnreadableValue()
),
)
yield (
0,
self.get_record_tuple(service_record, service_info),
)
yield cls.get_record_tuple(service_record, service_info)
else:
service_header = self.context.object(
service_table_name + constants.BANG + "_SERVICE_HEADER",
offset=offset,
layer_name=proc_layer_name,
)
if not service_header.is_valid():
continue
# since we walk the s-list backwards, if we've seen
# an object, then we've also seen all objects that
# exist before it, thus we can break at that time.
for service_record in service_header.ServiceRecord.traverse():
for service_record in cls.enumerate_vista_or_later_header(
context,
service_table_name,
service_binary_dll_map,
proc_layer_name,
offset,
):
if service_record in seen:
break
seen.append(service_record)
service_info = service_binary_dll_map.get(
service_record.get_name(),
ServiceBinaryInfo(
renderers.UnreadableValue(), renderers.UnreadableValue()
),
)
yield (
0,
self.get_record_tuple(service_record, service_info),
)
yield service_record
@classmethod
def get_prereq_info(cls, context, config_path, layer_name: str, symbol_table: str):
"""
Data structures and information needed to analyze service information
"""
service_table_name = cls._create_service_table(
context, symbol_table, config_path
)
services_key = cls._get_service_key(
context, config_path, layer_name, symbol_table
)
service_binary_dll_map = (
cls._get_service_binary_map(services_key)
if services_key is not None
else {}
)
filter_func = pslist.PsList.create_name_filter(["services.exe"])
return service_table_name, service_binary_dll_map, filter_func
def _generator(self):
kernel = self.context.modules[self.config["kernel"]]
service_table_name, service_binary_dll_map, filter_func = self.get_prereq_info(
self.context, self.config_path, kernel.layer_name, kernel.symbol_table_name
)
for record in self._enumeration_method(
self.context,
kernel.layer_name,
kernel.symbol_table_name,
service_table_name,
service_binary_dll_map,
filter_func,
):
yield (0, record)
def run(self):
return renderers.TreeGrid(
@@ -0,0 +1,212 @@
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
from typing import Iterator, List, Tuple, Iterable
from volatility3.framework import (
renderers,
interfaces,
constants,
symbols,
)
from volatility3.framework.configuration import requirements
from volatility3.framework.renderers import format_hints
from volatility3.framework.symbols.windows import versions
from volatility3.plugins.windows import ssdt, kpcrs
vollog = logging.getLogger(__name__)
class Timers(interfaces.plugins.PluginInterface):
"""Print kernel timers and associated module DPCs"""
_required_framework_version = (2, 0, 0)
_version = (1, 0, 0)
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.ModuleRequirement(
name="kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.PluginRequirement(
name="ssdt", plugin=ssdt.SSDT, version=(1, 0, 0)
),
requirements.PluginRequirement(
name="kpcrs", plugin=kpcrs.KPCRs, version=(1, 0, 0)
),
]
@classmethod
def list_timers(
cls,
context: interfaces.context.ContextInterface,
kernel_module_name: str,
layer_name: str,
symbol_table: str,
) -> Iterable[Tuple[str, int, str]]:
"""Lists all kernel timers.
Args:
context: The context to retrieve required elements (layers, symbol tables) from
kernel_module_name: The name of the kernel module on which to operate
layer_name: The name of the layer on which to operate
symbol_table: The name of the table containing the kernel symbols
Yields:
A _KTIMER entry
"""
kernel = context.modules[kernel_module_name]
if versions.is_windows_7(
context=context, symbol_table=symbol_table
) or versions.is_windows_8_or_later(context=context, symbol_table=symbol_table):
# Starting with Windows 7, there is no more KiTimerTableListHead. The list is
# at _KPCR.PrcbData.TimerTable.TimerEntries
# See http://pastebin.com/FiRsGW3f
for kpcr in kpcrs.KPCRs.list_kpcrs(
context, kernel_module_name, layer_name, symbol_table
):
if hasattr(kpcr.Prcb.TimerTable, "TableState"):
for timer_entries in kpcr.Prcb.TimerTable.TimerEntries:
for timer_entry in timer_entries:
for timer in timer_entry.Entry.to_list(
symbol_table + constants.BANG + "_KTIMER",
"TimerListEntry",
):
yield timer
else:
for timer_entries in kpcr.Prcb.TimerTable.TimerEntries:
for timer in timer_entries.Entry.to_list(
symbol_table + constants.BANG + "_KTIMER",
"TimerListEntry",
):
yield timer
elif versions.is_xp_or_2003(
context=context, symbol_table=symbol_table
) or versions.is_vista_or_later(context=context, symbol_table=symbol_table):
is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
if is_64bit or versions.is_vista_or_later(
context=context, symbol_table=symbol_table
):
# On XP x64, Windows 2003 SP1-SP2, and Vista SP0-SP2, KiTimerTableListHead
# is an array of 512 _KTIMER_TABLE_ENTRY structs.
array_size = 512
else:
# On XP SP0-SP3 x86 and Windows 2003 SP0, KiTimerTableListHead
# is an array of 256 _LIST_ENTRY for _KTIMERs.
array_size = 256
timer_table_list_head = kernel.object(
object_type="array",
offset=kernel.get_symbol("KiTimerTableListHead").address,
subtype=kernel.get_type("_LIST_ENTRY"),
count=array_size,
)
for table in timer_table_list_head:
for timer in table.to_list(
symbol_table + constants.BANG + "_KTIMER",
"TimerListEntry",
):
yield timer
else:
raise NotImplementedError("This version of Windows is not supported!")
def _generator(self) -> Iterator[Tuple]:
kernel = self.context.modules[self.config["kernel"]]
layer_name = kernel.layer_name
symbol_table = kernel.symbol_table_name
collection = ssdt.SSDT.build_module_collection(
self.context, kernel.layer_name, kernel.symbol_table_name
)
for timer in self.list_timers(
self.context, self.config["kernel"], layer_name, symbol_table
):
if not timer.valid_type():
continue
try:
dpc = timer.get_dpc()
if dpc == 0:
continue
if dpc.DeferredRoutine == 0:
continue
deferred_routine = dpc.DeferredRoutine
except Exception as e:
continue
module_symbols = list(
collection.get_module_symbols_by_absolute_location(deferred_routine)
)
if module_symbols:
for module_name, symbol_generator in module_symbols:
symbols_found = False
# we might have multiple symbols pointing to the same location
for symbol in symbol_generator:
symbols_found = True
yield (
0,
(
format_hints.Hex(timer.vol.offset),
timer.get_due_time(),
timer.Period,
timer.get_signaled(),
format_hints.Hex(deferred_routine),
module_name,
symbol.split(constants.BANG)[1],
),
)
# no symbols, but we at least can report the module name
if not symbols_found:
yield (
0,
(
format_hints.Hex(timer.vol.offset),
timer.get_due_time(),
timer.Period,
timer.get_signaled(),
format_hints.Hex(deferred_routine),
module_name,
renderers.NotAvailableValue(),
),
)
else:
# no module was found at the absolute location
yield (
0,
(
format_hints.Hex(timer.vol.offset),
timer.get_due_time(),
timer.Period,
timer.get_signaled(),
format_hints.Hex(deferred_routine),
renderers.NotAvailableValue(),
renderers.NotAvailableValue(),
),
)
def run(self):
return renderers.TreeGrid(
[
("Offset", format_hints.Hex),
("DueTime", str),
("Period(ms)", int),
("Signaled", str),
("Routine", format_hints.Hex),
("Module", str),
("Symbol", str),
],
self._generator(),
)
@@ -56,7 +56,7 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
sanity_check = 0x1000 * 0x1000 * 0x1000
sanity_check = 1024 * 1024 * 1024 # 1 GB
for task in pslist.PsList.list_processes(
context=self.context,
@@ -66,15 +66,14 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
):
layer_name = task.add_process_layer()
layer = self.context.layers[layer_name]
for start, end in self.get_vad_maps(task):
size = end - start
for start, size in self.get_vad_maps(task):
if size > sanity_check:
vollog.warn(
f"VAD at 0x{start:x} over sanity-check size, not scanning"
)
continue
for match in rules.match(data=layer.read(start, end - start, True)):
for match in rules.match(data=layer.read(start, size, True)):
if yarascan.YaraScan.yara_returns_instances():
for match_string in match.strings:
for instance in match_string.instances:
@@ -106,7 +105,7 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
task: The EPROCESS object of which to traverse the vad tree
Returns:
An iterable of tuples containing start and end addresses for each descriptor
An iterable of tuples containing start and size for each descriptor
"""
vad_root = task.get_vad_root()
for vad in vad_root.traverse():
@@ -17,6 +17,7 @@ class WindowsKernelIntermedSymbols(intermed.IntermediateSymbolTable):
self.set_type_class("_KTHREAD", extensions.KTHREAD)
self.set_type_class("_LIST_ENTRY", extensions.LIST_ENTRY)
self.set_type_class("_EPROCESS", extensions.EPROCESS)
self.set_type_class("_ERESOURCE", extensions.ERESOURCE)
self.set_type_class("_UNICODE_STRING", extensions.UNICODE_STRING)
self.set_type_class("_EX_FAST_REF", extensions.EX_FAST_REF)
self.set_type_class("_TOKEN", extensions.TOKEN)
@@ -39,6 +40,7 @@ class WindowsKernelIntermedSymbols(intermed.IntermediateSymbolTable):
self.set_type_class("_VACB", extensions.VACB)
self.set_type_class("_POOL_TRACKER_BIG_PAGES", pool.POOL_TRACKER_BIG_PAGES)
self.set_type_class("_IMAGE_DOS_HEADER", pe.IMAGE_DOS_HEADER)
self.set_type_class("_KTIMER", extensions.KTIMER)
# Might not necessarily defined in every version of windows
self.optional_set_type_class("_IMAGE_NT_HEADERS", pe.IMAGE_NT_HEADERS)
@@ -20,6 +20,7 @@ from volatility3.framework import (
)
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.windows.extensions import pool
@@ -306,16 +307,19 @@ class MMVAD_SHORT(objects.StructType):
raise AttributeError("Unable to find the private memory member")
@property
def Protection(self):
if self.has_member("u"):
return self.u.VadFlags.Protection
elif self.has_member("Core"):
return self.Core.u.VadFlags.Protection
else:
return None
def get_protection(self, protect_values, winnt_protections):
"""Get the VAD's protection constants as a string."""
protect = None
if self.has_member("u"):
protect = self.u.VadFlags.Protection
elif self.has_member("Core"):
protect = self.Core.u.VadFlags.Protection
protect = self.Protection
try:
value = protect_values[protect]
@@ -593,6 +597,38 @@ class UNICODE_STRING(objects.StructType):
String = property(get_string)
class ERESOURCE(objects.StructType):
def is_valid(self) -> bool:
vollog.debug(f"Checking ERESOURCE Validity: {hex(self.vol.offset)}")
if not self._context.layers[self.vol.layer_name].is_valid(self.vol.offset):
return False
sym_table = self.get_symbol_table_name()
waiters_valid = self.SharedWaiters == 0 or self._context.layers[
self.vol.layer_name
].is_valid(
self.SharedWaiters.vol.offset,
self._context.symbol_space.get_type(
sym_table + constants.BANG + "_KSEMAPHORE"
).size,
)
try:
return (
waiters_valid
and self.SystemResourcesList.Flink is not None
and self.SystemResourcesList.Blink is not None
and self.SystemResourcesList.Flink != self.SystemResourcesList.Blink
and self.SystemResourcesList.Flink.Blink == self.vol.offset
and self.SystemResourcesList.Blink.Flink == self.vol.offset
and self.NumberOfSharedWaiters == 0
)
except exceptions.InvalidAddressException:
return False
class EPROCESS(generic.GenericIntelProcess, pool.ExecutiveObject):
"""A class for executive kernel processes objects."""
@@ -1010,6 +1046,83 @@ class TOKEN(objects.StructType):
vollog.log(constants.LOGLEVEL_VVVV, "Broken Token Privileges.")
class KTIMER(objects.StructType):
"""A class for Kernel Timers"""
VALID_TYPES = {
8: "TimerNotificationObject",
9: "TimerSynchronizationObject",
}
def get_signaled(self):
if self.Header.SignalState:
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
def get_due_time(self):
return "{0:#010x}:{1:#010x}".format(self.DueTime.HighPart, self.DueTime.LowPart)
def get_dpc(self):
"""Return Dpc, and if Windows 7 or later, decode it"""
symbol_table_name = self.get_symbol_table_name()
kvo = self._context.layers[self.vol.native_layer_name].config[
"kernel_virtual_offset"
]
ntkrnlmp = self._context.module(
symbol_table_name,
layer_name=self.vol.native_layer_name,
offset=kvo,
native_layer_name=self.vol.native_layer_name,
)
if ntkrnlmp.has_symbol("KiWaitNever") and ntkrnlmp.has_symbol("KiWaitAlways"):
wait_never = ntkrnlmp.object(
object_type="unsigned long long",
offset=ntkrnlmp.get_symbol("KiWaitNever").address,
)
wait_always = ntkrnlmp.object(
object_type="unsigned long long",
offset=ntkrnlmp.get_symbol("KiWaitAlways").address,
)
low_byte = (wait_never) & 0xFF
entry = utility.rol(self.get_raw_dpc() ^ wait_never, low_byte)
swap_xor = self._context.layers[self.vol.native_layer_name].canonicalize(
self.vol.offset
)
entry = utility.bswap_64(entry ^ swap_xor)
dpc = entry ^ wait_always
symbol_table_name = self.get_symbol_table_name()
kdpc_type = self._context.symbol_space.get_type(
symbol_table_name + constants.BANG + "_KDPC"
)
return self._context.object(
object_type=kdpc_type,
layer_name=self.vol.layer_name,
offset=dpc,
)
else:
return self.Dpc
class KTHREAD(objects.StructType):
"""A class for thread control block objects."""
@@ -0,0 +1,278 @@
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
import struct
from datetime import datetime
from typing import Dict, Optional, Tuple, Union
from volatility3.framework import constants, exceptions, interfaces, objects, renderers
from volatility3.framework.symbols.windows.extensions import conversion
vollog = logging.getLogger(__name__)
class SHIM_CACHE_ENTRY(objects.StructType):
"""Class for abstracting variations in the shimcache LRU list entry structure"""
def __init__(
self,
context: interfaces.context.ContextInterface,
type_name: str,
object_info: interfaces.objects.ObjectInformation,
size: int,
members: Dict[str, Tuple[int, interfaces.objects.Template]],
) -> None:
super().__init__(context, type_name, object_info, size, members)
self._exec_flag = None
self._file_path = None
self._file_size = None
self._last_modified = None
self._last_updated = None
@property
def exec_flag(self) -> Union[bool, interfaces.renderers.BaseAbsentValue]:
"""Checks if InsertFlags fields has been bitwise OR'd with a value of 2.
This behavior was observed when processes are created by CSRSS."""
if self._exec_flag is not None:
return self._exec_flag
if hasattr(self, "ListEntryDetail") and hasattr(
self.ListEntryDetail, "InsertFlags"
):
self._exec_flag = self.ListEntryDetail.InsertFlags & 0x2 == 2
elif hasattr(self, "InsertFlags"):
self._exec_flag = self.InsertFlags & 0x2 == 2
elif hasattr(self, "ListEntryDetail") and hasattr(
self.ListEntryDetail, "BlobBuffer"
):
blob_offset = self.ListEntryDetail.BlobBuffer
blob_size = self.ListEntryDetail.BlobSize
if not self._context.layers[self.vol.native_layer_name].is_valid(
blob_offset, blob_size
):
self._exec_flag = renderers.UnparsableValue()
raw_flag = self._context.layers[self.vol.native_layer_name].read(
blob_offset, blob_size
)
if not raw_flag:
self._exec_flag = renderers.UnparsableValue()
try:
self._exec_flag = bool(struct.unpack("<I", raw_flag)[0])
except struct.error:
self._exec_flag = renderers.UnparsableValue()
else:
# Always set to true for XP/2K3
self._exec_flag = renderers.NotApplicableValue()
return self._exec_flag
@property
def file_size(self) -> Union[int, interfaces.renderers.BaseAbsentValue]:
if self._file_size is not None:
return self._file_size
try:
self._file_size = self.FileSize
if self._file_size < 0:
self._file_size = 0
except AttributeError:
self._file_size = renderers.NotApplicableValue()
except exceptions.InvalidAddressException:
self._file_size = renderers.UnreadableValue()
return self._file_size
@property
def last_modified(self) -> Union[datetime, interfaces.renderers.BaseAbsentValue]:
if self._last_modified is not None:
return self._last_modified
try:
self._last_modified = conversion.wintime_to_datetime(
self.ListEntryDetail.LastModified.QuadPart
)
except AttributeError:
self._last_modified = conversion.wintime_to_datetime(
self.LastModified.QuadPart
)
except exceptions.InvalidAddressException:
self._last_modified = renderers.UnreadableValue()
return self._last_modified
@property
def last_update(self) -> Union[datetime, interfaces.renderers.BaseAbsentValue]:
if self._last_updated is not None:
return self._last_updated
try:
self._last_updated = conversion.wintime_to_datetime(
self.LastUpdate.QuadPart
)
except AttributeError:
self._last_updated = renderers.NotApplicableValue()
return self._last_updated
@property
def file_path(self) -> Union[str, interfaces.renderers.BaseAbsentValue]:
if self._file_path is not None:
return self._file_path
if not hasattr(self.Path, "Buffer"):
return self.Path.cast(
"string", max_length=self.Path.vol.count, encoding="utf-16le"
)
try:
file_path_raw = (
self._context.layers[self.vol.native_layer_name].read(
self.Path.Buffer, self.Path.Length
)
or b""
)
self._file_path = file_path_raw.decode("utf-16", errors="replace")
except exceptions.InvalidAddressException:
self._file_path = renderers.UnreadableValue()
return self._file_path
def is_valid(self) -> bool:
"""Shim cache validation is limited to ensuring that a subset of the
pointers in the LIST_ENTRY field are valid (similar to validation of
ERESOURCE)"""
# shim entries on Windows XP do not have list entry attributes; in this case,
# perform a different set of validations
try:
if not hasattr(self, "ListEntry"):
return bool(self.last_modified and self.last_update and self.file_size)
# on some platforms ListEntry.Blink is null, so this cannot be validated
if (
self.ListEntry.Flink != 0
and (
self.ListEntry.Blink.dereference()
!= self.ListEntry.Flink.dereference()
)
and (
self.ListEntry.Flink.Blink
== self.ListEntry.Flink.Blink.dereference().vol.offset
)
):
return True
else:
return False
except exceptions.InvalidAddressException:
return False
class SHIM_CACHE_HANDLE(objects.StructType):
def __init__(
self,
context: interfaces.context.ContextInterface,
type_name: str,
object_info: interfaces.objects.ObjectInformation,
size: int,
members: Dict[str, Tuple[int, interfaces.objects.Template]],
) -> None:
super().__init__(context, type_name, object_info, size, members)
@property
def head(self) -> Optional[SHIM_CACHE_ENTRY]:
try:
if not self.eresource.is_valid():
return None
except exceptions.InvalidAddressException:
return None
rtl_avl_table = self._context.object(
self.get_symbol_table_name() + constants.BANG + "_RTL_AVL_TABLE",
self.vol.layer_name,
self.rtl_avl_table,
self.vol.native_layer_name,
)
if not self._context.layers[self.vol.layer_name].is_valid(
self.rtl_avl_table.vol.offset
):
return None
offset_head = rtl_avl_table.vol.offset + rtl_avl_table.vol.size
head = self._context.object(
self.get_symbol_table_name() + constants.BANG + "SHIM_CACHE_ENTRY",
self.vol.layer_name,
offset_head,
)
if not head.is_valid():
return None
return head
def is_valid(self, avl_section_start: int, avl_section_end: int) -> bool:
if self.vol.offset == 0:
return False
vollog.debug(f"Checking SHIM_CACHE_HANDLE validity @ {hex(self.vol.offset)}")
if not (
self._context.layers[self.vol.layer_name].is_valid(self.vol.offset)
and self.eresource.is_valid()
and self.rtl_avl_table.is_valid(avl_section_start, avl_section_end)
and self.head
):
return False
return self.head.is_valid()
class RTL_AVL_TABLE(objects.StructType):
def is_valid(self, page_start: int, page_end: int) -> bool:
try:
if self.BalancedRoot.Parent != self.BalancedRoot.vol.offset:
vollog.debug(
f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed BalancedRoot parent equality check"
)
return False
elif self.AllocateRoutine < page_start or self.AllocateRoutine > page_end:
vollog.debug(
f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed AllocateRoutine range check"
)
return False
elif self.CompareRoutine < page_start or self.CompareRoutine > page_end:
vollog.debug(
f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed CompareRoutine range check"
)
return False
elif (
(self.AllocateRoutine.vol.offset == self.CompareRoutine.vol.offset)
or (self.AllocateRoutine.vol.offset == self.FreeRoutine.vol.offset)
or (self.CompareRoutine.vol.offset == self.FreeRoutine.vol.offset)
):
vollog.debug(
f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed (Compare|Allocate|Free)Routine uniqueness check"
)
return False
return True
except exceptions.InvalidAddressException:
return False
class_types = {
"SHIM_CACHE_HANDLE": SHIM_CACHE_HANDLE,
"SHIM_CACHE_ENTRY": SHIM_CACHE_ENTRY,
"_RTL_AVL_TABLE": RTL_AVL_TABLE,
}
@@ -0,0 +1,327 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 16
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 24
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 25
}
},
"kind": "struct",
"size": 32
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 32
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 40
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 44
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 48
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 56
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 64
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 72
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 80
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 88
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 96
}
},
"kind": "struct",
"size": 104
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 16
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"Path": {
"offset": 16,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"LastModified": {
"offset": 32,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"FileSize": {
"offset": 40,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 48
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,334 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 8
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"Path": {
"offset": 8,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"LastModified": {
"offset": 16,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"FileSize": {
"offset": 24,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"Padding": {
"offset": 32,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 36
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,334 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 16
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 24
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 25
}
},
"kind": "struct",
"size": 32
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 32
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 40
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 44
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 48
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 56
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 64
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 72
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 80
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 88
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 96
}
},
"kind": "struct",
"size": 104
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 16
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"Path": {
"offset": 16,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"LastModified": {
"offset": 32,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"InsertFlags": {
"offset": 40,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"ShimFlags": {
"offset": 44,
"type": {
"kind": "base",
"name": "unsigned int"
}
}
},
"kind": "struct",
"size": 48
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,334 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 8
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"Path": {
"offset": 8,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"LastModified": {
"offset": 16,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"InsertFlags": {
"offset": 24,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"ShimFlags": {
"offset": 28,
"type": {
"kind": "base",
"name": "unsigned int"
}
}
},
"kind": "struct",
"size": 36
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,371 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 16
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 24
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 25
}
},
"kind": "struct",
"size": 32
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 32
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 40
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 44
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 48
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 56
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 64
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 72
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 80
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 88
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 96
}
},
"kind": "struct",
"size": 104
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 16
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"u1": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"Path": {
"offset": 24,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"ListEntryDetail": {
"offset": 40,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "SHIM_CACHE_ENTRY_DETAIL"
}
}
}
},
"kind": "struct",
"size": 48
},
"SHIM_CACHE_ENTRY_DETAIL": {
"fields": {
"u1": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"LastModified": {
"offset": 8,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"BlobSize": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"u2": {
"offset": 20,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"BlobBuffer": {
"offset": 24,
"type": {
"kind": "base",
"name": "unsigned long long"
}
}
},
"kind": "struct",
"size": 32
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,371 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 4
}
},
"kind": "struct",
"size": 8
},
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"u1": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"Path": {
"offset": 12,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"ListEntryDetail": {
"offset": 20,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "SHIM_CACHE_ENTRY_DETAIL"
}
}
}
},
"kind": "struct",
"size": 24
},
"SHIM_CACHE_ENTRY_DETAIL": {
"fields": {
"u1": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"InsertFlags": {
"offset": 4,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"LastModified": {
"offset": 8,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"BlobSize": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"BlobBuffer": {
"offset": 20,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 24
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,348 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 16
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 24
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 25
}
},
"kind": "struct",
"size": 32
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 32
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 40
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 44
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 48
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 56
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 64
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 72
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 80
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 88
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 96
}
},
"kind": "struct",
"size": 104
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 8
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"Path": {
"offset": 16,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"LastModified": {
"offset": 32,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"InsertFlags": {
"offset": 40,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"ShimFlags": {
"offset": 44,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"BlobSize": {
"offset": 48,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"BlobBuffer": {
"offset": 56,
"type": {
"kind": "base",
"name": "unsigned long long"
}
}
},
"kind": "struct",
"size": 64
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,348 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 4
}
},
"kind": "struct",
"size": 8
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"Path": {
"offset": 8,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"LastModified": {
"offset": 16,
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
}
},
"InsertFlags": {
"offset": 24,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"ShimFlags": {
"offset": 28,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"BlobSize": {
"offset": 32,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"BlobBuffer": {
"offset": 36,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 40
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,392 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 16
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 24
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 25
}
},
"kind": "struct",
"size": 32
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 32
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 40
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 44
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 48
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 56
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 64
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 72
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 80
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 88
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 96
}
},
"kind": "struct",
"size": 104
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 8
}
},
"kind": "struct",
"size": 8
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"u1": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"Path": {
"offset": 24,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"u2": {
"offset": 40,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"u3": {
"offset": 48,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"ListEntryDetail": {
"offset": 56,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "SHIM_CACHE_ENTRY_DETAIL"
}
}
}
},
"kind": "struct",
"size": 64
},
"SHIM_CACHE_ENTRY_DETAIL": {
"fields": {
"LastModified": {
"offset": 0,
"type": {
"kind": "struct",
"name": "_LARGE_INTEGER"
}
},
"InsertFlags": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"ShimFlags": {
"offset": 12,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"BlobSize": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"Padding": {
"offset": 24,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"BlobBuffer": {
"offset": 32,
"type": {
"kind": "base",
"name": "unsigned long long"
}
}
},
"kind": "struct",
"size": 40
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,386 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 4
}
},
"kind": "struct",
"size": 8
},
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_ENTRY": {
"fields": {
"ListEntry": {
"offset": 0,
"type": {
"kind": "struct",
"name": "nt_symbols!_LIST_ENTRY"
}
},
"u1": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"u2": {
"offset": 12,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"Path": {
"offset": 16,
"type": {
"kind": "struct",
"name": "nt_symbols!_UNICODE_STRING"
}
},
"u3": {
"offset": 24,
"type": {
"kind": "base",
"name": "unsigned long long"
}
},
"ListEntryDetail": {
"offset": 32,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "SHIM_CACHE_ENTRY_DETAIL"
}
}
}
},
"kind": "struct",
"size": 36
},
"SHIM_CACHE_ENTRY_DETAIL": {
"fields": {
"LastModified": {
"offset": 0,
"type": {
"kind": "struct",
"name": "_LARGE_INTEGER"
}
},
"InsertFlags": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned int"
}
},
"ShimFlags": {
"offset": 12,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"BlobSize": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"BlobBuffer": {
"offset": 20,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 24
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,485 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 4
}
},
"kind": "struct",
"size": 8
},
"SHIM_CACHE_HEADER": {
"fields": {
"Magic": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 0
},
"u1": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 4
},
"NumEntries": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 8
},
"u2": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 12
}
},
"kind": "struct",
"size": 400
},
"SHIM_CACHE_ENTRY": {
"fields": {
"Path": {
"type": {
"count": 520,
"kind": "array",
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 0
},
"LastModified": {
"type": {
"kind": "union",
"name": "LARGE_INTEGER"
},
"offset": 4
},
"FileSize": {
"type": {
"kind": "base",
"name": "long long"
},
"offset": 8
},
"LastUpdate": {
"type": {
"kind": "union",
"name": "LARGE_INTEGER"
},
"offset": 12
}
},
"kind": "struct",
"size": 552
},
"_SEGMENT": {
"fields": {
"ControlArea": {
"offset": 0,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_CONTROL_AREA"
}
}
},
"TotalNumberOfPtes": {
"offset": 4,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"NonExtendedPtes": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"WritableUserReferences": {
"offset": 12,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"SizeOfSegment": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"SegmentPteTemplate": {
"offset": 24,
"type": {
"kind": "struct",
"name": "nt_symbols!_MMPTE"
}
},
"NumberOfCommittedPages": {
"offset": 28,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"ExtendInfo": {
"offset": 32,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_MMEXTEND_INFO"
}
}
},
"SystemImageBase": {
"offset": 36,
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
}
},
"BasedAddress": {
"offset": 40,
"type": {
"kind": "base",
"name": "long"
}
},
"u1": {
"offset": 44,
"type": {
"kind": "base",
"name": "long"
}
},
"u2": {
"offset": 48,
"type": {
"kind": "base",
"name": "long"
}
},
"PrototypePte": {
"offset": 52,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_MMPTE"
}
}
},
"ThePtes": {
"offset": 60,
"type": {
"kind": "array",
"count": 1,
"subtype": {
"kind": "base",
"name": "nt_symbols!_MMPTE"
}
}
}
},
"kind": "struct",
"size": 64
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -0,0 +1,485 @@
{
"symbols": {},
"enums": {},
"base_types": {
"unsigned long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned long long": {
"kind": "int",
"size": 8,
"signed": false,
"endian": "little"
},
"unsigned char": {
"kind": "char",
"size": 1,
"signed": false,
"endian": "little"
},
"pointer": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned int": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
},
"unsigned short": {
"kind": "int",
"size": 2,
"signed": false,
"endian": "little"
},
"long": {
"kind": "int",
"size": 4,
"signed": false,
"endian": "little"
}
},
"user_types": {
"_LARGE_INTEGER": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"QuadPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "long long"
}
},
"u": {
"offset": 0,
"type": {
"kind": "struct",
"name": "__unnamed_2"
}
}
},
"kind": "union",
"size": 8
},
"__unnamed_2": {
"fields": {
"HighPart": {
"offset": 4,
"type": {
"kind": "base",
"name": "long"
}
},
"LowPart": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 8
},
"_RTL_BALANCED_LINKS": {
"fields": {
"Parent": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 0
},
"LeftChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 4
},
"RightChild": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 8
},
"Balance": {
"type": {
"kind": "base",
"name": "unsigned char"
},
"offset": 12
},
"Reserved": {
"type": {
"kind": "array",
"count": 3,
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 12
}
},
"kind": "struct",
"size": 16
},
"_RTL_AVL_TABLE": {
"fields": {
"BalancedRoot": {
"type": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
},
"offset": 0
},
"OrderedPointer": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 16
},
"WhichOrderedElement": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 20
},
"NumberGenericTableElements": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 24
},
"DepthOfTree": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 28
},
"RestartKey": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_BALANCED_LINKS"
}
},
"offset": 32
},
"DeleteCount": {
"type": {
"kind": "base",
"name": "unsigned long"
},
"offset": 36
},
"CompareRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 40
},
"AllocateRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 44
},
"FreeRoutine": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 48
},
"TableContext": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
},
"offset": 52
}
},
"kind": "struct",
"size": 56
},
"SHIM_CACHE_HEADER": {
"fields": {
"Magic": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 0
},
"u1": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 4
},
"NumEntries": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 8
},
"u2": {
"type": {
"kind": "base",
"name": "unsigned int"
},
"offset": 12
}
},
"kind": "struct",
"size": 400
},
"SHIM_CACHE_ENTRY": {
"fields": {
"Path": {
"type": {
"count": 520,
"kind": "array",
"subtype": {
"kind": "base",
"name": "unsigned char"
}
},
"offset": 0
},
"LastModified": {
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
},
"offset": 528
},
"FileSize": {
"type": {
"kind": "base",
"name": "long long"
},
"offset": 536
},
"LastUpdate": {
"type": {
"kind": "union",
"name": "_LARGE_INTEGER"
},
"offset": 544
}
},
"kind": "struct",
"size": 552
},
"SHIM_CACHE_HANDLE": {
"fields": {
"eresource": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!ERESOURCE"
}
},
"offset": 0
},
"rtl_avl_table": {
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "_RTL_AVL_TABLE"
}
},
"offset": 4
}
},
"kind": "struct",
"size": 8
},
"_SEGMENT": {
"fields": {
"ControlArea": {
"offset": 0,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_CONTROL_AREA"
}
}
},
"TotalNumberOfPtes": {
"offset": 4,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"NonExtendedPtes": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"WritableUserReferences": {
"offset": 12,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"SizeOfSegment": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"SegmentPteTemplate": {
"offset": 24,
"type": {
"kind": "struct",
"name": "nt_symbols!_MMPTE"
}
},
"NumberOfCommittedPages": {
"offset": 32,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"ExtendInfo": {
"offset": 36,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_MMEXTEND_INFO"
}
}
},
"SystemImageBase": {
"offset": 40,
"type": {
"kind": "pointer",
"subtype": {
"kind": "base",
"name": "void"
}
}
},
"BasedAddress": {
"offset": 44,
"type": {
"kind": "base",
"name": "long"
}
},
"u1": {
"offset": 48,
"type": {
"kind": "base",
"name": "long"
}
},
"u2": {
"offset": 52,
"type": {
"kind": "base",
"name": "long"
}
},
"PrototypePte": {
"offset": 56,
"type": {
"kind": "pointer",
"subtype": {
"kind": "struct",
"name": "nt_symbols!_MMPTE"
}
}
},
"ThePtes": {
"offset": 64,
"type": {
"kind": "array",
"count": 1,
"subtype": {
"kind": "base",
"name": "nt_symbols!_MMPTE"
}
}
}
},
"kind": "struct",
"size": 72
}
},
"metadata": {
"producer": {
"version": "0.0.1",
"name": "dgmcdona by hand",
"datetime": "2024-07-05T18:28:00.000000+00:00"
},
"format": "4.0.0"
}
}
@@ -114,6 +114,24 @@ is_windows_xp = OsDistinguisher(
],
)
is_windows_xp_sp2 = OsDistinguisher(
version_check=lambda x: (5, 1) <= x < (5, 2),
fallback_checks=[
("KdCopyDataBlock", None, False),
("_MMFREE_POOL_ENTRY", None, False),
("_HANDLE_TABLE", "HandleCount", True),
],
)
is_windows_xp_sp3 = OsDistinguisher(
version_check=lambda x: (5, 1) <= x < (5, 2),
fallback_checks=[
("KdCopyDataBlock", None, False),
("_MMFREE_POOL_ENTRY", None, True),
("_HANDLE_TABLE", "HandleCount", True),
],
)
is_xp_or_2003 = OsDistinguisher(
version_check=lambda x: (5, 1) <= x < (6, 0),
fallback_checks=[
@@ -122,6 +140,15 @@ is_xp_or_2003 = OsDistinguisher(
],
)
is_2003 = OsDistinguisher(
version_check=lambda x: (5, 2) <= x < (5, 3),
fallback_checks=[
("KdCopyDataBlock", None, False),
("_HANDLE_TABLE", "HandleCount", True),
("_MM_AVL_TABLE", None, True),
],
)
is_win10_up_to_15063 = OsDistinguisher(
version_check=lambda x: (10, 0) <= x < (10, 0, 15063),
fallback_checks=[
@@ -141,6 +168,15 @@ is_win10_15063 = OsDistinguisher(
],
)
is_win10_15063_or_later = OsDistinguisher(
version_check=lambda x: x >= (10, 0, 15063),
fallback_checks=[
("ObHeaderCookie", None, True),
("_HANDLE_TABLE", "HandleCount", False),
("_EPROCESS", "KeepAliveCounter", False),
],
)
is_win10_16299_or_later = OsDistinguisher(
version_check=lambda x: x >= (10, 0, 16299),
fallback_checks=[