将 Windows 注册表 hive 文件解析为 DuckDB 中可 SQL 查询的强类型行,支持事务日志重放与已删除 cell 恢复,专用于集群规模 DFIR 证据分析。

# vgi-reghive
一个 [VGI](https://query.farm) worker,用于将 **Windows 注册表 hive 文件** —
即 `SYSTEM`、`SOFTWARE`、`NTUSER.DAT`、`SAM`、`SECURITY`、`UsrClass.dat`
和 `AmCache.hve` 使用的磁盘 `regf` 格式 — 解析为强类型的键/值行,供
**DFIR** 直接在基于 Apache Arrow 的 DuckDB 中使用。支持完整的键路径、值
名称/类型/数据(`REG_SZ`/`REG_DWORD`/`REG_BINARY`/`REG_MULTI_SZ`/`REG_QWORD`/…)、
每个键的最后写入时间戳、对脏 hive 的**事务日志(`.LOG1`/`.LOG2`)重放**,
以及从未分配空间中**恢复已删除的 cell**。纯离线计算在引擎内完成,
主机上无需 agent,无流量外发。
它是 Windows-DFIR 套件中 `vgi-evtx` 和 `vgi-mft` 的同胞组件 — 作为独立的
worker 存在,因为 `regf` 既不是 EVTX 的二进制 XML 格式,也不是
MFT/`$MFT` 的记录格式。
## 用途
成熟的免费 incumbent 工具(如 RegRipper、regipy、Eric
Zimmerman 的 Registry Explorer / RECmd)已经能很好地完成*解析*工作 — 我们
无意在“将 hive 转储为行”上竞争。我们的价值在于提供这些工具所不具备的
**集群规模、基于 SQL 的注册表筛选**:ATTACH 一个包含数千个收集到的 hive 的
目录,并运行**一次查询**,即可将注册表证据与安全环境的其余部分
(`vgi-ioc`/threat-intel、`vgi-cve`、`vgi-yara`、`vgi-sigma`、`vgi-secretscan`)
进行 JOIN 操作 — 无需在每台主机上单独调用 RegRipper,也无需费力整理结果。
## SQL 接口
```
INSTALL vgi FROM community;
LOAD vgi;
ATTACH 'reghive' AS reghive (TYPE vgi); -- spawns the worker binary
SET search_path = 'reghive.main';
-- 1. Read a directory of collected hives into key/value rows. read_hive()
-- auto-detects regf, walks the key tree, and (by default) applies sibling
-- .LOG1/.LOG2 transaction logs found next to each file.
SELECT key_path, value_name, value_type, value_data, key_last_write, is_deleted
FROM read_hive('/cases/4421/*/NTUSER.DAT')
WHERE key_path LIKE 'Software\Microsoft\Windows\CurrentVersion\Run%';
-- 2. Persistence triage: surface Run-keys across the fleet, joined to IOCs.
SELECT r.source, r.key_path, r.value_name, r.value_data, i.feed, i.category
FROM read_hive('/cases/4421/*/{NTUSER.DAT,SOFTWARE}') r
LEFT JOIN ioc.indicators i
ON i.kind = 'filepath' AND r.value_data ILIKE '%' || i.value || '%'
WHERE r.key_path LIKE '%CurrentVersion\Run%'
AND i.value IS NOT NULL;
-- 3. Surface deleted cells (recovered keys/values from unallocated space).
SELECT key_path, value_name, value_type, value_data, key_last_write, recovery
FROM read_hive('/cases/4421/*/SOFTWARE')
WHERE is_deleted; -- recovered-from-free-space evidence only
-- 4. Probe a hive header: is it dirty (does it need transaction-log recovery)?
SELECT (hive_info(content)).hive_type, (hive_info(content)).is_dirty
FROM read_blob('/cases/4421/host7/SYSTEM');
-- 5. Pull one subtree / one key (BLOB from read_blob, fed as a literal).
SELECT * FROM reghive.main.hive_subtree(unhex('...regf bytes...'), 'ControlSet001\Services');
SELECT reghive.main.hive_key(content, 'ControlSet001\Services\Schedule') AS svc
FROM read_blob('SYSTEM');
```
## 函数列表
| 函数 | 类型 | 返回值 |
|---|---|---|
| `read_hive(glob_or_blob [, apply_logs, recover_deleted, mode])` | table | §输出模式 中定义的行 |
| `hive_subtree(blob, key_path [, apply_logs, recover_deleted])` | table | 同上,但范围限定于某个子树 |
| `hive_key(blob, key_path)` | scalar | `STRUCT(key_path, last_write, class_name, subkey_count, value_count, is_deleted, values LIST
)` |
| `hive_value(blob, key_path, value_name)` | scalar | `STRUCT(value_type, value_data, value_raw)` — `value_name := ''`/`NULL` → 表示 (Default) 值 |
| `key_info(blob, key_path)` | scalar | `STRUCT(last_write, subkey_count, value_count, class_name, is_deleted)` |
| `hive_info(blob)` | scalar | `STRUCT(hive_type, major, minor, root_path, primary_seq, secondary_seq, is_dirty, last_written)` |
| `well_formed(blob)` | scalar | `STRUCT(ok, hive_type, error, kind)` — **永不触发 panic** |
| `logs_applied(blob, log1, log2)` | scalar | `STRUCT(applied, entries_replayed, dirty_pages, became_clean, log_format)` |
| `reghive_version()` | scalar | `VARCHAR` |
`read_hive` / `hive_subtree` 的命名选项:`apply_logs`(重放同级的
`.LOG1`/`.LOG2`,默认值为 `true`),`recover_deleted`(扫描未分配的 cell,
默认值为 `true`),`mode ∈ {values, keys, all}`(默认值为 `values`)。
### 输出模式(`read_hive` / `hive_subtree`)
每个**值**对应一行,对于没有值的键,则有一行仅包含键信息的行
(由 `mode` 控制)。重复的键列会被反规范化到每一行值数据中。
| 列名 | 类型 | 备注 |
|---|---|---|
| `key_path` | VARCHAR | 从 hive 根目录开始的路径(去除了合成的根键名;对于孤立键为 `$Deleted\…`) |
| `value_name` | VARCHAR | 值名称;对于 **(Default)** 值和仅包含键信息的行,该值为 `NULL` |
| `value_type` | VARCHAR | `REG_SZ`/`REG_DWORD`/`REG_MULTI_SZ`/`REG_BINARY`/…/`REG_` |
| `value_data` | VARCHAR | **强制转换**后的呈现形式(UTF-16 解码,整数转为字符串,MULTI_SZ 以换行符连接,二进制以十六进制表示)。对于二进制数据是有损的 |
| `value_raw` | BLOB | 磁盘上的**原始**字节(无损;是包含 `SAM`/`SECURITY` 凭据的列) |
| `value_dword` | BIGINT | 仅针对 `REG_DWORD`/`REG_QWORD` 填充 |
| `key_last_write` | TIMESTAMPTZ | 父键的最后写入 FILETIME → UTC |
| `is_deleted` | BOOLEAN | 从未分配空间中重建的行 |
| `hive_type` | VARCHAR | `SYSTEM`/`SOFTWARE`/`NTUSER`/`SAM`/`SECURITY`/`USRCLASS`/`AMCACHE`/`UNKNOWN` |
| `source` | VARCHAR | 源文件路径或 `''` |
| `recovery` | VARCHAR | 正常时为 `NULL`;否则为 `dirty-no-logs`、`logs-applied`、`deleted-orphan`、`deleted-reparented`、`modified-prior` |
| `diagnostics` | VARCHAR | 正常解码时为 `NULL`;否则为 `truncated`、`bad-checksum`、`bad-utf16`、… |
## 核心优势
- **事务日志重放。** 收集到的 hive 通常处于 *脏(dirty)* 状态 — 在实时系统
写入过程中被复制下来,其最新更改仅存在于日志中。当 hive 的基础块校验和错误
**或者**其主/副序列号不一致时,该 hive 就是脏的。`read_hive` 默认会应用同级
的 `.LOG1`/`.LOG2` 日志(在输出行之前将脏 hive 恢复到其应有状态),并通过
`recovery` 列和 `logs_applied` 函数报告其执行的操作。
- **已删除 cell 的恢复。** 释放键/值通常只是将 cell 的
大小符号反转并解除其链接 — 这些字节在被重新分配前会一直存在。通过
`recover_deleted`(默认开启),`read_hive` 会从未分配空间中重建这些 cell,
将它们标记为 `is_deleted`,并将其标注为 `deleted-orphan` /
`deleted-reparented`,以便查询时可以通过
`WHERE is_deleted` / `WHERE NOT is_deleted` 来包含或排除它们。
## 构建与测试
```
cargo build --release --bin reghive-worker # the worker binary (a DuckDB vgi LOCATION)
cargo test # unit + golden-fixture + zero-panic proptest
cargo run -p reghive-core --example gen_fixtures # regenerate tests/hives/*.hve
TRANSPORT=subprocess ci/run-integration.sh # haybarn SQLLogic E2E (also unix / http)
```
`tests/hives/` 下的 golden fixture 是**合成的**(由
`reghive-core` 的 hive writer 构建)且许可证干净 — 我们绝不提交真实的
包含有效哈希的 `SAM`/`SECURITY`。
## 许可证
- **Worker:** MIT(参见 `LICENSE`)。
- **解析引擎:** [`notatin`](https://github.com/strozfriedberg/notatin)
(Stroz Friedberg),**Apache-2.0** — 这是一款现代的、100% 安全的 Rust 离线 regf
解析器,独特地提供了事务日志应用以及已删除/修改记录的恢复功能。GPL 的 Rust regf crate `nt-hive` (GPL-2.0+) 和 `nt_hive2`
(GPL-3.0) 被**刻意排除**在依赖树之外。
`regf` 格式本身是公开记录的(参见
[msuhanov regf 规范](https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md)、
libyal/libregf,以及 Google Project Zero 的 "Windows Registry Adventure #5: regf")。
无 ToS,无重新分发的数据集。
## 搭配使用
`vgi-evtx` 和 `vgi-mft`/`vgi-prefetch`(Windows-DFIR 套件)、
`vgi-ioc`/threat-intel、`vgi-cve`、`vgi-yara`/`vgi-sigma`、`vgi-secretscan`,以及
`vgi-mask`/`vgi-pii`(在结果离开会话之前脱敏 `SAM`/`SECURITY` 的哈希字节)。
作为 Windows-DFIR / 安全套件的一部分,在治理
代理后销售。
版权所有 2026 Query Farm LLC — https://query.farm