Retour aux mises à jour
New releaseAug 20, 2026

regipy v6.3.0

Regipy est une bibliothèque python indépendante du système d'exploitation pour analyser les ruches de registre hors ligne.

Partager

regipy

OpenSSF Scorecard

⚠️ 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 attrs supprimée – Les classes de données utilisent désormais le module dataclasses intégré de Python
  • Si votre code importe des classes internes (Cell, VKRecord, Value, Subkey) et utilise des fonctions d’attrs comme attr.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 :

  • Utilisation en tant que bibliothèque :
    • Parcourir récursivement la ruche de registre, depuis la racine ou un chemin donné, et obtenir toutes les sous-clés et valeurs
    • Lire des sous-clés et valeurs spécifiques
    • Appliquer des journaux de transactions sur une ruche de registre
  • Outils en ligne de commande
    • Déverser une ruche de registre entière au format JSON
    • Appliquer des journaux de transactions sur une ruche de registre
    • Comparer des ruches de registre
    • Exécuter des plugins à partir d’un système de plugins robuste (par exemple : amcache, shimcache, extraire le nom de l’ordinateur…)

Nécessite Python 3.9 ou supérieur.

Installation

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]

Backend accéléré en Rust (alpha)

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 :

RucheClésPythonRustAccélération
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 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é.

CLI

Analyser l’en-tête :

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
  • Lors de l’analyse de l’en-tête d’une ruche, une validation de la somme de contrôle et des transactions est également effectuée.

Déverser la ruche entière sur le disque (cela peut prendre du temps)

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

Exécuter les plugins pertinents sur la ruche

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

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

Récupérer une ruche de registre à l’aide des journaux de transactions :

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é

Utilisation en tant que bibliothèque

Initialiser l’objet ruche de registre

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

Parcourir récursivement toute la ruche depuis la clé racine

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

Parcourir une clé et obtenir toutes les sous-clés ainsi que leur date de modification :

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

Obtenir les valeurs d’une clé :

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}]

Utiliser comme plugin :

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
		}]
	}
}

Exécuter tous les plugins pertinents pour une ruche spécifique

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'
	}]
}

Cas de validation

Rapport des cas de validation

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

Développement

Configuration pour le développement

# 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

Exécution des tests

# 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

Qualité du code

# Run linter
ruff check .

# Run formatter
ruff format .

# Run type checker
mypy regipy/

Tester les actions GitHub localement

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

Licence

MIT

Catégories