
regipy v6.3.0
Regipy is an os independent python library for parsing offline registry hives
regipy
⚠️ Breaking Changes in v6.0.0
Version 6.0.0 includes significant modernization changes:
- Python 3.9+ required - Dropped support for Python 3.6, 3.7, and 3.8
attrslibrary removed - Data classes now use Python's built-indataclassesmodule- If your code imports internal classes (
Cell,VKRecord,Value,Subkey) and usesattrsfunctions likeattr.asdict(), switch todataclasses.asdict()See the CHANGELOG for full details.
Regipy is a python library for parsing offline registry hives (Hive files with REGF header). regipy has a lot of capabilities:
- Use as a library:
- Recurse over the registry hive, from root or a given path and get all subkeys and values
- Read specific subkeys and values
- Apply transaction logs on a registry hive
- Command Line Tools
- Dump an entire registry hive to json
- Apply transaction logs on a registry hive
- Compare registry hives
- Execute plugins from a robust plugin system (i.e: amcache, shimcache, extract computer name...)
Requires Python 3.9 or higher.
Installation
Regipy latest version can be installed from pypi:
pip install regipy[full]
NOTE: regipy[full] installs dependencies that require compilation tools and might take some time.
It is possible to install a version with relaxed dependencies, by omitting the [full].
Also, it is possible to install from source by cloning the repository and executing:
pip install --editable .[full]
Rust-accelerated backend (alpha)
An optional Rust implementation of the core REGF parser is available as an
opt-in backend, published separately to PyPI as
regipy-rs:
pip install regipy[rust]
from regipy.registry_rs import RegistryHive # instead of regipy.registry
reg = RegistryHive("/tmp/NTUSER.dat")
# Same API: get_key, iter_values, recurse_subkeys, plugins — everything
# works unchanged, including all regipy plugins.
It is a drop-in replacement validated 1:1 against the pure-Python parser over
the entire test-hive corpus — every key path, timestamp, value and plugin
output, notarized by matching SHA-256 traversal digests (see
regipy_tests/comparison_test.py and the Forensic parity evidence section
of regipy-rs/BENCHMARKS.md).
Full traversal with values (recurse_subkeys), best of 3 runs:
| Hive | Keys | Python | Rust | Speedup |
|---|---|---|---|---|
| NTUSER.DAT | 1,812 | 173 ms | 5 ms | 38x |
| UsrClass.dat | 6,205 | 948 ms | 17 ms | 55x |
| amcache.hve | 2,105 | 837 ms | 12 ms | 67x |
| SYSTEM | 30,756 | 23.1 s | 91 ms | 253x |
| SYSTEM (Win10 1709) | 43,211 | 118.7 s | 111 ms | 1,068x |
| SOFTWARE | 117,488 | 745.6 s | 292 ms | 2,550x |
cProfile shows why: in the Python backend, traversal time is dominated by
per-record construct struct parsing and value decoding; with the Rust
backend, the parser disappears from the profile entirely and the only
remaining Python cost is constructing the returned Subkey dataclasses.
The full profiles, per-hive digests and a disclaimer documenting the few
intentional divergences (exception types on corrupted hives, cycle-guard
behavior) are in regipy-rs/BENCHMARKS.md;
python regipy-rs/benchmark.py regenerates the entire report.
The pure-Python parser remains the default and is unaffected when the Rust backend is not installed.
CLI
Parse the header
regipy-parse-header ~/Documents/TestEvidence/Registry/SYSTEM
Example output:
╒════════════════════════╤══════════╕
│ 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: Hive is not clean! You should apply transaction logs
- When parsing the header of a hive, also checksum validation and transaction validations are done
Dump entire hive to disk (this might take some time)
regipy-dump ~/Documents/TestEvidence/Registry/NTUSER-CCLEANER.DAT -o /tmp/output.json
regipy-dump util can also output a timeline instead of a JSON, by adding the -t flag
Run relevant plugins on Hive
regipy-plugins-run ~/Documents/TestEvidence/Registry/SYSTEM -o /tmp/plugins_output.json
The hive type will be detected automatically and the relevant plugins will be executed. See the plugins section for more information
Compare registry hives
Compare registry hives of the same type and output to CSV (if -o is not specified output will be printed to screen)
regipy-diff NTUSER.dat NTUSER_modified.dat -o /tmp/diff.csv
Example output:
[2019-02-11 19:49:18.824245] INFO: regipy.cli: Comparing NTUSER.DAT vs 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: Detected 2 differences
Recover a registry hive, using transaction logs
regipy-process-transaction-logs NTUSER.DAT -p ntuser.dat.log1 -s ntuser.dat.log2 -o recovered_NTUSER.dat
After recovering, compare the hives with registry-diff to see what changed
Using as a library
Initiate the registry hive object
from regipy.registry import RegistryHive
reg = RegistryHive("/Users/martinkorman/Documents/TestEvidence/Registry/Vibranium-NTUSER.DAT")
Iterate recursively over the entire hive, from root key
for entry in reg.recurse_subkeys(as_json=True):
print(entry)