返回更新列表
新发布Aug 20, 2026

regipy v6.3.0

Regipy 是一个独立于操作系统的 Python 库,用于解析离线注册表配置单元。

分享

regipy

OpenSSF Scorecard

⚠️ v6.0.0 版本的破坏性变更

版本 6.0.0 包含了重要的现代化更改:

  • 需要 Python 3.9+ - 放弃了对 Python 3.6、3.7 和 3.8 的支持
  • 移除了 attrs - 数据类现在使用 Python 内置的 dataclasses 模块
  • 如果你的代码导入了内部类(Cell, VKRecord, Value, Subkey)并使用了 attrs 的函数如 attr.asdict(),请切换到 dataclasses.asdict()

详见 CHANGELOG

Regipy 是一个用于解析离线注册表配置单元(具有 REGF 头的配置单元文件)的 Python 库。regipy 具有许多功能:

  • 作为库使用:
    • 从根目录或指定路径递归遍历注册表配置单元,获取所有子键和值
    • 读取特定的子键和值
    • 在注册表配置单元上应用事务日志
  • 命令行工具
    • 将整个注册表配置单元转储为 JSON
    • 在注册表配置单元上应用事务日志
    • 比较注册表配置单元
    • 从强大的插件系统执行插件(例如:amcache、shimcache、提取计算机名...)

需要 Python 3.9 或更高版本。

安装

可以从 pypi 安装最新版本的 regipy:

pip install regipy[full]

注意:regipy[full] 安装的依赖需要编译工具,可能需要一些时间。 也可以通过省略 [full] 来安装依赖较宽松的版本。

另外,可以通过克隆仓库并从源码安装:

pip install --editable .[full]

Rust 加速后端(alpha)

一个可选的 Rust 实现的核心 REGF 解析器可以作为 opt-in 后端使用,并作为单独的包发布到 PyPI: regipy-rs

pip install regipy[rust]
from regipy.registry_rs import RegistryHive  # 替代 regipy.registry

reg = RegistryHive('/tmp/NTUSER.dat')
# 相同的 API:get_key, iter_values, recurse_subkeys, plugins — 一切
# 正常工作,包括所有 regipy 插件。

这是一个即插即用的替代品,已在整个测试配置单元集合上以 1:1 的比例与纯 Python 解析器进行了验证 — 每个键路径、时间戳、值和插件输出,都通过匹配的 SHA-256 遍历摘要进行了公证(参见 regipy_tests/comparison_test.pyregipy-rs/BENCHMARKS.md 中的 Forensic parity evidence 部分)。

完整遍历(包括值,recurse_subkeys),取三次运行的最佳结果:

HiveKeysPythonRustSpeedup
NTUSER.DAT1,812173 ms5 ms38x
UsrClass.dat6,205948 ms17 ms55x
amcache.hve2,105837 ms12 ms67x
SYSTEM30,75623.1 s91 ms253x
SYSTEM (Win10 1709)43,211118.7 s111 ms1,068x
SOFTWARE117,488745.6 s292 ms2,550x

cProfile 揭示了原因:在 Python 后端中,遍历时间主要被每条记录的 construct 结构解析和值解码所占据;使用 Rust 后端时,解析器完全从性能分析中消失,唯一的剩余 Python 开销是构造返回的 Subkey 数据类。完整的性能分析、每个配置单元的摘要以及记录少数有意差异(损坏配置单元上的异常类型、循环守卫行为)的免责声明在 regipy-rs/BENCHMARKS.md 中;python regipy-rs/benchmark.py 可重新生成整个报告。

纯 Python 解析器仍然是默认选项,并且在未安装 Rust 后端时不受影响。

CLI

解析头部:

regipy-parse-header ~/Documents/TestEvidence/Registry/SYSTEM

示例输出:

╒════════════════════════╤══════════╕
│ signature              │ b'regf'  │
├────────────────────────┼──────────┤
│ primary_sequence_num   │ 11639    │
├────────────────────────┼──────────┤
│ secondary_sequence_num │ 11638    │
├────────────────────────┼──────────┤
│ last_modification_time │ 0        │
├────────────────────────┼──────────┤
│ major_version          │ 1        │
├────────────────────────┼──────────┤
│ minor_version          │ 5        │
├────────────────────────┼──────────┤
│ file_type              │ 0        │
├────────────────────────┼──────────┤
│ file_format            │ 1        │
├────────────────────────┼──────────┤
│ root_key_offset        │ 32       │
├────────────────────────┼──────────┤
│ hive_bins_data_size    │ 10534912 │
├────────────────────────┼──────────┤
│ clustering_factor      │ 1        │
├────────────────────────┼──────────┤
│ file_name              │ SYSTEM   │
├────────────────────────┼──────────┤
│ checksum               │ 0        │
╘════════════════════════╧══════════╛
[2019-02-09 13:46:12.111654] WARNING: regipy.cli: 配置单元不干净!你应该应用事务日志
  • 解析配置单元头部时,还会进行校验和验证和事务验证

