
Regipy est une bibliothèque python indépendante du système d'exploitation pour analyser les ruches de registre hors ligne.
⚠️ Changements majeurs dans v6.0.0
La version 6.0.0 inclut des changements de modernisation significatifs :
- Python 3.9+ requis – Abandon du support pour Python 3.6, 3.7 et 3.8
- Bibliothèque
attrssupprimée – Les classes de données utilisent désormais le moduledataclassesintégré de Python- Si votre code importe des classes internes (
Cell,VKRecord,Value,Subkey) et utilise des fonctions d’attrscommeattr.asdict(), passez àdataclasses.asdict()Voir le CHANGELOG pour tous les détails.
Regipy est une bibliothèque Python pour l’analyse de ruches de registre hors ligne (fichiers de ruche avec en-tête REGF). regipy dispose de nombreuses capacités :
Nécessite Python 3.9 ou supérieur.
La dernière version de regipy peut être installée depuis pypi :
pip install regipy[full]
NOTE : regipy[full] installe des dépendances qui nécessitent des outils de compilation et peuvent prendre du temps.
Il est possible d’installer une version avec des dépendances allégées en omettant [full].
De plus, il est possible d’installer depuis les sources en clonant le dépôt et en exécutant :
pip install --editable .[full]
Une implémentation Rust optionnelle du parseur REGF de base est disponible en tant que
backend au choix, publiée séparément sur PyPI sous le nom
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.
C’est un remplacement direct validé 1:1 par rapport au parseur pure-Python sur l’ensemble
des ruches de test — chaque chemin de clé, horodatage, valeur et sortie de plugin,
notarié par des digest de parcours SHA-256 correspondants (voir
regipy_tests/comparison_test.py et la section Forensic parity evidence
de regipy-rs/BENCHMARKS.md).
Parcours complet avec valeurs (recurse_subkeys), meilleur de 3 exécutions :
cProfile montre pourquoi : dans le backend Python, le temps de parcours est dominé par
l’analyse des structures construct par enregistrement et le décodage des valeurs ; avec le
backend Rust, l’analyse disparaît complètement du profil et le seul coût Python restant est
la construction des classes Subkey retournées.
Les profils complets, les digest par ruche et une clause de non-responsabilité documentant
les quelques divergences intentionnelles (types d’exceptions sur les ruches corrompues,
comportement du garde-cycle) se trouvent dans
regipy-rs/BENCHMARKS.md ;
python regipy-rs/benchmark.py régénère l’intégralité du rapport.
Le parseur pure-Python reste le défaut et n’est pas affecté si le backend Rust n’est pas installé.
regipy-parse-header ~/Documents/TestEvidence/Registry/SYSTEM
Exemple de sortie :
╒════════════════════════╤══════════╕
│ 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: La ruche n’est pas propre ! Vous devriez appliquer les journaux de transactions
regipy-dump ~/Documents/TestEvidence/Registry/NTUSER-CCLEANER.DAT -o /tmp/output.json
L’utilitaire regipy-dump peut également produire une chronologie au lieu d’un JSON, en ajoutant l’option -t
regipy-plugins-run ~/Documents/TestEvidence/Registry/SYSTEM -o /tmp/plugins_output.json
Le type de ruche sera détecté automatiquement et les plugins pertinents seront exécutés. Voir la section sur les plugins pour plus d’informations
Comparer des ruches de registre du même type et exporter en CSV (si -o n’est pas spécifié, la sortie s’affiche à l’écran)
regipy-diff NTUSER.dat NTUSER_modified.dat -o /tmp/diff.csv
Exemple de sortie :
[2019-02-11 19:49:18.824245] INFO: regipy.cli: Comparaison de NTUSER.DAT vs NTUSER_modified.DAT
╒══════════════╤══════════════╤════════════════════════════════════════════════════════════════════════════════╤════════════════════════════════════════════════╕
│ différence │ première_ruche │ deuxième_ruche │ 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 différences détectées
regipy-process-transaction-logs NTUSER.DAT -p ntuser.dat.log1 -s ntuser.dat.log2 -o recovered_NTUSER.dat
Après la récupération, comparez les ruches avec registry-diff pour voir ce qui a changé
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'
}]
}
Tous les nouveaux plugins doivent avoir un ou plusieurs cas de validation de base (qui pourront être étendus ultérieurement), par exemple :
from regipy.plugins.system.bam import BAMPlugin
from regipy_tests.validation.validation import ValidationCase
class NTUserUserAssistValidationCase(ValidationCase):
# define your plugin class
plugin = BAMPlugin
# define the test file name, which should be present in `regipy_tests/data`
test_hive_file_name = "SYSTEM_WIN_10_1709.xz"
# Use `expected_entries` to test for presence of a few samples from the plugin results
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",
}
]
# OR use `exact_expected_result` to test for an exact 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
# Clone the repository
git clone https://github.com/mkorman90/regipy.git
cd regipy
# Install in development mode with all dependencies
pip install -e ".[full,dev]"
# Install pre-commit hooks
pre-commit install
# Run all tests
pytest
# Run specific test files
pytest regipy_tests/tests.py
pytest regipy_tests/cli_tests.py
# Run plugin validation
PYTHONPATH=. python regipy_tests/validation/plugin_validation.py
# Run linter
ruff check .
# Run formatter
ruff format .
# Run type checker
mypy regipy/
Pour tester les modifications du workflow CI localement avant de les pousser, utilisez act :
# Install act (Fedora)
sudo dnf install act-cli
# Install act (macOS)
brew install act
# Install act (other)
# See https://nektosact.com/installation/index.html
Assurez-vous que Docker est en cours d’exécution, puis :
# List available jobs
act -l
# Run the lint job
act -j lint
# Run all jobs for a push event
act push
# Run the test job with a specific Python version
act -j test
# Test the build job from publish workflow (simulates a release)
act release -j build --eventpath /dev/stdin <<< '{"action": "published"}'
Remarque : Certains travaux peuvent nécessiter des secrets. Vous pouvez les fournir avec :
act -j publish --secret PYPI_API_TOKEN=your_token
MIT
| Ruche | Clés | Python | Rust | Accélération |
|---|
| 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 |