windows-registry-hive-exploitation.md (9291B)
1 --- 2 title: "Windows Registry Hive Exploitation Primitives" 3 section: "Windows" 4 sectionSlug: "windows-hardening" 5 sourcePath: "src/windows-hardening/windows-local-privilege-escalation/windows-registry-hive-exploitation.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/windows-local-privilege-escalation/windows-registry-hive-exploitation.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Windows Registry Hive Exploitation Primitives 14 15 ## Why hive corruption is special 16 17 Windows registry hives are **memory-mapped `.regf` files** managed by a custom allocator (`HvAllocateCell`, `HvReallocateCell`, `HvFreeCell`). The allocator: 18 19 - **Does not randomize allocations** – cell placement depends only on the order/size of prior registry API calls, so layouts are reproducible across hosts. 20 - **Lacks integrity checks** – manually altered header/data fields are trusted by kernel consumers (`Cmp*` routines) and by the Registry process itself. 21 - **Shares address space with privileged hives** – in many cases attacker-controlled hives are mapped into the same user-mode address range as HKLM/HKU hives, enabling inter-hive overflows. 22 23 This makes hive-based memory corruption bugs (e.g., CVE-2023-23420 / CVE-2023-23423) uniquely reliable for LPE.<sup>[[1]](#references)</sup> 24 25 ## Deterministic layout grooming with registry APIs 26 27 Because hive allocation is deterministic, you can groom cell placement purely via Win32 APIs. A typical workflow is:<sup>[[1]](#references)</sup> 28 29 1. **Reset the target key** (delete/recreate) so the hive bin contains only known cells. 30 2. **Allocate predictable runs of cells** by creating values with carefully selected sizes: 31 - Key/value metadata cells are multiples of 8 bytes. 32 - Writing `0x3FD8`-byte values forces a fresh `0x4000`-byte bin (`0x3FD8` data + `_HBIN` header/padding), ideal for interleaving bins later. 33 3. **Use resize-friendly types** (e.g., `REG_BINARY`) so you can free/extend individual cells just by calling `RegSetValueEx` with different lengths. 34 4. **Record the sequence** of operations (create/delete/resize). Replaying it reproduces the same layout on other systems because the allocator has no randomness. 35 36 <details> 37 <summary>Example layout shaper (simplified C)</summary> 38 39 ```c 40 void MakeBin(HKEY base, const wchar_t *name, size_t bytes) { 41 std::vector<uint8_t> buf(bytes, 0x41); 42 RegSetKeyValueW(base, NULL, name, REG_BINARY, buf.data(), (DWORD)buf.size()); 43 } 44 45 void Groom(HKEY hive) { 46 for (int i = 0; i < 0x20; ++i) { 47 wchar_t value[32]; 48 swprintf(value, L"bin_%02d", i); 49 MakeBin(hive, value, 0x3FD8); 50 RegDeleteKeyValueW(hive, NULL, value); // leaves holes for victim cells 51 } 52 } 53 ``` 54 55 </details> 56 57 Once a corruption primitive (overwrite/fill) is available, the groom guarantees that the **target cell resides next to the sprayed holes**, enabling precise overwrites without heap spraying.<sup>[[1]](#references)</sup> 58 59 ## API-only access to privileged hives via misconfigured descendants 60 61 Windows only evaluates the **ACL on the final component** of a registry path. If any descendant under HKLM/HKU grants `KEY_SET_VALUE`, `KEY_CREATE_SUB_KEY`, or `WRITE_DAC` to low-privileged users, you can reach it even when every parent key is locked down. Project Zero found **>1000 such writable keys in HKLM on Windows 11**, including long-lived entries like `HKLM\SOFTWARE\Microsoft\DRM` and several `HKLM\SYSTEM` branches.<sup>[[1]](#references)</sup> 62 63 Practical enumeration strategy: 64 65 1. From an elevated context, walk `\Registry\Machine` and `\Registry\User`, dumping each key’s security descriptor. Store items whose DACL allows unprivileged SIDs. 66 2. As a normal user, attempt `RegOpenKeyEx` with `KEY_SET_VALUE|KEY_CREATE_SUB_KEY` against the recorded paths. Successful opens are viable targets for hive corruption bugs that require attacker-controlled data in system hives. 67 3. Maintain a cache of open handles to **stable writable locations** so PoCs can directly deploy corrupted metadata. 68 69 ```powershell 70 $targets = Get-ChildItem Registry::HKEY_LOCAL_MACHINE -Recurse | 71 Where-Object { (Get-Acl $_.PsPath).Access.IdentityReference -match 'S-1-5-32-545' } | 72 Select-Object -ExpandProperty PsPath 73 74 foreach ($path in $targets) { 75 try { Get-Item -Path $path -ErrorAction Stop | Out-Null } 76 catch {} 77 } 78 ``` 79 80 Once such a path is known, the exploit never needs offline hive tampering—**standard registry APIs are enough** to stage the corrupt cells inside privileged hives touched by SYSTEM services.<sup>[[1]](#references)</sup> 81 82 ## Cross-user hive abuse via `HKCU\Software\Microsoft\Input\TypingInsights` 83 84 Every user hive contains `HKCU\Software\Microsoft\Input\TypingInsights`, whose ACL grants `KEY_ALL_ACCESS` to **Everyone (S-1-1-0).** Until Microsoft tightens it, any user can:<sup>[[1]](#references)</sup> 85 86 - **Fill another user’s hive** up to the 2 GiB limit, causing logon failures or forcing hive truncation (useful to coerce allocator behavior or DoS). 87 - **Drop corrupted cells** into other users’ `NTUSER.DAT`, setting up lateral exploits that trigger when the victim process reads the compromised key. 88 - **Modify differencing hives** for sandboxed apps that rely on per-user overlay hives, forcing them to consume malicious metadata. 89 90 This makes hive corruption vulnerabilities applicable to **lateral movement**, not just elevation within the same account.<sup>[[1]](#references)</sup> 91 92 ## Turning metadata corruption into paged pool overflows 93 94 Large registry values are stored in `_CM_BIG_DATA` records:<sup>[[1]](#references)</sup> 95 96 - `_CM_KEY_VALUE.DataLength` holds the logical size. Its high bit indicates whether the payload lives inside the cell or in big-data storage. 97 - `_CM_BIG_DATA.Count` counts **16 KiB chunks** (16384 bytes minus metadata) referenced via a chunk table. 98 99 When any component calls `CmpGetValueData`:<sup>[[1]](#references)</sup> 100 101 1. The kernel allocates a **paged pool buffer** sized strictly from `DataLength`. 102 2. It copies `Count * 0x4000` bytes from hive storage into that buffer. 103 104 If you can corrupt the cell so `DataLength < 16344 * (Count - 1)`, the copy **overruns the destination linearly** into adjacent paged-pool objects. A reliable exploit chain is:<sup>[[1]](#references)</sup> 105 106 1. Use the deterministic groom to place the vulnerable `_CM_KEY_VALUE` near controllable metadata. 107 2. Flip `DataLength` to a small number (e.g., 0x100) while leaving `_CM_BIG_DATA.Count` intact. 108 3. Pool-groom from user mode (pipes, ALPC ports, section objects) so a chosen object (like `EPROCESS->Token` owner or `SRVNET_BUFFER`) occupies the next chunk after the allocation from step 1. 109 4. Trigger a read (e.g., `RegQueryValueEx`, `NtQueryValueKey`) so `CmpGetValueData` copies all chunks and **overwrites the neighbor’s fields** with attacker-controlled data from the hive. 110 5. Use the corrupted kernel object to pivot to arbitrary read/write or direct SYSTEM token theft. 111 112 Because the overflow length equals `(Count * 0x4000) - DataLength`, you get a **precise byte budget** and full control over the bytes written, outperforming many driver-based pool overflows.<sup>[[1]](#references)</sup> 113 114 ## Inter-hive linear overflows via tightly packed HBINs 115 116 Hives mounted by the Registry process are mapped in **2 MiB-aligned views** with **no guard gaps**. You can force two different hives to grow in lockstep until their `_HBIN` ranges touch:<sup>[[1]](#references)</sup> 117 118 1. Choose an attacker-writable hive (app hive or user hive) and a privileged target (e.g., `HKLM\SOFTWARE`). 119 2. Continuously create/delete `0x3FD8`-byte values in both hives. Each allocation adds a `0x4000`-byte bin, so running both writers in parallel interleaves their bins in virtual memory (observed with `!process Registry` + `!vad`). 120 3. Once the final bin of the attacker hive sits immediately before an HBIN belonging to HKLM, use the hive corruption bug to **overflow out of the attacker hive**, smashing HBIN headers or cells inside HKLM. 121 4. With HKLM metadata under control you can: 122 - Stage a big-data inconsistency primitive directly in the privileged hive. 123 - Corrupt configuration data consumed by SYSTEM services before it ever leaves the kernel. 124 125 The absence of guard pages means a linear overwrite from an unprivileged hive can **directly corrupt SYSTEM-owned hive structures**, enabling data-only attacks or setting up the pool overflow described above inside HKLM/HKU.<sup>[[1]](#references)</sup> 126 127 ## Operational tips 128 129 - Monitor hive placement with `!vad` (user-mode) and `!reg view` / `!pool` (kernel) to confirm adjacency before triggering the overflow.<sup>[[1]](#references)</sup> 130 - Cache writable HKLM paths discovered during enumeration so corruption primitives can be deployed quickly even after reboots. 131 - Combine hive grooming with standard pool feng shui (pipe-pair freelists and `NtAllocateVirtualMemory` in the Registry process) to stabilize post-overflow primitives. 132 133 ## References 134 135 - [1] [Project Zero – The Windows Registry Adventure #8: Practical exploitation of hive memory corruption](https://projectzero.google/2025/05/the-windows-registry-adventure-8-exploitation.html)