Windows 注册表 Hive 利用 原语

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

为什么 hive 损坏很特殊

Windows registry hives 是由自定义分配器 (HvAllocateCell, HvReallocateCell, HvFreeCell) 管理的内存映射 .regf 文件。该分配器:

  • 不随机化分配 – cell 的放置仅取决于先前 registry API 调用的顺序/大小,因此布局在不同主机上是可重现的。
  • 缺乏完整性检查 – 手动修改的 header/data 字段会被内核消费者(Cmp* routines)和注册表进程自身信任。
  • 与特权 hive 共享地址空间 – 在许多情况下,攻击者控制的 hive 会映射到与 HKLM/HKU hive 相同的 user-mode 地址范围,从而能触发跨 hive 的溢出。

这使得基于 hive 的内存损坏漏洞(例如 CVE-2023-23420 / CVE-2023-23423)在 LPE 场景下特别可靠。

使用 registry APIs 进行确定性布局整理

因为 hive 分配是确定性的,你可以纯粹通过 Win32 APIs 来整理 cell 放置。一个典型工作流程是:

  1. 重置目标键(删除/重建),使 hive bin 仅包含已知的 cells。
  2. 通过创建具有精心选择大小的值来分配可预测的 cell 连续段
  • Key/value 元数据 cell 是 8 字节的倍数。
  • 写入 0x3FD8 字节的值会强制创建一个新的 0x4000 字节 bin(0x3FD8 数据 + _HBIN header/填充),便于后续交错 bins。
  1. 使用易于调整大小的类型(例如 REG_BINARY),这样你可以仅通过使用不同长度调用 RegSetValueEx 来释放/扩展单个 cell。
  2. 记录操作序列(create/delete/resize)。重放该序列会在其他系统上重现相同布局,因为分配器没有随机性。
示例布局整形器(简化的 C) ```c void MakeBin(HKEY base, const wchar_t *name, size_t bytes) { std::vector buf(bytes, 0x41); RegSetKeyValueW(base, NULL, name, REG_BINARY, buf.data(), (DWORD)buf.size()); }

void Groom(HKEY hive) { for (int i = 0; i < 0x20; ++i) { wchar_t value[32]; swprintf(value, L“bin_%02d“, i); MakeBin(hive, value, 0x3FD8); RegDeleteKeyValueW(hive, NULL, value); // leaves holes for victim cells } }

</details>

## 通过错误配置的后代实现对特权 hive 的仅 API 访问

Windows 只会评估注册表路径的 **最终组件上的 ACL**。如果 HKLM/HKU 下的任一后代项向低权限用户授予 `KEY_SET_VALUE`、`KEY_CREATE_SUB_KEY` 或 `WRITE_DAC`,即使所有父项都被锁定,你仍然可以访问它。Project Zero 在 Windows 11 的 HKLM 中发现了 **>1000 个这样的可写键**,包括长期存在的条目如 `HKLM\SOFTWARE\Microsoft\DRM` 和若干 `HKLM\SYSTEM` 分支。

实用的枚举策略:

1. 从提权的上下文,遍历 `\Registry\Machine` 和 `\Registry\User`,导出每个键的安全描述符。保存那些 DACL 允许非特权 SID 的项。
2. 作为普通用户,针对记录的路径尝试用 `RegOpenKeyEx` 请求 `KEY_SET_VALUE|KEY_CREATE_SUB_KEY`。打开成功的路径是可行目标,适用于需要攻击者可控数据写入系统 hive 的损坏漏洞。
3. 维护一份指向 **稳定可写位置** 的打开句柄缓存,以便 PoC 能直接部署损坏的元数据。
```powershell
$targets = Get-ChildItem Registry::HKEY_LOCAL_MACHINE -Recurse |
Where-Object { (Get-Acl $_.PsPath).Access.IdentityReference -match 'S-1-5-32-545' } |
Select-Object -ExpandProperty PsPath

foreach ($path in $targets) {
try { Get-Item -Path $path -ErrorAction Stop | Out-Null }
catch {}
}

一旦路径已知,利用时就不需要离线 hive 篡改——标准 registry APIs 就足够 在由 SYSTEM 服务触及的特权 hive 中布置损坏的 cells。

Cross-user hive abuse via HKCU\Software\Microsoft\Input\TypingInsights

