Chrome App-Bound Encryption Bypass
What It Does
Chrome 127+ introduced App-Bound Encryption (ABE) to protect the master encryption key stored in Local State. Unlike legacy DPAPI, ABE binds the key to the browser process identity via a service-specific secret. Malware that previously relied on CryptUnprotectData (which works for any process running as the same user) must now either:
- Inject into the browser process and call the browser's own decryption routines
- Use a Chrome extension with elevated privileges that can access the ABE key
- Extract the
app_bound_encrypted_keyfield fromLocal Stateand decrypt it with the correct service identity
This technique page documents the third approach, observed in a standalone harvester DLL.
Detection / Fingerprint
Static indicators of ABE-aware malware:
- String
app_bound_encrypted_keyoraster_app_bound_encrypted_keyin the binary - Debug/log string
NO_ABE:Browser uses legacy DPAPI encryption (App-Bound Encryption not enabled)— indicates graceful fallback - Debug prefix
ASTER_KEY:or similar — developer/project marker for decrypted ABE material BCryptOpenAlgorithmProvider+BCryptGenerateSymmetricKey+BCryptDecryptimports (CNG AES)CoInitializeEx+CoCreateInstanceimports (COM interop for DPAPI fallback)CryptStringToBinaryAimport (Base64 decode of the ABE key field)
Implementation Patterns Observed
In sample 9d3d5ac0 (MSVC 14.50 x64 DLL):
- Reads
Local StateJSON from%LOCALAPPDATA%\Google\Chrome\User Data\ - Checks for
app_bound_encrypted_keyfield - If present: Base64-decode via
CryptStringToBinaryA, then AES-decrypt viabcrypt.dllCNG APIs - If absent or ABE fails: falls back to legacy DPAPI path (
CryptUnprotectDatavia COM) - Uses the recovered master key to decrypt
os_crypt.encrypted_keyand then browser SQLite databases
Reproduce on Your Own VMs
Not yet fully reproducible — the ABE service identity secret is not publicly documented. To replicate:
- Set up a Windows 11/Chrome 127+ VM
- Enable ABE in Chrome flags (
chrome://flags/#app-bound-encryption) - Save a password in Chrome to generate
app_bound_encrypted_key - Build a test tool that:
- Reads
Local StateJSON - Extracts
app_bound_encrypted_key - Attempts
BCryptDecryptwith various AES modes (CBC, GCM, CCM) - Falls back to
CryptUnprotectDataif ABE fails
- Reads
- Compare behavior against a known ABE-enabled profile
Research target: determine the exact AES mode, key derivation, and service identity binding used by Chrome's ABE implementation.
Defensive Countermeasures
- Enable ABE in Chrome 127+ (default on for enterprise; consumer rollout ongoing)
- Monitor for
Local Statereads by non-browser processes — high signal when combined with SQLite file access - Detect
app_bound_encrypted_keystring presence in non-browser binaries - Application Control (WDAC/AppLocker): block unsigned DLLs from loading in browser contexts
Pages Where Observed
- unclassified-msvc-browser-credential-harvester — primary sample
9d3d5ac0 - browser-credential-harvesting — cross-family concept page