将整个配置单元转储到磁盘(可能需要一些时间)

regipy-dump ~/Documents/TestEvidence/Registry/NTUSER-CCLEANER.DAT -o /tmp/output.json

regipy-dump 工具也可以通过添加 -t 标志输出时间线而不是 JSON

在配置单元上运行相关插件

regipy-plugins-run ~/Documents/TestEvidence/Registry/SYSTEM -o /tmp/plugins_output.json

配置单元类型将被自动检测,并执行相关插件。 参见插件部分以获取更多信息

比较注册表配置单元

比较相同类型的注册表配置单元并输出到 CSV(如果未指定 -o,则输出将打印到屏幕)

regipy-diff NTUSER.dat NTUSER_modified.dat -o /tmp/diff.csv

示例输出:

[2019-02-11 19:49:18.824245] INFO: regipy.cli: 正在比较 NTUSER.DAT 与 NTUSER_modified.DAT
╒══════════════╤══════════════╤════════════════════════════════════════════════════════════════════════════════╤════════════════════════════════════════════════╕
│ difference   │ first_hive   │ second_hive                                                                    │ description                                    │
╞══════════════╪══════════════╪════════════════════════════════════════════════════════════════════════════════╪════════════════════════════════════════════════╡
│ new_subkey   │              │ 2019-02-11T19:46:31.832134+00:00                                               │ \Software\Microsoft\legitimate_subkey          │
├──────────────┼──────────────┼────────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────┤
│ new_value    │              │ not_a_malware: c:\temp\legitimate_binary.exe @ 2019-02-11 19:45:25.516346+00:00 │ \Software\Microsoft\Windows\CurrentVersion\Run │
╘══════════════╧══════════════╧════════════════════════════════════════════════════════════════════════════════╧════════════════════════════════════════════════╛
[2019-02-11 19:49:18.825328] INFO: regipy.cli: 检测到 2 处差异

使用事务日志恢复注册表配置单元:

regipy-process-transaction-logs NTUSER.DAT -p ntuser.dat.log1 -s ntuser.dat.log2 -o recovered_NTUSER.dat

恢复后,使用 registry-diff 比较配置单元以查看更改

作为库使用

初始化注册表配置单元对象

from regipy.registry import RegistryHive
reg = RegistryHive('/Users/martinkorman/Documents/TestEvidence/Registry/Vibranium-NTUSER.DAT')

递归遍历整个配置单元,从根键开始

for entry in reg.recurse_subkeys(as_json=True):
    print(entry)

遍历一个键并获取所有子键及其修改时间:

for sk in reg.get_key('Software').iter_subkeys():
    print(sk.name, convert_wintime(sk.header.last_modified).isoformat())

Adobe 2019-02-03T22:05:32.525965
AppDataLow 2019-02-03T22:05:32.526047
McAfee 2019-02-03T22:05:32.526140
Microsoft 2019-02-03T22:05:32.526282
Netscape 2019-02-03T22:05:32.526352
ODBC 2019-02-03T22:05:32.526521
Policies 2019-02-03T22:05:32.526592

获取一个键的值:

reg.get_key('Software\Microsoft\Internet Explorer\BrowserEmulation').get_values(as_json=True)
[{'name': 'CVListTTL',
  'value': 0,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'UnattendLoaded',
  'value': 0,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'TLDUpdates',
  'value': 0,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'CVListXMLVersionLow',
  'value': 2097211,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'CVListXMLVersionHigh',
  'value': None,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'CVListLastUpdateTime',
  'value': None,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'IECompatVersionHigh',
  'value': None,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'IECompatVersionLow',
  'value': 2097211,
  'value_type': 'REG_DWORD',
  'is_corrupted': False},
 {'name': 'StaleCompatCache',
  'value': 0,
  'value_type': 'REG_DWORD',
  'is_corrupted': False}]

作为插件使用:

