
Unpacking the AAD Broker LocalState Cache
Deep technical teardown of the Entra ID (Azure AD) Broker's LocalState cache on Windows 11, reverse-engineering the file naming scheme derived from identity material, the AES-GCM/DPAPI-wrapped Packer::V3 format inside AAD.Core.dll, and the JSON/binary serialization of AuthenticationContext objects used for PRT and per-application authority files. The author shows how to decrypt cached PRT and authority token files, derive the TPM-bound PRT session key via NCryptKeyDerivation (replicating mimikatz's dpapi::cloudapkd), and extract cached access/refresh tokens and JWTs — giving an attacker with local SYSTEM context a path to long-lived, MFA-bypassing cloud access and rich identity reconnaissance data. Companion extraction code is released as AADBrokerDecrypt on GitHub.
What it is
A reverse-engineering teardown of the Entra ID (Azure AD) Broker's LocalState cache on Windows 11 24H2 (build 26100.4946), located at <LocalAppData>\Packages\Microsoft.AAD.BrokerPlugin_<PublisherId>\LocalState. Companion tooling: AADBrokerDecrypt (github.com/jackullrich/AADBrokerDecrypt).
How it works
Filenames encode identity material: <PublisherId> is Base32(SHA256(publisher string)[:8]); cache entries use prefixes u_ (UPN), p_ (PRT authority), c_ (client/app ID), a_ (authority) — each a 24-char token from SHA-1 of the input, encoded with the broker's custom Base32-hex alphabet via StringUtility::FileSysName. Full path pattern: u_<UPNID>\c_<CLIENTID>\a_<AUTHID>.<ext>, where <ext> reflects logon type (def/pwd/ngc/scd/fido).
Packed files start with a UTF-8 BOM and a 3-1 (encrypted) or 3-0 (hashed) header tag; stripping these reveals a Base64 ASN.1 blob holding a DPAPI-protected KEK (262 bytes), an RFC 3394-wrapped CEK (40 bytes), a 12-byte IV, and AES-GCM ciphertext. Unprotecting the KEK (in the user's security context) unwraps the CEK, which decrypts the content. The plaintext is zlib-compressed (4-byte unknown header + zlib stream); inflating it yields a serialized AuthenticationContext object — either JSON (magic 0x13/19, with a JsonHeader{Magic,Size}) or a custom length-prefixed-string binary format (magic values 5–18), which the author recommends string-extracting rather than fully parsing.
The PRT session key (prt.sk_val in the unpacked JSON) is itself base64 + legacy-DPAPI-wrapped with a machine key, revealing an SkBlobHeader{Version, SkGuidLength, OpaqueKeyLength} structure containing an NGC key GUID (also visible at HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Ngc\KeyTransportKey\...\TpmKeyTransportKeyName) and an opaque TPM-bound key blob. The session key is derived by opening the named key via NCryptOpenKey against MS_PLATFORM_CRYPTO_PROVIDER (requires temporarily elevated privileges), importing the opaque blob with NCryptImportKey(..., NCRYPT_OPAQUETRANSPORT_BLOB, ...), then calling NCryptKeyDerivation with KDF label "AzureAD-SecureConversation" and NCRYPT_SHA256_ALGORITHM — the same logic as mimikatz's dpapi::cloudapkd /keyvalue:<OpaqueKey> /keyname:<SK-GUID>.
Authority (a_) files use the same pack/unpack scheme but store per-app cache[] entries containing access tokens (tkn) and ID tokens (id_tkn) as raw JWTs, plus rt (refresh token) fields.
Preconditions / Affected
Windows 11 (tested on 24H2/26100.4946). Decrypting the KEK requires the user's security context; deriving the TPM-bound PRT session key requires local SYSTEM-level privilege elevation to open the NGC key via the platform crypto provider.
What to do
mimikatz.exe dpapi::cloudapkd /keyvalue:<OpaqueKey> /keyname:<SK-GUID>Use AADBrokerDecrypt to locate and unpack u_/p_/c_/a_ cache files and extract cached JWTs/refresh tokens; the repo also includes the Base32 PublisherId derivation and a naive string-extractor for the binary-serialized (magic 5–18) authority files.
Caveats
The author notes the 3-0 (hash-only) header exists in the packing code but was never observed on the analyzed machine. Full reverse engineering of the custom binary serialization (magic 5–18) was not completed — string extraction is a workaround, not a parser. The author states replay of derived session keys elsewhere depends on TPM binding and local privilege level, and calls for further research into what the cached metadata enables.
Organisations named here
- AAD Broker
- Primary Refresh Token (PRT)
Technologies named here
- Azure AD Broker
- AADBrokerDecrypt
- Mimikatz
- Windows 11 24H2
- AAD.Core.dll
- Sysinternals strings
- Microsoft Entra ID
- Windows
Techniques named here
- AAD Broker LocalState cache unpacking
- CEK unwrapping and AES-GCM decryption
- zlib decompression of serialized payload
- AuthenticationContext deserialization
- PRT session key extraction and derivation
- Package ID derivation
- Cache filename derivation
- Token theft and reuse from authority files
- Session key impersonation for silent token renewal
- JWT inspection from cached tokens
Related in Offensive Security