DPAPI-in-depth with tooling: standalone DPAPI

Geplaatst door

The Microsoft Data Protection Application Programming Interface, or DPAPI for short, is a Windows API tool for developers to enable them to store sensitive data in a way that it is encrypted but still decryptable.
It has been around since Windows 2000 which makes it more or less ancient in computer terms.
However it has since been tweaked to such an extent that it is no longer recognizable, things like RSA, AES256, SHA512 and even PBKDF2 have been added or increased in rounds.

This article will go in depth on how Stand Alone DPAPI works: only local Windows accounts (so no Active Directory nor Microsoft Live) and no TPM. It has been developed and verified on the latest version of Windows 10 x64 (v20H2, 19042.685 at the time of writing).

This article will exclusively focus on local User and System DPAPI encryption and provides some in depth cryptographical insights.

An example of the result of this research and tooling can be seen in this short video:


DPAPI in daily life

So where is DPAPI used? The answer: close to everything that is password-related:

  • Chrome & Edge (which now share the same Chromium code base) rely on DPAPI for storing cookies, usernames and  passwords
  • Many applications such as Outlook, Internet Explorer
  • Windows Credential Manager, which is used for File Shares, Remote Desktop sessions …
  • Wi-Fi passwords, both the PreSharedKey versions as the Enterprise PEAP versions
  • Third party tools like OpenVPN, iCloud, VMware Workstation, FortiClient or Dropbox
  • Windows Hello Credentials like PIN, Picture Password, Fingerprint …


The impact of DPAPI attacks like this can be massive. Some examples:

  • An attacker finds an external drive or a file share holding a read only backup copy of a Windows C-drive. Most password extraction tools are useless since most of them require to be run on working systems.
  • An attacker gets (administrative) access to a Windows workstation and refuses or is unable to run any tools that are not native to the system. He wants to copy out the required files and perform offline analysis later. E.g. running Mimikatz (even a modified or PowerShell version) on a production device is not always recommended
  • Or maybe even access to a Virtual Hard Drive of a VM (e.g. access to an iSCSI server) holding all the data.


DPAPI has two parts: the encryption/decryption keys, called DPAPI Master Keys and the encrypted data itself, called a DPAPI Blob or just blob.

The blob is actually a binary, hex-formatted data structure with several fields. The first two fields are the version and a provider ID (which is always the GUID df9d8cd0-1501-11d1-8c7a-00c04fc297eb).
They are HEX encoded into the beginning of the blob like this:
01000000d08c9ddf0115d1118c7a00c04fc297eb …

This makes that most DPAPI blobs actually have a “signature”, which means they can be scanned for on the hard drive or in the Windows registry.

The next field is another version followed by the GUID of the Master Key to decrypt the blob, this GUID is actually the file name of the encrypted Master Key on the hard drive.

Amongst the rest of the fields are the most important ones [2]:

  • Description: this would be the only Plain Text ASCII part of the blob, although optional
  • Crypto algorithm & length: often AES-256
  • Hash algorithm & length: often SHA-512
  • Salt: optional salt for encryption and decryption, often 32 Bytes
  • Cipher: the encrypted data, very random in length of course
  • Hmac: not strictly needed to decrypt, but needed to verify decryption key, often 32 Bytes
  • Sign: not strictly needed to decrypt, but needed to verify decryption key, often 64 Bytes

Want to create and see a blob yourself? It is easy in versions of Windows, just open any PowerShell window.
Here the string “Secret Data” is encrypted into a blob and the hex code is shown:

