Registry Callbacks
Kernel-mode callback mechanism for monitoring and intercepting registry operations.
Attack Surface Overview
- Callback registration: Drivers register via
CmRegisterCallbackExto receive notifications for all registry operations - Operation types: Pre-operation (can block/modify) and post-operation callbacks
- Altitude-based ordering: Callbacks execute in order of registration altitude (like minifilter altitudes)
- Callback context: Driver-defined context pointer passed to every invocation
- User-reachable via: Any registry operation from user mode (
RegCreateKeyEx,RegSetValueEx,RegQueryValueEx,NtSetValueKey, etc.)
Mechanism Deep-Dive
Registry callbacks intercept operations at the Configuration Manager (Cm) level. When user-mode code performs any registry operation, the following sequence occurs:
- The I/O manager routes the request to the Configuration Manager
- Cm invokes each registered callback with a
REG_NOTIFY_CLASSvalue indicating the operation type (e.g.,RegNtPreCreateKeyEx,RegNtPreSetValueKey) - Pre-operation callbacks can inspect and modify arguments, or return
STATUS_CALLBACK_BYPASSto block the operation entirely - The actual registry operation executes within the Configuration Manager
- Post-operation callbacks receive the result and can perform logging, auditing, or cleanup
Key APIs:
CmRegisterCallbackEx-- Register a callback routine with an altitude string that determines invocation orderCmUnRegisterCallback-- Deregister a previously registered callback using the cookie returned at registrationREG_CREATE_KEY_INFORMATION-- Structure passed to callbacks for key creation events, containing the key path, desired access, and creation optionsREG_SET_VALUE_KEY_INFORMATION-- Structure passed for value write events, containing the value name, type, data pointer, and data length
Common Vulnerability Patterns
-
Insufficient input validation: The callback receives untrusted
ValueName,Data, andDataSizefields from user mode. Failure to validate these parameters before copying or processing leads to buffer overflows or integer overflow conditions. -
TOCTOU on registry data: A callback reads value data from user-mode memory, but a concurrent user-mode thread modifies the data between the validation check and the point where the driver acts on it. This is especially common when callbacks reference the caller's buffer directly instead of capturing a local copy.
-
Pool corruption in callback context: Drivers that allocate per-key tracking context in their callbacks may not properly handle callback re-entrancy. A registry operation on a key triggers a callback, which itself performs a registry operation, causing recursive callback invocation that corrupts or double-frees context structures.
-
Missing altitude conflicts: Multiple drivers registering callbacks at the same or adjacent altitudes can create race conditions where callback execution order is non-deterministic, leading to inconsistent state when both modify the same operation.
-
Unregistration races: Calling
CmUnRegisterCallbackwhile callbacks are actively executing on other processors leads to use-after-free of the callback context. The Configuration Manager's callback list removal does not fully synchronize with in-flight callback invocations on all CPUs.
Related CVEs
| CVE | Driver | Description |
|---|---|---|
| CVE-2024-21338 | appid.sys |
AppLocker driver callback vulnerability, exploited by Lazarus Group for kernel code execution |
| CVE-2023-36424 | cldflt.sys |
Cloud Files minifilter registry callback issue leading to elevation of privilege |
AutoPiff Detection
AutoPiff identifies registry callback-related vulnerabilities through the following detection rules:
callback_input_validation_added-- New size or type checks on callback parameters, indicating previously missing input validationcallback_context_lifetime_fix-- Reference counting changes for callback context objects, suggesting a use-after-free or double-free fixcm_callback_lock_change-- Synchronization changes around callback registration or invocation, pointing to race condition fixesregistry_access_mask_hardened-- Registry key access mask reduced to least-privilegedouble_fetch_to_capture_fix-- TOCTOU fixed by capturing value data into a kernel buffer before processing