Registry Callbacks
Ring 0Enumerate, remove, and restore registry notification callbacks registered via CmRegisterCallbackEx.
Security Research Only
Overview
Registry callbacks allow kernel drivers to monitor and intercept registry operations. EDR/AV products use these to detect malicious registry modifications. DioProcess can enumerate these callbacks and optionally remove/restore them.
RegistryCallbackInfo Structure
pub struct RegistryCallbackInfo {
pub index: u32, // Callback slot index
pub callback_address: u64, // Callback function address
pub cookie: u64, // Registration cookie (for unregister)
pub altitude: String, // Callback altitude (priority string)
pub module_name: String, // Driver module name
}
// Registry operations monitored by callbacks
pub enum RegNotifyClass {
RegNtPreDeleteKey,
RegNtPreSetValueKey,
RegNtPreDeleteValueKey,
RegNtPreSetInformationKey,
RegNtPreRenameKey,
RegNtPreEnumerateKey,
RegNtPreEnumerateValueKey,
RegNtPreQueryKey,
RegNtPreQueryValueKey,
RegNtPreCreateKey,
RegNtPreCreateKeyEx,
RegNtPostCreateKey,
RegNtPostCreateKeyEx,
// ... 30+ operation types
}Implementation
// Enumeration: Walk the CmCallbackListHead linked list
NTSTATUS EnumerateRegistryCallbacks(PREG_CALLBACK_INFO* Callbacks, PULONG Count) {
// 1. Find CmCallbackListHead via signature scanning in CM (Configuration Manager)
PLIST_ENTRY CallbackListHead = FindCmCallbackListHead();
// 2. Walk the doubly-linked list
PLIST_ENTRY Entry = CallbackListHead->Flink;
while (Entry != CallbackListHead) {
// 3. Get the callback registration structure
PCM_CALLBACK_CONTEXT_BLOCK Context = CONTAINING_RECORD(
Entry,
CM_CALLBACK_CONTEXT_BLOCK,
CallbackListEntry
);
Info->Index = Index++;
Info->CallbackAddress = (ULONG64)Context->Function;
Info->Cookie = (ULONG64)Context->Cookie;
Info->Altitude = Context->Altitude.Buffer;
Info->ModuleName = GetModuleFromAddress(Context->Function);
Entry = Entry->Flink;
}
return STATUS_SUCCESS;
}
// Remove: Unlink from list, save for restore
NTSTATUS RemoveRegistryCallback(ULONG Index) {
// Find callback by index
// Save original Flink/Blink
// Unlink from list: Prev->Flink = Entry->Flink; Next->Blink = Entry->Blink
return STATUS_SUCCESS;
}
// Restore: Re-link saved entry
NTSTATUS RestoreRegistryCallback(ULONG Index) {
// Use saved Flink/Blink to reinsert at original position
return STATUS_SUCCESS;
}IOCTLs
| IOCTL | Code | Description |
|---|---|---|
| ENUM_REGISTRY_CALLBACKS | 0x0022204C | Enumerate all registry callbacks |
| REMOVE_REGISTRY_CALLBACK | 0x00222050 | Remove callback by index |
| RESTORE_REGISTRY_CALLBACK | 0x00222054 | Restore previously removed callback |
Altitude System
Like minifilters, registry callbacks use an altitude string to determine call order. Higher altitudes are called first (see the callback before lower-altitude callbacks).
Example altitudes:
"389000" (high priority, security product)
"320000" (medium priority, AV)
"200000" (lower priority, monitoring)
UI Features
Registry callbacks are displayed in the Callback Enumeration tab alongside process, thread, image, and object callbacks:
- • Callback table — Index, Callback Address, Altitude, Module
- • Sorting — By altitude (descending) or module name
- • Search filter — Filter by module name or altitude
- • Context menu — Copy Address, Remove Callback, Restore Callback
- • Remove status — Visual indicator for removed callbacks
Registry Operations Monitored
Callbacks receive notifications for these registry operations:
Key Operations
- • CreateKey / CreateKeyEx
- • OpenKey / OpenKeyEx
- • DeleteKey
- • RenameKey
- • EnumerateKey
- • QueryKey
Value Operations
- • SetValueKey
- • DeleteValueKey
- • QueryValueKey
- • EnumerateValueKey
- • QueryMultipleValueKey
Use Cases
- • Identify which drivers are monitoring registry activity
- • Temporarily disable registry monitoring for research
- • Analyze how security products use registry callbacks
- • Test registry-based persistence detection
- • Forensic analysis of active registry monitors
Related Topics
- • Callback Enumeration — Process, thread, image callbacks
- • System Events — Real-time registry event capture