Windows Undocumented Features: Breakpoints for Registry Keys
For the first time, breakpoints for registry keys appeared in Windows XP, where the kernel realized the ability to execute int 3 instructions when opening a registry key with a mark (debug flag)
BREAK_ON_OPENor when creating a subkey as part of such a key. 
Fig. 1: Fragment of the CmpDoOpen
function This functionality appeared in the kernel even before the release of any service packs, and it was not required to install the debug ("checked") version of the kernel. However, the API functions for setting the flag
BREAK_ON_OPENwas not, and therefore this flag could be set at the key only by editing the file with the registry hive in the HEX editor. Starting with Windows Vista, the list of available debugging flags was expanded, it became possible to set these flags through the NtSetInformationKey API function, however, the functionality itself remained only in debugging versions of the kernel (which can be taken from the Windows Driver Kit).
Tab. 1: Possible values of the debug flag
| Flag | Value | Note |
|---|---|---|
| BREAK_ON_OPEN | 0x01 | Key opening |
| BREAK_ON_DELETE | 0x02 | Key Removal |
| BREAK_ON_SECURITY_CHANGE | 0x04 | Security Descriptor Change |
| BREAK_ON_CREATE_SUBKEY | 0x08 | Create subkey |
| BREAK_ON_DELETE_SUBKEY | 0x10 | Delete subkey |
| BREAK_ON_SET_VALUE | 0x20 | Setting value |
| BREAK_ON_DELETE_VALUE | 0x40 | Delete value |
| BREAK_ON_KEY_VIRTUALIZE | 0x80 | Key Virtualization |
To set the debug flag, you must call the NtSetInformationKey function, passing it the handle of the registry key as the first argument for which you want to set the debug flag. The second argument is KeySetDebugInformation, and the last two arguments must describe a buffer containing a double word (DWORD), which contains the value of the debug flag (or a combination of two or more flags).
To activate the discussed breakpoints, it is necessary to set the value of the CmpRegDebugBreakEnabled kernel variable to one.
Example
As an example, let’s try to catch the moment the value is written to the registry key “
HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices”, where information about the mounted volumes is stored, and determine the Windows component that writes data there. To do this, mark the specified key with the debug flag BREAK_ON_SET_VALUE, enable breakpoints by changing the value of the CmpRegDebugBreakEnabled variable to one, and format the test disk, which we will then mount. As a result, the breakpoint is triggered, the following call stack is visible:
# Child-SP RetAddr Call Site
00 ffffd000`79b851a0 fffff803`7ccf88fa nt!CmSetValueKey+0x158
01 ffffd000`79b852b0 fffff803`7c69eac3 nt!NtSetValueKey+0x73e
02 ffffd000`79b85470 fffff803`7c697e40 nt!KiSystemServiceCopyEnd+0x13
03 ffffd000`79b85678 fffff803`7d08f11e nt!KiServiceLinkage
04 ffffd000`79b85680 fffff801`46d6fcaa nt!RtlWriteRegistryValue+0x9e
05 ffffd000`79b856f0 fffff801`46d6b58c mountmgr+0xecaa
06 ffffd000`79b85820 fffff803`7cd9cd78 mountmgr+0xa58c
07 ffffd000`79b85850 fffff803`7cd9bdd5 nt!PnpNotifyDriverCallback+0x1b8
08 ffffd000`79b85900 fffff803`7cdd6755 nt!PnpNotifyDeviceClassChange+0x2f9
09 ffffd000`79b859d0 fffff803`7c66dcb7 nt!PnpDeviceEventWorker+0x4c1
0a ffffd000`79b85b50 fffff803`7c5e7071 nt!ExpWorkerThread+0x177
0b ffffd000`79b85be0 fffff803`7c699836 nt!PspSystemThreadStartup+0x23d
0c ffffd000`79b85c60 00000000`00000000 nt!KiStartSystemThread+0x16The call stack clearly shows that the record initiates the mountmgr component, in its code you can find the required nt! RtlWriteRegistryValue call:
fffff801`46d6fca4 ff15fe44ffff call qword ptr [mountmgr+0x31a8 (fffff801`46d641a8)] // вызов nt!RtlWriteRegistryValue
fffff801`46d6fcaa 488d55b7 lea rdx,[rbp-49h]conclusions
The described functionality can be used both for solving tasks directly related to debugging the kernel and drivers, and for solving third-party tasks, for example, searching for programs in the system image under study that use the specified registry key.