Add-Type -AssemblyName System.Security
$EncryptedBytes = [Security.Cryptography.ProtectedData]::Protect([Byte[]][Char[]]"Secret Data", $Null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
($EncryptedBytes | ForEach-Object ToString X2) -join ""

For completeness sake to decrypt the data (PowerShell does all the DPAPI work):

[System.Text.Encoding]::ASCII.GetString([Security.Cryptography.ProtectedData]::UnProtect($EncryptedBytes, $Null, [Security.Cryptography.DataProtectionScope]::CurrentUser))

This should result in a hex string of about 230 Bytes containing the above fields. This DPAPI blob is encrypted with the Master Key of the current windows user.

DPAPI Master Keys

There are two types of Master Keys: the ones unique for your device called the System Master Key and the ones unique to every user called the User Master Keys.

In the PowerShell example above, replace CurrentUser with LocalMachine to use System Master Keys.

User Master Keys

These are commonly stored in this folder:

%APPDATA%\Microsoft\Protect within a folder that is the user SID, there usually is only one such SID per user.
When opening that folder, it might seem empty, because the Master Keys are of the “Protected Operating System” type.

Multiple Master Keys here, the file “Preferred” contains only the GUID of the main User Master Key

These Master Key files are also binary, hex-formatted data structures holding several fields, however the DPAPI Master Key itself is encrypted too and needs a user password (hash) and the user SID (which is the folder name).

Some of the more important fields besides the version are these:

  • Cipher algorithm & length: often AES-256
  • Hash algorithm & length: often SHA-512
  • Rounds: PBKDF2 iterations, often 8000
  • IV: used as salt for PBKDF2, often 16 Bytes
  • Cipher: the encrypted Master Key itself, often 144 Bytes

This User Master Key can be decrypted using the user SID and the SHA1 hash of the clear text user password (UTF-16LE encoded).
This has two consequences:

  • DPAPI User Master Keys cannot be decrypted offline unless the password or SHA1 hash of that password is known
  • On a running system, after typing in the password during login: the SHA1 password hash is being kept in the memory of the process “lsass.exe”, and that is what e.g. PowerShell uses to encrypt and decrypt User DPAPI Blobs.

Password history?

Does this mean that if a user changes his password, all DPAPI blobs are lost?

Yes and No; it depends on the way the password was changed and whether or not the previous password was asked.

When changing a user password via a shell (e.g. the net user <username> * command) or via the lusrmgr.msc console, then YES: all user DPAPI encrypted data is lost.

When changing via the GUI, Windows asks for the Current password, for which the SHA1 hash is then stored away in a special file: the CREDHIST file, found in the user %APPDATA%\Microsoft\Protect\ folder.

Changing your password this way does not render the DPAPI encrypted data useless.

Again the CREDHIST file is a binary, hex-formatted data structure which contains one non-optional field: the GUID for the CredHistPool. Followed by a list of CredHist entries, each older entry is encrypted with the SHA1 hash of the more recent password. Turning the CREDHIST file into a history chain structure, where each entry contains the password both in the NTLM format as well as the SHA1 format.

So no clear text passwords can be found in this CREDHIST file and it is only used when changing passwords via the GUI (e.g. when pressing Ctrl+Alt+Del > Change a Password).

System Master Keys

Every system has System Master Keys that are used to encrypt data that must be accessible for every user. These can be found in the folder: %windir%\System32\Microsoft\Protect\S-1-5-18 (and the subfolder “User”)

Again multiple Master Keys, the Preferred file contains the GUID to use

The structure and formatting of the System Master Keys is exactly the same as the User Master Keys, the only difference is the way they are decrypted: not with user password hash and SID, but with the LSA DPAPI secret key.

Inside the Registry file %windir%\System32\config\SYSTEM lays a system unique DPAPI key, it is encrypted with the Syskey which is to be extracted from the %windir%\System32\config\SECURITY file. Multiple tools exist to extract these on- or offline (e.g. lsadump.py from CredDump 7).

Extracting the DPAPI System Key, starting with 01 00 …

The extracted DPAPI System Data is actually only 44 Bytes with the first 4 Bytes being the version, the next 20 Bytes are the “User Cred” and the final 20 Bytes are the “Machine Cred”. For some reason the “User Cred” is the one used the most to actually decrypt the System Master Keys.

Learn by example

So what is needed to decrypt User Blobs? A special framework exists called DPAPICK, which is written in Python2 and requires older crypto modules like M2Crypto and an older version of construct.
Built on top of this framework is a nice list of scripts called DPAPILAB, also written in Python2.

However: for this research I adjusted and/or recreated all of the scripts from both DPAPICK as DPAPILAB and made them work on Windows and Linux, in Python3 and without the need of M2Crypto (now pycryptodome).
All next code examples are from this new and improved framework called DPAPILAB-NG, created especially for offline decryption of Windows secrets.

>> https://github.com/tijldeneut/dpapilab-ng

So what is needed to decrypt a User based DPAPI Blob? E.g. the one from PowerShell earlier?
The blob itself, the user master keys, the users’ SID and the user password or SHA1 hash from the user password encoded as UTF-16LE.
In this example, the user password is “123”, which means the SHA1 hash is 0d5399508427ce79556cda71918020c1e8d15b53

This can be done in steps:

  1. The DPAPI blob from above is stored on disk with a PowerShell command like
    Set-Content crypted.dat -Value $EncryptedBytes -Encoding Byte
  2. Look at the meta data in the blob, it should show the Master Key GUID:
    blobinfo.py crypted.dat
  3. Look at the meta data of the User Master Keys, it will list all data for all MKs:
    mkinfo.py %APPDATA%\Microsoft\Protect\S-1-5-21-1382274214-3906649457-1162072392-1001
  4. Decrypt the needed User Master Key:
    mkudec.py %APPDATA%\Microsoft\Protect\S-1-5-21-1382274214-3906649457-1162072392-1001\c49e2090-e2d9-4ea4-a2ae-3bb87f5f8385 --sid=S-1-5-21-1382274214-3906649457-1162072392-1001 --pwdhash=0d5399508427ce79556cda71918020c1e8d15b53
  5. Now the blob can be decrypted with the, now unlocked, User Master Key (either the full or the SHA1 hash):
    blobdec-with-masterkey.py crypted.dat --masterkey=705f574acbeaf81fff0a9cd93c9a44535db30457

One Command
All off the above can be done in only one command:
blobdec.py --masterkey=%APPDATA%\Microsoft\Protect\S-1-5-21-1382274214-3906649457-1162072392-1001 --sid=S-1-5-21-1382274214-3906649457-1162072392-1001 --password=123 crypted.dat

Notice that there also options like –credhist (for older blobs) and –entrop_hex (some third party tools require extra data)

System DPAPI Blobs
Are very similar, but instead of the user SID and password (hash), they require the SYSTEM and SECURITY hives.

These can be extracted as administrator to the local folder with:

An encrypted file called crypted-as-system.dat could then be decrypted like this:
blobdec.py --system=SYSTEM.hive --security=SECURITY.hive --masterkey=%windir%\System32\Microsoft\Protect\S-1-5-18\ crypted-as-system.dat

Putting it all together

These visuals try to provide an idea on where the data is coming from and how DPAPI puts everything together.

Decrypting a User DPAPI blob The thick lined boxes are Data Input

Decrypting a System DPAPI blob

First conclusion

This is the basics of DPAPI: although most blobs are buried somewhere in the filesystem in other structures the decryption will always happen according the structures and examples in this article.

A real-life example would be your Wi-Fi profiles, which are stored in

When looking at such an XML file for a Wi-Fi profile with a Pre Shared Key, notice that data of the “keyMaterial” tag will start with “01000000D08C9DDF…”, which is a DPAPI Blob encrypted with the System DPAPI Keys from the folder

For the OpenVPN community client the DPAPI Blob is a User DPAPI encrypted blob with entropy, both can be found in the Windows registry.

OpenVPN usage of User based DPAPI

The Eye Opener

However: if the User DPAPI blobs are encrypted with the SHA1 hash of the user password, which is not stored on disk. What happens when a user logs in using a PIN, Facial Recognition, Picture Password etc … ?

à It turns out that as soon as any Windows Hello Credential (as the options above are called) is used, the Clear Text User Password (thus NOT even the SHA1 hash) is stored On Disk!

An example would be the Picture Password, enabling this will save the Windows clear text user password in a System DPAPI blob that is part of the Windows Vault structure, this structure is located at

This means that decrypting the Windows User Password can be as simple as this command:
vaultdec.py --masterkey=\Windows\System32\Microsoft\Protect\S-1-5-18\User --system=system --security=security %windir%\System32\config\systemprofile\AppData\Local\Microsoft\Vault\4BF4C442-9B8A-41A0-B380-DD4A704DDB28

In case of a PIN it is being stored in an entirely different way, which has different names: Microsoft NGC or Next Gen Cryptography or DPAPI-NG.

References Part 1

[1] https://www.passcape.com/windows_password_recovery_dpapi
[2] https://www.passcape.com/index.php?section=docsys&cmd=details&id=28
[3] https://github.com/jordanbtucker/dpapick
[4] https://github.com/dfirfpi/dpapilab


NGC comes by many names and many usages. This Next-Gen-Cryptography is sometimes called CNG DPAPI or DPAPI-NG and was introduced in Windows 8.

It makes use of the concept of having multiple Security Providers, such as “Microsoft Software Key Storage Provider” or “Microsoft Platform Crypto Provider”.
The common DLL’s in the Windows subsystem that are responsible for DPAPI-NG usually start with “ncrypt”: ncrypt.dll, ncryptprov.dll and ncryptsslp.dll. These API’s speak to the lsass provider in memory which in turn speaks to the required DPAPI subsystems as required.

Learn by example

The starting point is the Windows NGC folder:

>> Note: Accessing this folder requires specific permissions that do not include the Administrator: SYSTEM privileges

The different pieces of the puzzle will be detailed out with some code and key examples and one specific scenario will be used: “Decrypting a clear text Windows Login Password hidden behind a Windows Hello PIN code”. For our example, this example assumes a 4 digit numeric PIN code, although it does not matter.

The base: parsing Ngc files

The Ngc folder contains encrypted data and metadata, but no keys. Instead of putting it all into a couple of files, its actually stored into a file structure which contains just dat-files: 1.dat, 6.dat, 7.dat etc …

NGC folder contents for GUID {FD22DDF9-0421-440A-BD66-88984127198E}

Within the Ngc folder, there is a GUID for each provider and user that is initialized, when opening the GUID folder, there are some dat-files which contain the metadata about the provider (7.dat) and the user SID (1.dat)

Next, there is a subfolder called “Protectors”, which holds a list of protected data bytes, presented as dat-files inside a subfolder which is just called 1:
                contains the Key GUID {AA8C34F7-EAFE-467A-958B-FEFB4C9F065C}
                contains the encrypted data. This is actually the only encrypted data in this entire folder.

  • This Ngc data is RSA encrypted and requires a private key which is itself DPAPI encrypted with the Windows Hello PIN. This RSA private key can be found in the Crypto folder (see later) and will carry GUID {AA8C34F7-EAFE-467A-958B-FEFB4C9F065C}

So {AA8C34F7-EAFE-467A-958B-FEFB4C9F065C} as the Key 1 GUID and
e.g. 748da00958e9c4344b3892786de6f2665f251df… (256 bytes in total) as the encrypted InputData

With NGC there are actually two separate RSA decryption rounds.
So there is also at least one extra GUID folder which holds at least one other subfolder, this contains the metadata such as the key GUID needed for the 2nd phase of the decryption later.
This 2nd key is also stored in dat-files:
                contains the key ID, such as //9DDC52DB-DC02-4A8C-B892-38DEF4FA748F
                contains the key GUID, such as {89C3C960-905C-43C2-B0A3-D78BAAB83665}

  • Key ID //9DDC52DB-DC02-4A8C-B892-38DEF4FA748F is a static ID for a 2nd round RSA Key GUID

Crypto Keys Round 1

This phase is what happens inside “ncrypt.dll” when provided with the correctly encoded Windows Hello PIN code.

In the folder above, multiple Private Keys can be found, one per file. All of them contain some metadata and two System DPAPI blobs.

This system has 4 different keys (3 RSA type and 1 ECS)

The metadata includes the key type (RSA or ECS), the Key GUID and the Public Key in clear text. This means no DPAPI is needed to encrypt a secret using DPAPI-NG.

The first DPAPI blob contains the Private Key Properties, which can be decrypted with a System DPAPI key (so when provided with the System Masterkeys, SYSTEM and SECURITY hives) and a static entropy string “6jnkd5J3ZdQDtrsu” (null terminated)
A DPAPI entropy is added to the DPAPI decryption algorithm as a concatenation with the DPAPI Blob salt (see first chapter). Using this entropy, the System DPAPI decryption of the Private Key Properties is possible.

These RSA Private Key Properties contain two important fields:
SmartCardPin PBKDF2 Salt:         f75e939f (4 Bytes)
SmartCardPin PBKDF2 Rounds: 0x2710 or 10000

  • SmartCardPin is the official NcryptSetProperty string from Microsoft
  • Using these key properties and the user PIN key, the RSA Private Key data can be decrypted
  • ECS Private key data can be decrypted in the exact same way as the Private Key Properties, but the static entropy string is now “xT5rZW5qVVbrvpuA” (null terminated)

Decrypting the RSA Private Key data using a Windows Hello PIN key

In the example above, a PIN like 1397 would first be converted into 3100330039003700 and then end up looking like 33003100330033003300390033003700 which is fed into a SHA256 PBKDF2 key derivation, with salt f75e939f and 10000 rounds. This results in 93c3ccf613a271a326ebd8a1942863ed706c64dbb8f1959b75222f0194cc05da.
These 32 Bytes are then converted to uppercase and again rewritten as UTF-16LE
and after a SHA512 hash this results in the extra entropy value:

The DPAPI Blob Salt, the Private Key Entropy and the new PIN-based hash are concatenated to eventually DPAPI decrypt the RSA Private Key data

RSA Private Key data to RSA Private Key

The resulting RSA Private Key, is not the private key itself, but actually a so called “BCRYPT RSA Private Key BLOB” [2] of size 539 Bytes and starting with ASCII string “RSA2”.
This Private Key BLOB contains the Modulus “n” (which is the Public Key), the exponent “e”, prime1 “p” and prime2 “q” (where n = p*q). Which makes it possible to actually construct the RSA Private Key.

Constructing the RSA Private Key given the p, q and e factors.

RSA Decrypt NGC Input Data

  • With the RSA Private Key from Round 1 , the NGC input data from step1 can finally be decrypted and we end up with 108 Bytes, that contain 3 new “PINs” of 32 Bytes each, one of them is called the “Decrypt PIN”.

    Which is the data required for Round 2 of Crypto Keys: 2e95e3be76cbee4e98aacd508900d0d60a2c42b42f44afc018d8776c6b909023

Crypto Keys Round 2

All steps from Round 1 are now to be repeated (in practice this would be a new API Call to ncrypt.dll).

The required data for this Round 2 is:

The NGC Key 2 GUID for Key ID //9DDC52DB-DC02-4A8C-B892-38DEF4FA748F:
And the decrypted “Decrypt PIN” from Round 1:

So this means repeating the steps from Round 1:

  • DPAPI Decrypt the Private Key Properties for Key GUID {89C3C960-905C-43C2-B0A3-D78BAAB83665}
     which include PBKDF2 Salt and Rounds
  • Perform the SHA256 PBKDF2 Key Derivation and subsequent SHA512 hash to get the SmartCardPin
  • Use that SmartCardPin to DPAPI Decrypt the Private Key data itself

  • Eventually ending up with a 2nd RSA Private Key, this RSA Private Key can be used to decrypt an AES256 Key
  • This RSA Encrypted AES256 key can be in several places: for example the Windows Vault:

Decrypting Windows Vault


There are System Vaults which use System DPAPI MasterKeys to encrypt the secrets, like the location above or a 2nd location like %programdata%\Microsoft\Vault\
But there are also several User Vaults that, of course, use User DPAPI MasterKeys (based on the user password) to decrypt the secrets: %localappdata%\Microsoft\Vault\

VSCH files are Vault Schema’s (holding the Vault Layout) and VCRD files the encrypted Vault Credentials.

  • In case a Windows Operating System is “protected” via a Windows Hello Picture Password, then the Cleartext Windows Login Password can simply be decrypted using a System DPAPI MasterKey

For this system the Windows Logon password was “waza1234/-”

There are several different Schema Types:

  • 3e0e35be-1b77-43e7-b873-aed901b6275b = Domain Password
  • e69d7838-91b5-4fc9-89d5-230d4d4cc2bc = Domain Certificate
  • 3c886ff3-2669-4aa2-a8fb-3f6759a77548 = Domain Extended
  • b2e033f5-5fde-450d-a1bd-3791f465720c = Pin Logon
  • b4b8a12b-183d-4908-9559-bd8bce72b58a = Picture Password
  • fec87291-14f6-40b6-bd98-7ff245986b26 = Biometric
  • 1d4350a3-330d-4af9-b3ff-a927a45998ac = Next Generation Credential

And in case of an NGC Windows Hello PIN code encryption, the vault actually contains an entry of type “Next Generation Credential”, which is a DPAPI Blob that holds the User SID, the RSA Encrypted AES Key (“EncData” in the screenshot above), the AES IV and the AES Encrypted user password.

  • Inside the NGC vcrd file, there is actually a typo: the NGC VCRD file contains the text “NGC Local Accoount Logon Vault Resource”

Final Decryption and putting it all together

The final parts can now be combined:

  • RSA Private Key from Crypto Round 2
  • RSA Encrypted AES256 Key from the Windows Vault
  • IV for AES Decryption
  • Encrypted Password

First the RSA Private Key is used to decrypt the EncData, which is then used as the key for an AES256 decryption together with the IV and Encrypted Password.

Final Decryption of the NGC Password

Full decryption scheme of DPAPI-NG


This new toolset is a redevelopment in Python 3 of the original DPAPILAB toolset with some extensions on DPAPI-NG (or NGC). The features include:

  • Dependencies are as low as possible, the construct library is only needed for working with “vaultdec.py”
  • All scripts starting with ngc are completely new and created especially for working with NGC data
  • Works equally well on- as well as offline, both in Linux and Windows
  • They all expect arguments to point to the separate folders, so it is clear which data is used from where
  • It supports a PIN brute force option, by default it walks through all PIN’s from 0000 to 9999, but this can be changed in code
  • When learning, the script _NGC_Step_by_step_on_and_offline.py -h can be used to get a guided introduction on extracting all required data parts

Go and find it here, all feedback is welcome:

Closing Remarks & Mitigation

Why two similar Crypto Keys rounds?

When using a TPM chip, the “DecryptPIN” is no longer stored in the Ngc folder as “InputData” but can be found inside the TPM chip. The file 15.dat will actually be gone and the Ngc Crypto Provider will no longer be “Microsoft Software Key Storage Provider” but rather “Microsoft Platform Crypto Provider”.

It is however still possible to extract the data from the TPM chip programmatically, although this must be done on a live system. The required Mimikatz commands are included in the scripts and a PowerShell version is underway.

It is still a strange decision from Microsoft to decide not to store hashes on disk, but rather Clear Text passwords.

TPM as a mitigation will surely help, but BitLocker, secure backups and secure backup channels, network segmentation and training people to lock their workstation is at least equally important.
As well as not using PIN or Picture passwords

References Part 2

[1] https://docs.microsoft.com/en-us/windows/win32/seccng/cng-dpapi
[2] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/540b7b8b-2232-45c8-9d7c-af7a5d5218ed
[3] https://github.com/gentilkiwi/mimikatz
[4] https://www.passcape.com/index.php?section=blog&cmd=details&id=26

Eén reactie

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Deze site gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.