May 18 2022 | Matt Merrill

EntropyCapture: Simple Extraction of DPAPI Optional Entropy



During a short application assessment, enumeration and decryption of a third-party application’s Windows Data Protection API (DPAPI) blobs using SharpDPAPI produced non-readable data because optional entropy was being used. This may be common with applications that use DPAPI to protect sensitive data (e.g., configurations, passwords, user information, etc.). Although traditionally, many operators focus on identifying and reverse engineering the binary that is protecting and unprotecting the data, this was not an option due to operational time constraints. The approach covered in this blog post will describe the process I followed to write the simple tool EntropyCapture that will extract the DPAPI optional entropy using API hooking. Capturing the optional entropy provides the ability to decrypt the sensitive DPAPI blob back to readable data, and may provide additional information to be used in an attack path.

API Hooking

In simple terms, API hooking is intercepting a function call from a program and redirecting it to another function. This is possible by patching the target function in-memory to redirect to the other function, which then will return back to the original function. There are many ways to approach API hooking, but for this blog post only Microsoft Detours library and API Monitor will be used.

Microsoft Detours library is open-source and supports 32-bit and 64-bit processes, in addition it is rather lightweight making it appealing for offensive tool development and remote operations.

What functions to Hook

DPAPI uses a small set of functions to protect and unprotect data, making the target functions easy to identify. Hooking the DPAPI functions CryptProtectData() and CryptUnProtectData() will allow us to capture and write out the optional entropy passed during the API call.

For demonstration purposes a simple console application will be used, this application calls those functions stated above and sets the pOptionalEntropy parameter to “EntropyTest” displayed in the code snippet below:

Figure 1 — Sample Application With Optional Entropy

After executing the sample console application with API Monitor attached, we can see the DPAPI functions called and display the pOptionalEntropy value:

Figure 2 — API Monitor Displaying Entropy Value


Now that we know which functions to hook and how to capture the optional entropy value, we can build a simple tool to automate this process.

EntropyCapture is a standalone DLL that, when injected into a process that is using optional entropy, will perform the API hooking, capture the entropy, and write the value to a file.

Converting the DLL into shellcode using the sRDI project allows the included aggressor script to monitor and inject into the provided process name. When started, EntropyCapture will retrieve a process list, search for the provided application name, and then inject into it.

When the aggressor script is loaded into Cobalt Strike, the following new commands are available:

  • start_entropyCapture [process name] — Starts checking for the stated process and injects into them.
  • stop_entropyCapture — Stops checking but will not unload the already loaded DLL.
  • show_entropyCapture — Prints the contents of the file showing the captured entropy.

Short Operational Scenario

During an assessment, you are performing system enumeration looking for potentially interesting DPAPI files using SharpDPAPI. While searching through the “Program Files” directory, a config file was identified to be a DPAPI blob.

Figure 3 — SharpDPAPI Search Command
SharpDPAPI search /type:folder /path:”C:Program FilesDemo”

Trying to decrypt the Config.dat file using the required masterkey, that was obtained using the SharpDPAPI ‘masterkeys/machinemasterkeys’ command, provided non-readable data after converting the hexadecimal “dec(blob): 93 C3 51 7A 4D 24 C8…” value back to ASCII.

Figure 4 — SharpDPAPI Decrypt Without Entropy
SharpDPAPI blob /target:”C:Program FilesDemoConfig.dat” [masterkey]

Non-readable data can be indicative of optional entropy being set, to successfully decrypt the Config.dat file we need to obtain the optional entropy value that will be used in the decryption process.

First and foremost, the process that is performing the encryption/decryption of the blob of interest will need to be identified. In the case of this demo, the process that is performing the encryption/decryption of the Config.dat file is Demo.exe. To capture the optional entropy using EntropyCapture is pretty simple following the general steps listed below:

  • Load the EntropyCapture.cna script into CobaltStrike
  • Execute start_entropyCapture command with the identified process name start_entropyCapture Demo.exe
  • Display the captured entropy using show_entropyCapture
  • Execute stop_entropyCapture to stop the process monitoring
Figure 5 — EntropyCapture Usage

Now that the optional entropy has been captured, we can successfully decrypt the config file using SharpDPAPI with the /entropy option displayed below.

Figure 6 — SharpDPAPI Decrypt With Entropy
SharpDPAPI blob /target:”C:Program FilesDemoConfig.dat” [masterkey] /entropy:[Hex String]

After converting the hexadecmial “dec(blob): 70 61 73 73 77 6F 72…” value back to ASCII we get an interesting value “password=JH*GBFSDF_S(Boubuerv” that may be useful during an assessment or in context to the application.

Wrap Up

Many applications use DPAPI to store sensitive data on clients, but they don’t always use the optional entropy parameter. When the optional entropy was used by an application it required additional time to disassemble and manually identify the entropy value. With the use of EntropyCapture this helps to reduce that time that could be used elsewhere. In addition, the data protected by applications can be any sort of information (passwords, api keys, hashes, etc), and if successfully extracted could be that missing piece to the puzzle.


EntropyCapture source code is available here.

EntropyCapture: Simple Extraction of DPAPI Optional Entropy was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.