from regipy.plugins.ntuser.ntuser_persistence import NTUserPersistencePlugin
NTUserPersistencePlugin(reg, as_json=True).run()

{
	'Software\\Microsoft\\Windows\\CurrentVersion\\Run': {
		'timestamp': '2019-02-03T22:10:52.655462',
		'values': [{
			'name': 'Sidebar',
			'value': '%ProgramFiles%\\Windows Sidebar\\Sidebar.exe /autoRun',
			'value_type': 'REG_EXPAND_SZ',
			'is_corrupted': False
		}]
	}
}

为特定配置单元运行所有相关插件

from regipy.plugins.utils import run_relevant_plugins
reg = RegistryHive('/Users/martinkorman/Documents/TestEvidence/Registry/SYSTEM')
run_relevant_plugins(reg, as_json=True)

{
	'routes': {},
	'computer_name': [{
		'control_set': 'ControlSet001\\Control\\ComputerName\\ComputerName',
		'computer_name': 'DESKTOP-5EG84UG',
		'timestamp': '2019-02-03T22:19:28.853219'
	}]
}

验证用例

验证用例报告

所有新插件应具有一个或多个基本验证用例(将来可以扩展),例如:

from regipy.plugins.system.bam import BAMPlugin
from regipy_tests.validation.validation import ValidationCase


class NTUserUserAssistValidationCase(ValidationCase):
    # 定义你的插件类
    plugin = BAMPlugin
    # 定义测试文件名,该文件应存在于 `regipy_tests/data` 中
    test_hive_file_name = "SYSTEM_WIN_10_1709.xz"

    # 使用 `expected_entries` 来测试插件结果中是否存在一些样本
    expected_entries = [
        {
            "sequence_number": 9,
            "version": 1,
            "sid": "S-1-5-90-0-1",
            "executable": "\\Device\\HarddiskVolume2\\Windows\\System32\\dwm.exe",
            "timestamp": "2020-04-19T09:09:35.731816+00:00",
            "key_path": "\\ControlSet001\\Services\\bam\\state\\UserSettings\\S-1-5-90-0-1",
        }
    ]

    # 或者使用 `exact_expected_result` 来测试精确结果:
    exact_expected_result = [
        {
            "sequence_number": 9,
            "version": 1,
            "sid": "S-1-5-90-0-1",
            "executable": "\\Device\\HarddiskVolume2\\Windows\\System32\\dwm.exe",
            "timestamp": "2020-04-19T09:09:35.731816+00:00",
            "key_path": "\\ControlSet001\\Services\\bam\\state\\UserSettings\\S-1-5-90-0-1",
        },
        {
            "sequence_number": 8,
            "version": 1,
            "sid": "S-1-5-90-0-1",
            "executable": "\\Device\\HarddiskVolume2\\Windows\\System32\\cmd.exe",
            "timestamp": "2020-04-19T09:09:34.544224+00:00",
            "key_path": "\\ControlSet001\\Services\\bam\\state\\UserSettings\\S-1-5-90-0-1",
        }
    ]

    expected_entries_count = 2

开发

设置开发环境

# 克隆仓库
git clone https://github.com/mkorman90/regipy.git
cd regipy

# 以开发模式安装所有依赖
pip install -e ".[full,dev]"

# 安装 pre-commit 钩子
pre-commit install

运行测试

# 运行所有测试
pytest

# 运行特定测试文件
pytest regipy_tests/tests.py
pytest regipy_tests/cli_tests.py

# 运行插件验证
PYTHONPATH=. python regipy_tests/validation/plugin_validation.py

代码质量

# 运行 linter
ruff check .

# 运行格式化工具
ruff format .

# 运行类型检查器
mypy regipy/

本地测试 GitHub Actions

在推送前,使用 act 本地测试 CI 工作流更改:

# 安装 act (Fedora)
sudo dnf install act-cli

# 安装 act (macOS)
brew install act

# 安装 act (其他)
# 参见 https://nektosact.com/installation/index.html

确保 Docker 正在运行,然后:

# 列出可用作业
act -l

# 运行 lint 作业
act -j lint

# 运行 push 事件的所有作业
act push

# 使用特定的 Python 版本运行测试作业
act -j test

# 测试发布工作流中的 build 作业(模拟发布版本)
act release -j build --eventpath /dev/stdin <<< '{"action": "published"}'

注意:某些作业可能需要 secrets。可以通过以下方式提供:

act -j publish --secret PYPI_API_TOKEN=your_token

许可证

MIT

分类