18 KiB
CLI reference
The toolkit logic lives in the importable module dpapi_toolkit.py, which is
also the CLI. For per-format command examples (Vault, Wi-Fi, RDP, Chromium, and
the rest) see artifacts.md; for the removable plugins and the
DPAPI-NG walkthrough see plugins.md.
Help and inspection
Short command help:
python3 dpapi_toolkit.py -h
Detailed key, artifact, location, and limitation help:
python3 dpapi_toolkit.py -hh
Inspect a supported artifact without providing a key:
python3 dpapi_toolkit.py artifact.bin
The tool prints every embedded classic DPAPI blob and its required masterkey GUID. No output file is created during inspection.
Use - as the input to read one artifact from standard input. Binary and
textual hexadecimal input are both accepted:
cat artifact.bin | python3 dpapi_toolkit.py - --type blob --real-masterkey KEY
printf '%s' '01000000...' | python3 dpapi_toolkit.py - --structure
Standard input is a single-artifact CLI flow; folder batch mode and web drag and drop use local files instead.
Print the full parsed structure of a blob or an encrypted master-key file without decrypting anything:
python3 dpapi_toolkit.py artifact.bin --structure
--structure lists each blob's identity and scope (version, provider/master-key
GUIDs, flags, description), cryptography (cipher and hash algorithms), and binary
fields (salt, HMAC, ciphertext, signature). For an encrypted master-key file it
also reports the PBKDF2 iteration count and the Hashcat mode it maps to. This is
the same breakdown the GUIs show in their Structure view.
Automatic masterkey-directory lookup
--masterkey-dir works for both one artifact and recursive batch mode. The
tool reads the GUID embedded in each DPAPI blob, searches the directory
recursively, and decrypts only the matching GUID-named masterkey.
With a password:
python3 dpapi_toolkit.py BLOB \
--masterkey-dir PROTECT-SID \
--sid S-1-5-21-... \
--password PASSWORD
With DPAPI_SYSTEM:
python3 dpapi_toolkit.py SYSTEM_BLOB \
--masterkey-dir SYSTEM_PROTECT_DIRECTORY \
--dpapi-system DPAPI_SYSTEM_HEX
With recovered user material:
python3 dpapi_toolkit.py BLOB --masterkey-dir PROTECT-SID --prekey PREKEY
python3 dpapi_toolkit.py BLOB --masterkey-dir PROTECT-SID --sid SID --nt-hash HASH
python3 dpapi_toolkit.py BLOB --masterkey-dir PROTECT-SID --sid SID --sha1-hash HASH
python3 dpapi_toolkit.py BLOB --masterkey-dir PROTECT-SID --sid SID --credkey KEY
With the AD domain backup key:
python3 dpapi_toolkit.py BLOB \
--masterkey-dir PROTECT-SID \
--domain-backup-key BACKUPKEY.pvk
The directory may also contain already-decrypted 20-byte mappings or 64-byte
masterkeys. For automatic matching, those raw files must be named exactly with
their masterkey GUID. --real-masterkey KEY remains the direct fallback when
you already know that one clear key applies, so it does not need directory
lookup.
Files containing multiple DPAPI blobs may reference different GUIDs. Each blob
is resolved and decrypted separately. If only some matching masterkeys are
available, those values are still returned and each unresolved value is listed
in the activity log and, for structured JSON formats, in an errors entry. The
run fails only when none of its independent values can be decrypted. CREDHIST is
the exception: it returns the recovered prefix, but cannot continue past a
missing link because every older entry depends on the preceding one. Optional
entropy works normally with directory lookup:
python3 dpapi_toolkit.py BLOB \
--masterkey-dir PROTECT-SID \
--sid SID --password PASSWORD \
--entropy-file entropy.bin
Output behavior
Outputs are never overwritten. A run timestamp is prepended to every output:
20260831_142501_secret_dec.bin
If that name already exists, _2, _3, and so on are appended.
--out-file NAME selects the base output name but keeps the timestamp prefix.
Batch runs create a separate directory:
20260831_142501_ARTIFACTS_dec/
With --out-dir RESULTS, the timestamped run directory is created below
RESULTS. For a single artifact, --out-dir RESULTS places the timestamped
output file directly in RESULTS. Every batch run also writes
batch_report.json.
Choose the output representation with -o / --out:
-o auto # automatic text/binary handling; default
-o hex # one continuous hexadecimal text line, saved as .hex
-o raw # exact decrypted bytes, saved as .bin
-o unhex # ASCII/UTF-16 hex text -> binary .bin
-o utf16-utf8 # UTF-16LE -> UTF-8 .txt
--show # also display the result in the terminal
--output-format is a long alias for -o/--out. --hex, --raw, --unhex,
and --utf16-utf8 remain available as convenience aliases. --console is an
alias for --show. Use --out-file FILE when a custom base filename is needed.
When --out-dir and --out-file are combined, the directory comes from
--out-dir and the base filename comes from --out-file.
Examples:
python3 dpapi_toolkit.py blob.bin --real-masterkey KEY -o hex --show
python3 dpapi_toolkit.py blob.bin --real-masterkey KEY -o raw --console
python3 dpapi_toolkit.py blob.bin --real-masterkey KEY -o unhex
python3 dpapi_toolkit.py blob.bin --real-masterkey KEY -o utf16-utf8 --show
Structured formats such as Credentials, Vault, Wi-Fi, RDP, Outlook, and RDCMan are normally saved as JSON. RSA private keys are normally converted to PEM.
Unlocking user masterkeys
Default location:
%APPDATA%\Microsoft\Protect\<USER-SID>\<MASTERKEY-GUID>
Current account password
python3 dpapi_toolkit.py BLOB \
--masterkey MASTERKEY-GUID \
--sid S-1-5-21-... \
--password 'password'
Omit --password to receive a non-echoing prompt. For an empty password, pass
--password '' explicitly. Password mode automatically tries local, classic
domain, and newer domain derivation and accepts only a verified masterkey.
NT hash
A 16-byte NT hash is a valid input for classic domain-style and Protected Users masterkey derivation when the owning SID is also known. It is not interchangeable with the 20-byte local SHA1 password hash; the toolkit tries only the derivations appropriate to the supplied value and accepts a result only after masterkey HMAC verification.
python3 dpapi_toolkit.py BLOB \
--masterkey MASTERKEY-GUID \
--sid S-1-5-21-... \
--nt-hash NTHASH
Local SHA1 password hash
This input is exactly the 20-byte digest
SHA1(password.encode("utf-16le")). It is a classic local-DPAPI password
credential key, not an Entra dpapi_prekey. The toolkit combines it with the
owning SID to derive and verify the masterkey prekey.
python3 dpapi_toolkit.py BLOB \
--masterkey MASTERKEY-GUID \
--sid S-1-5-21-... \
--sha1-hash SHA1
Final prekey recovered from another offline source
This is already the final 20-byte SID-bound key used to unlock an encrypted user masterkey. It is not a PIN and is not applied directly to a DPAPI blob.
python3 dpapi_toolkit.py BLOB \
--masterkey MASTERKEY-GUID \
--prekey PREKEY_HEX
Unbound credential key
This is commonly recovered from CloudAP/CacheData. It still needs the owning account SID so the toolkit can derive the masterkey prekey; it is not itself a Windows Hello PIN input.
python3 dpapi_toolkit.py BLOB \
--masterkey MASTERKEY-GUID \
--sid S-1-5-21-... \
--credkey CREDENTIAL_KEY_HEX
Already-decrypted masterkey
python3 dpapi_toolkit.py BLOB --real-masterkey MASTERKEY_HEX
python3 dpapi_toolkit.py BLOB --real-masterkey MASTERKEY_BASE64
python3 dpapi_toolkit.py BLOB --real-masterkey masterkey.bin
--real-masterkey accepts the full 64-byte masterkey or its 20-byte SHA1
mapping. It bypasses password, SID, DPAPI_SYSTEM, and domain backup processing.
SID interpretation: local, on-prem AD, and Entra ID
The tool validates and classifies a supplied SID before attempting decryption:
S-1-12-1-...is treated as an Entra ID/cloud-account SID. The classic on-prem AD DPAPI domain backup key is rejected for this SID. Use recovered CloudAP--prekey/--credkey, an already-decrypted masterkey, or the software NGC path where applicable.S-1-5-21-...may be either a local account or an on-prem AD account. The SID alone cannot distinguish them; successful masterkey HMAC verification selects the usable password derivation.- Built-in and service SIDs are identified separately when verbose output is enabled.
An Entra SID does not by itself prove that the account uses a PIN, nor whether
the Windows Hello key is software-backed or TPM-backed. That requires the NGC
protector/provider and CNG key metadata. --pin is accepted only with
--type ngc-cng. If the profile is Hello/TPM-only, the classic DPAPI masterkey
cannot be cracked from its SID and masterkey file: neither the PIN verifier nor
the TPM private key is stored in the $DPAPImk$ record. Such a record can only
test password/credential-derived DPAPI candidates, when those exist. Software
NGC PIN testing is a separate --type ngc-cng workflow.
SYSTEM and service-account DPAPI
Common masterkey locations:
%WINDIR%\System32\Microsoft\Protect\S-1-5-18\User\<MASTERKEY-GUID>
%WINDIR%\System32\Microsoft\Protect\S-1-5-18\<MASTERKEY-GUID>
The DPAPI_SYSTEM LSA secret must be extracted offline from both the SYSTEM and
SECURITY hives. Accepted forms are:
- Full 44 bytes: version + 20-byte MachineKey + 20-byte UserKey.
- 40 bytes: MachineKey + UserKey.
- One 16/20-byte component.
- Text containing
MachineKey:andUserKey:values.
Decrypt an artifact in one command:
python3 dpapi_toolkit.py SYSTEM_BLOB \
--masterkey SYSTEM-MASTERKEY-GUID \
--dpapi-system DPAPI_SYSTEM_HEX
Decrypt only the SYSTEM masterkey first:
python3 dpapi_toolkit.py SYSTEM-MASTERKEY-GUID \
--type masterkey \
--dpapi-system DPAPI_SYSTEM_HEX
The resulting timestamped .bin can then be supplied with --real-masterkey.
AD domain backup key
Domain user masterkey files may contain a DomainKey section protected with the domain DPAPI backup RSA key.
python3 dpapi_toolkit.py MASTERKEY-GUID \
--type masterkey \
--domain-backup-key BACKUPKEY.pvk
The alias --pvk is accepted. PEM, DER, Windows PVK, raw CAPI
PRIVATEKEYBLOB, hex, and Base64 inputs are supported. For encrypted PVK or PEM
files, use --pvk-password TEXT or --pvk-password-file FILE. Strong and
legacy weak-key Microsoft PVK encryption are both recognized; no password
guessing is performed.
Legacy version-1 masterkey DomainKey sections can instead be recovered with the
collected 256-byte G$BCKUPKEY_<GUID> ServerWrap key (the .key exported by
common AD backup-key tooling). The MS-BKRP HMAC and SID are validated locally;
no BKRP RPC request is made. A full P_BACKUP_KEY value containing the leading
version dword is accepted as well.
python3 dpapi_toolkit.py MASTERKEY-GUID --type masterkey \
--pvk BACKUPKEY.pvk --pvk-password-file pvk-password.txt
Optional entropy
If the application supplied optional entropy to CryptProtectData, the same
bytes are required during decryption.
Literal UTF-8 text:
python3 dpapi_toolkit.py BLOB --real-masterkey KEY --entropy 'application text'
Hex, Base64, or UTF-16LE text:
python3 dpapi_toolkit.py BLOB --real-masterkey KEY --entropy hex:01020304
python3 dpapi_toolkit.py BLOB --real-masterkey KEY --entropy base64:AQIDBA==
python3 dpapi_toolkit.py BLOB --real-masterkey KEY --entropy utf16:Secret
Exact bytes from a file:
python3 dpapi_toolkit.py BLOB --real-masterkey KEY --entropy-file entropy.bin
Explicit entropy overrides built-in entropy for that run. Without an explicit value, known CAPI/CNG entropy is selected automatically.
CREDHIST password history
Default location:
%APPDATA%\Microsoft\Protect\<USER-SID>\CREDHIST
CREDHIST is a chain of older SHA1 and NT password hashes encrypted using the newer credential. Start with the current password or current key material:
python3 dpapi_toolkit.py CREDHIST --type credhist --password CURRENT_PASSWORD
python3 dpapi_toolkit.py CREDHIST --type credhist --nt-hash CURRENT_NT_HASH
python3 dpapi_toolkit.py CREDHIST --type credhist --sha1-hash CURRENT_SHA1
python3 dpapi_toolkit.py CREDHIST --type credhist --prekey CURRENT_PREKEY
python3 dpapi_toolkit.py CREDHIST --type credhist --credkey CURRENT_CREDKEY
The SID is stored in each CREDHIST entry, so --sid is not required. Output is
JSON containing each history GUID, SID, SHA1 hash, and NT hash. Those recovered
hashes can then decrypt masterkeys protected before the password changed.
Hashcat masterkey export
python3 dpapi_toolkit.py MASTERKEY-GUID --hashcat --sid S-1-5-21-...
--hashcat always treats the input as an encrypted master-key file, so
--type is not required. Add --type masterkey when you want to be explicit:
python3 dpapi_toolkit.py MASTERKEY-GUID --type masterkey --hashcat --sid S-1-5-21-...
The Hashcat mode comes from the masterkey's cipher/hash, and the derivation context comes from the account type:
| Masterkey algorithms | Local account | Domain account (legacy) | Domain account (2016+) |
|---|---|---|---|
| 3DES/SHA1 | 15300 | 15300 | 15310 |
| AES-256/SHA-512 | 15900 | 15900 | 15910 |
In short: a local account masterkey cracks as 15900 (or 15300), and a
domain account masterkey is usually 15910 (or 15310) on 2016-and-later
domain controllers, or 15900/15300 on older ones. The mode alone is not enough:
the $DPAPImk$ record also embeds a context number (1 local, 2 domain, 3
domain-new), and Hashcat derives the key differently for each, so a local
masterkey only cracks with the local (context 1) record even though it is also
mode 15900.
The masterkey file does not reliably reveal which account type it belongs to, so
the default --hashcat-context all exports the local, domain, and domain-new
records; crack whichever matches. Use local, domain, domain-new, or
domain-auto (both domain forms) to narrow it.
To export every master key under a directory at once, add --batch. Each master
key becomes its own record (they may have different passwords and are cracked
independently), the owning SID is read from a Protect\<SID> parent directory
when present or from --sid otherwise, and the records are grouped into one file
per mode:
python3 dpapi_toolkit.py PROTECT-DIR --batch --hashcat --sid S-1-5-21-...
Recursive batch mode
One encrypted masterkey for a directory:
python3 dpapi_toolkit.py ARTIFACTS \
--batch \
--masterkey MASTERKEY-GUID \
--sid SID \
--password PASSWORD
One already-decrypted masterkey:
python3 dpapi_toolkit.py ARTIFACTS --batch --real-masterkey KEY
A Protect folder of masterkeys matched to blobs by GUID:
python3 dpapi_toolkit.py ARTIFACTS \
--batch \
--masterkey-dir PROTECT-SID \
--sid SID \
--password PASSWORD
Domain masterkeys with an AD backup key:
python3 dpapi_toolkit.py ARTIFACTS \
--batch \
--masterkey-dir PROTECT-SID \
--domain-backup-key BACKUPKEY.pvk
SYSTEM masterkeys:
python3 dpapi_toolkit.py ARTIFACTS \
--batch \
--masterkey-dir SYSTEM_PROTECT_DIR \
--dpapi-system DPAPI_SYSTEM_HEX
Batch mode recursively recognizes certificates, CREDHIST, Wi-Fi XML, .rdp,
RDCMan, Vault policies/records, Credentials, CAPI/CNG, and generic embedded
classic DPAPI blobs. First-class CLIXML, KeePass, SCCM, and removable-plugin
dispatch currently use single-artifact mode. Masterkeys are cached by GUID. A
--real-masterkey has no GUID and is tried as a fallback. Within one recognized
multi-value file, successful values are kept when other GUIDs are unavailable;
the batch report marks that artifact as partial and records per-item errors.
Default collection locations
| Artifact | Default location |
|---|---|
| User masterkeys | %APPDATA%\Microsoft\Protect\<SID>\* |
| SYSTEM masterkeys | %WINDIR%\System32\Microsoft\Protect\S-1-5-18\* |
| CREDHIST | %APPDATA%\Microsoft\Protect\<SID>\CREDHIST |
| Local Credentials | %LOCALAPPDATA%\Microsoft\Credentials\* |
| Roaming Credentials | %APPDATA%\Microsoft\Credentials\* |
| User Vault | %LOCALAPPDATA%\Microsoft\Vault\* |
| SYSTEM Vault | %WINDIR%\System32\config\systemprofile\AppData\Local\Microsoft\Vault |
| CAPI keys | %APPDATA%\Microsoft\Crypto\RSA\<SID>\* |
| CNG keys | %APPDATA%\Microsoft\Crypto\Keys\* |
| Public certificates | %APPDATA%\Microsoft\SystemCertificates\My\Certificates\* |
| Wi-Fi profiles | %ProgramData%\Microsoft\Wlansvc\Profiles\Interfaces\*\*.xml |
| Outlook profiles | NTUSER.DAT, under Software\Microsoft\Office\...\Outlook\Profiles |
| NGC metadata | %WINDIR%\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc |
Troubleshooting
required master key <GUID>-
Find that exact GUID-named file under the appropriate user or SYSTEM Protect directory, or supply its already-decrypted key with
--real-masterkey. invalid paddingorsignature verification failed-
The masterkey or optional entropy is wrong. DPAPI plaintext is accepted only after cryptographic verification.
could not decrypt master key-
Check the owning SID and unlocking material. A password changed by an administrator may require CREDHIST or the AD domain backup key.
no classic DPAPI blob found-
Force the correct
--type, verify that the file was exported as binary, or confirm that the application actually uses classic DPAPI rather than DPAPI-NG or custom encryption. output path exists-
Normal output selection avoids collisions automatically. This error would indicate a race with another process; rerun to receive a new timestamp/suffix.