每个用户 hive 都包含 HKCU\Software\Microsoft\Input\TypingInsights,其 ACL 授予 KEY_ALL_ACCESSEveryone (S-1-1-0). 在 Microsoft 采取收紧措施之前,任意用户可以:

  • 将另一个用户的 hive 填满 直到 2 GiB 限制,导致登录失败或强制 hive 截断(可用于强制分配器行为或 DoS)。
  • 向其他用户的 NTUSER.DAT 投放损坏的 cells,为横向利用做准备,当受害进程读取被破坏的键时触发。
  • 修改差异 hive(differencing hives),针对依赖于每用户 overlay hives 的沙箱应用,迫使它们使用恶意元数据。

这使得 hive 损坏漏洞适用于 lateral movement,不仅限于同一账户内的权限提升。

Turning metadata corruption into paged pool overflows

Large registry values are stored in _CM_BIG_DATA records:

  • _CM_KEY_VALUE.DataLength 保存逻辑大小。其高位表示 payload 是在 cell 内还是在 big-data 存储中。
  • _CM_BIG_DATA.Count 计数通过 chunk table 引用的 16 KiB chunk(16384 字节减去元数据)。

当任何组件调用 CmpGetValueData 时:

  1. 内核按 DataLength 严格分配一个 paged pool buffer
  2. 它从 hive 存储复制 Count * 0x4000 字节到该缓冲区。

如果你能破坏 cell 使 DataLength < 16344 * (Count - 1),复制会线性地越界写入相邻的 paged-pool 对象。一个可靠的 exploit 链是:

  1. 使用确定性的 groom 将易受攻击的 _CM_KEY_VALUE 放置在可控元数据附近。
  2. DataLength 翻小(例如 0x100),同时保持 _CM_BIG_DATA.Count 不变。
  3. 从用户态进行 pool-groom(pipes、ALPC ports、section objects),使选定对象(如 EPROCESS->Token 所在者或 SRVNET_BUFFER)在步骤 1 的分配之后占据下一个 chunk。
  4. 触发读取(例如 RegQueryValueExNtQueryValueKey),使 CmpGetValueData 复制所有 chunk 并用来自 hive 的攻击者控制数据覆盖邻居的字段
  5. 利用被破坏的内核对象转向任意读/写或直接窃取 SYSTEM token。

由于 overflow 长度等于 (Count * 0x4000) - DataLength,你获得了一个精确的字节预算并对写入的字节拥有完全控制,优于许多基于驱动的 pool overflow。

Inter-hive linear overflows via tightly packed HBINs

Hives mounted by the Registry process are mapped in 2 MiB-aligned views with no guard gaps。你可以强制两个不同的 hive 同步增长,直到它们的 _HBIN 区域接触:

  1. 选择一个可由攻击者写入的 hive(app hive 或 user hive)和一个特权目标(例如 HKLM\SOFTWARE)。
  2. 在两个 hive 中持续创建/删除 0x3FD8 字节的值。每次分配会添加一个 0x4000 字节的 bin,所以并行运行两个写入者会在虚拟内存中交错它们的 bins(可使用 !process Registry + !vad 观察到)。
  3. 一旦攻击者 hive 的最后一个 bin 紧邻属于 HKLM 的 HBIN,使用 hive 损坏 bug 从攻击者 hive 溢出,破坏 HKLM 内的 HBIN 头或 cells。
  4. 在控制了 HKLM 元数据后你可以:
  • 在特权 hive 中直接部署 big-data 不一致原语。
  • 在数据离开内核之前破坏被 SYSTEM 服务消费的配置数据。

由于缺少 guard pages,来自非特权 hive 的线性覆盖可以直接破坏 SYSTEM 拥有的 hive 结构,从而在 HKLM/HKU 内实现仅数据的攻击或设置上文所述的 pool overflow。

Operational tips

  • 使用 !vad(用户态)和 !reg view / !pool(内核)监视 hive 的布局,确认在触发 overflow 前已相邻。
  • 缓存枚举期间发现的可写 HKLM 路径,以便在重启后也能迅速部署损坏原语。
  • 将 hive grooming 与标准的 pool feng shui(pipe pair freelists、NtAllocateVirtualMemoryRegistry process 上)结合,以稳定溢出后的原语。

References

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks