6.5 KiB
Removable offline application plugins
Plugins are loaded only when selected (or when their narrow filename rule
matches) from the toolkit-local plugins directory. They are ordinary local
Python code and are therefore trusted at the same level as the toolkit itself;
remove a plugin directory to remove the feature. Plugin manifests cannot point
outside their own directory, and the toolkit never downloads plugins. Each
manifest may declare its own text, password, and file controls for the web
interface. The web interface always exposes 3. Plugins; selecting a plugin
there reveals only that plugin's controls, names its required main artifact,
and states whether 2. Unlock key is also needed. 1. Artifact is not used
for plugin runs. Removing a plugin removes its choice and panel.
All application plugins are entirely offline. They do not contact a vendor service or a Windows host.
Certificate / PFX bundle
The Certificate / PFX plugin bundles a PEM/DER private key, or decrypts a
CAPI/CNG key first, then matches it to a certificate by public key. Both the key
input and the certificate input may be a single file or a folder, so a directory
of keys can be matched against a copied SystemCertificates\My\Certificates
folder in one run; each match is reported by the certificate SHA1 thumbprint:
python3 dpapi_toolkit.py private-key.pem --plugin certificate_pfx \
--certificate certificate.cer --pfx-password 'new PFX password'
python3 dpapi_toolkit.py CNG_FILE --plugin certificate_pfx \
--real-masterkey KEY --certificate CERT_FILE \
--pfx-password 'new PFX password'
python3 dpapi_toolkit.py CRYPTO_KEYS_DIR --plugin certificate_pfx \
--masterkey-dir PROTECT-SID --sid SID --password PASSWORD \
--certificate MY_CERTIFICATES_DIR --pfx-password 'new PFX password'
Entra ID CacheData
The CacheData plugin supports a password node when the exact password is known. It validates the file checksum, applies the fixed PBKDF2/AES flow, and returns the PRT JSON, raw DPAPI credential key, and derived SID-bound prekey. It can also export a bounded Hashcat mode-33700 verifier for a separate authorized recovery process. When a file contains several password nodes, each is attempted and every node matching the supplied password is returned even if sibling nodes do not decrypt. The toolkit itself accepts no wordlist, generates no candidates, and does not launch Hashcat:
python3 dpapi_toolkit.py CacheData --plugin cachedata --password 'known password'
python3 dpapi_toolkit.py CacheData --plugin cachedata --cachedata-hashcat
PIN/NGC CacheData nodes remain separate because they require the collected NGC and CNG key chain; TPM-backed keys cannot be reconstructed from copied files.
Windows SYSTEM/SECURITY/SAM hives
The Windows-hives plugin derives the boot key from a collected SYSTEM hive.
Add a collected SECURITY hive to recover the 20-byte DPAPI_SYSTEM MachineKey
and UserKey, and optionally add SAM to export local account hashes. It does
not use Remote Registry, RPC, SMB, cached-domain-logon extraction, password
history, or general LSA-secret output. Pass the hives explicitly, or point the
main input at a folder that holds them (each hive is matched by name):
python3 dpapi_toolkit.py SYSTEM --plugin windows_hives \
--security-hive SECURITY --sam-hive SAM
python3 dpapi_toolkit.py HIVES_DIR --plugin windows_hives
The raw .dpapi_system result can be supplied directly to a later command with
--dpapi-system. The .sam result uses the standard
username:RID:LM:NT::: representation and is written with owner-only
permissions like every other decrypted secret.
DPAPI-NG (offline root key)
The DPAPI-NG plugin accepts an exported KDS root key as JSON and deliberately
uses only its preloaded in-process key cache. It supports the SID protection
descriptor implemented by the optional dpapi-ng package and refuses a cache
miss instead of allowing DNS/RPC discovery:
python3 dpapi_toolkit.py secret.dpapi-ng --plugin dpapi_ng \
--dpapi-ng-root-key root-key.json
Walkthrough
DPAPI-NG (the NCryptProtectSecret/NCryptUnprotectSecret API) protects data to
a protection descriptor, usually a SID or group, rather than to one account
password. Its keys derive from a domain-wide KDS root key stored on the
domain controllers. This plugin needs that root key supplied explicitly; it never
contacts a domain controller.
-
Export the KDS root key (needs Domain Admin or SYSTEM). The root keys live in the configuration partition at
CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=.... ThemsKds-RootKeyDataattribute is confidential and only Domain Admins/SYSTEM can read it. Read the objects with a privileged LDAP query (for exampleGet-ADObject -SearchBase 'CN=Master Root Keys,...' -Filter * -Properties *), or recover them offline from a collectedNTDS.dit. -
Write
root-key.json. The file is one object or a list of objects. Each object needsRootKeyId(the objectcnGUID) and Base64RootKeyData(the 64-bytemsKds-RootKeyData). The remaining fields are optional and fall back to the Windows defaults shown here when omitted:[ { "RootKeyId": "d9a2b0a1-1111-2222-3333-444455556666", "RootKeyData": "<base64 of msKds-RootKeyData>", "Version": 1, "KdfAlgorithm": "SP800_108_CTR_HMAC", "KdfParameters": "<base64 of msKds-KDFParam, optional>", "SecretAgreementAlgorithm": "DH", "SecretAgreementParameters": "<base64 of msKds-SecretAgreementParam, optional>", "PrivateKeyLength": 512, "PublicKeyLength": 2048 } ]The attribute-to-field mapping is
cn->RootKeyId,msKds-RootKeyData->RootKeyData,msKds-Version->Version,msKds-KDFAlgorithmID->KdfAlgorithm,msKds-KDFParam->KdfParameters,msKds-SecretAgreementAlgorithmID->SecretAgreementAlgorithm,msKds-SecretAgreementParam->SecretAgreementParameters,msKds-PrivateKeyLength->PrivateKeyLength, andmsKds-PublicKeyLength->PublicKeyLength. Only KDFSP800_108_CTR_HMACand secret-agreementDH,ECDH_P256,ECDH_P384, orECDH_P521are supported. -
Decrypt. On the CLI, run the command above. In the web UI, open 3. Plugins, choose DPAPI-NG (offline root key), drop the DPAPI-NG artifact as the main input and
root-key.jsonin its field, then Run plugin.1. Artifactand2. Unlock keyare not used. If no supplied root key matches the blob, the plugin stops rather than falling back to the network.