9d3d5ac032a3d26671c21b3b8832c46785f30523b3631ff2d59d5eaf3494d661unclassified-msvc-browser-credential-harvester: 9d3d5ac0 — MSVC 14.50 x64 DLL with Chrome App-Bound Encryption bypass, SQLite 3.49.1, Bootstrap reflective loader
Executive Summary
A 1.02 MB MSVC 14.50 x64 DLL compiled in April 2026. Single export Bootstrap at 0x18002FA88. No packing, no obfuscation, no Authenticode signature. Statically links SQLite 3.49.1 and carries a full browser-credential harvesting toolchain targeting Chrome, Brave, Edge, and Firefox. Notable for explicit handling of Chrome's newer App-Bound Encryption (ABE) (app_bound_encrypted_key, ASTER_KEY:) with a graceful fallback to legacy DPAPI. No network APIs in the IAT — this is a pure extraction module; exfiltration is handled by a separate stage. Static-only analysis (CAPE skipped — no Windows guest).
What It Is
| Field | Value |
|---|---|
| SHA-256 | 9d3d5ac032a3d26671c21b3b8832c46785f30523b3631ff2d59d5eaf3494d661 |
| File type | PE32+ executable (DLL) (GUI) x86-64, 6 sections ^[file.txt] |
| Size | 1,047,040 bytes (1.02 MB) |
| Compiler | MSVC 14.50 (Visual Studio 2022) ^[exiftool.json] |
| Timestamp | Wed Apr 22 05:56:01 2026 UTC ^[pefile.txt:38] |
| Signed | No ^[rabin2-info.txt] |
| Packing | None |
| Sections | .text (code, entropy 6.57), .data, .pdata, .idata, .fptable (entropy 0.0), .reloc ^[pefile.txt:79-199] |
| Entry point | 0x1800E3F5C ( falls inside .text) ^[pefile.txt:54] |
| Export | Bootstrap @ 0x18002FA88 (1 function, 1 name) ^[pefile.txt:267-268] |
| Debug | IMAGE_DEBUG_TYPE_POGO (Profile-Guided Optimization) ^[pefile.txt:575] |
| GuardCF | Enabled (SecurityCookie, GuardCFCheckFunctionPointer) ^[pefile.txt:528-532] |
| PIC | Yes (pic: true in rabin2) ^[rabin2-info.txt] |
| SQLite | 3.49.1 statically linked (source ID 873d4e274b...) ^[strings.txt:1474] |
How It Works
The binary is a browser credential extraction module designed to be loaded reflectively (the Bootstrap export) or via normal DLL load. It does not contain any network exfiltration logic — it writes harvested data to JSON files on disk (fingerprint.json, cookies.json, passwords.json, etc.) and relies on a companion stage for upload.
Browser Targeting
Strings reveal deep Chrome/Brave/Edge knowledge ^[strings.txt:249-314]:
Chrome,Brave-Browser,Microsoft\Browser,chrome,chrome-betaUser Data,Local State,Default,Preferences,ExtensionsLogin Data,Login Data For Account,Cookies,Web DataNetwork,autofill,credentials_enable_service,safebrowsing
App-Bound Encryption Bypass
This is the distinguishing capability. Chrome 127+ introduced App-Bound Encryption to protect Local State keys even from Local System. This sample explicitly handles both paths:
app_bound_encrypted_key— the new ABE field in ChromeLocal State^[strings.txt:328]aster_app_bound_encrypted_key— variant/prefixed field name ^[strings.txt:332]ASTER_KEY:— debug/log prefix for decrypted ABE key material ^[strings.txt:333]NO_ABE:Browser uses legacy DPAPI encryption (App-Bound Encryption not enabled)— graceful fallback path ^[strings.txt:330]
The presence of both ABE and DPAPI fallback strings, plus DecryptData failed: 0x ^[strings.txt:341], indicates a two-path decryption routine: try ABE first, fall back to CryptUnprotectData (implied by DPAPI references and CoInitializeEx for COM interop).
SQLite Aggregation
The binary embeds the full SQLite 3.49.1 engine (source ID 873d4e274b4988d260ba8354a9718324a1c26187a4ab4c1cc0227c03d0f10e70) ^[strings.txt:1474]. It uses SQLite to query browser databases:
- Cookies:
SELECT host_key, name, path, is_secure, is_httponly, expires_utc, encrypted_value FROM cookies^[strings.txt:360] - Passwords:
SELECT origin_url, username_value, password_value FROM logins^[strings.txt:369] - Cards:
SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards^[strings.txt:375] - IBANs:
SELECT value_encrypted, nickname FROM local_ibans^[strings.txt:382] - Tokens:
SELECT service, encrypted_token, binding_key FROM token_service^[strings.txt:386]
Fingerprinting
Before extraction, the binary builds a fingerprint.json containing:
- Browser version, executable path, user data path
- Profile count, computer name, Windows user
- OS version (via
RtlGetVersion) ^[strings.txt:317] - Architecture
- Sync status, enterprise management, update channel
- Default search engine, hardware acceleration, metrics, autofill, password manager, safe browsing, DNT, third-party cookie blocking, translate status ^[strings.txt:260-306]
Output Files
Harvested data is written to:
fingerprint.jsoncookies.jsonpasswords.jsonpasswords_account.jsoncards.jsoniban.jsontokens.json^[strings.txt:353-359]
Anti-Analysis
Minimal but present:
IsDebuggerPresent^[pefile.txt:471]QueryPerformanceCounter+GetTickCounttiming ^[pefile.txt:451-452]CreateMutexWfor single-instance gating ^[pefile.txt:414]- No VM-specific checks observed
Decompiled Behavior
Bootstrap Export (0x18002FA88)
Radare2 decompilation of sym.chrome_decrypt.dll_Bootstrap reveals a reflective-loader stub nested inside a legitimate MSVC DLL ^[r2:sym.chrome_decrypt.dll_Bootstrap]:
- PE validation: checks MZ (
0x5A4D) and PE (0x4550) signatures at the module base. - PEB walking: reads
gs:[0x60](PEB), follows+0x18(LDR), then+0x20(InMemoryOrderModuleList) to enumerate loaded modules. - Export hash resolution: iterates exports with
ror r9d, 0xD(ROR13 hash algorithm), comparing against hardcoded hashes0x6a4abc5band0x3cfa685d. - API pointer caching: resolved function pointers stored in a local stack array (
[rbp + rbx*8 - 0x80]).
This is a classic position-independent shellcode pattern, suggesting the Bootstrap export is designed for injection scenarios where the Windows loader has not fixed the IAT. The DLL's normal import table (100+ APIs) is available for non-injected use.
Import Surface
Cryptography / DPAPI:
bcrypt.dll:BCryptOpenAlgorithmProvider,BCryptGenerateSymmetricKey,BCryptDecrypt,BCryptDestroyKey,BCryptSetProperty,BCryptCloseAlgorithmProvider^[pefile.txt:280-285]CRYPT32.dll:CryptStringToBinaryA(Base64 decode) ^[pefile.txt:343]
COM / OLE (for DPAPI and browser interop):
ole32.dll:CoInitializeEx,CoCreateInstance,CoSetProxyBlanket,CoUninitialize,CoTaskMemFree^[pefile.txt:295-299]OLEAUT32.dll:SysAllocStringByteLen,SysFreeString,SysStringByteLen(by ordinal) ^[pefile.txt:309-311]
System / Process:
CreateThread,CreateToolhelp32Snapshot,Process32FirstW,Process32NextW,TerminateThread^[pefile.txt:379-396]VirtualProtect,CreateFileMappingW,MapViewOfFile,UnmapViewOfFile^[pefile.txt:417-450]GetUserNameA,GetComputerNameA,RtlGetVersion,GetNativeSystemInfo^[pefile.txt:353,382,378]SHGetKnownFolderPath(for locating browser profile directories) ^[pefile.txt:321]
File / Mutex:
CreateMutexW,WaitForSingleObject,WaitForSingleObjectEx^[pefile.txt:390,414,429]CreateFileW/A,ReadFile,WriteFile,DeleteFileW/A,SetEndOfFile,SetFilePointer^[pefile.txt:385-428]
No WinInet, WinHTTP, WS2_32, URLMon, or SMTP APIs are imported. Exfiltration is not this module's job.
C2 Infrastructure
None recoverable from static analysis.
No hardcoded domains, IPs, URLs, webhooks, or paste sites. No network imports. The binary writes harvested data to local JSON files and expects a companion stage to handle exfiltration. This is a deliberate separation of concerns: the harvester stays small and focused, while the downloader/exfiltrator carries the network risk.
Interesting Tidbits
- The
ASTER_KEYprefix (ASTER_KEY:) is unique in this corpus. It may be a developer handle, a project codename, or simply a prefix chosen to avoid collisions. No other sample in the wiki references it. ^[strings.txt:333] .fptablesection with entropy 0.0 suggests a pre-computed float lookup table — possibly for fast entropy calculations or crypto operations. ^[pefile.txt:162-179]- SQLite 3.49.1 is very recent (Feb 2025 source ID). The malware author rebuilt SQLite from source or linked a static library from a recent distribution. ^[strings.txt:1474]
chrome_decrypt.dllas the module name in the export directory is unusually honest for malware. It advertises its purpose. ^[pefile.txt:268]- No wallet/crypto strings — this is a browser credential harvester, not a crypto-wallet clipper. The focus is on cookies, passwords, saved cards, and IBANs.
- GuardCF enabled — unusual for malware; adds legitimate software camouflage and complicates certain hooking techniques.
How To Mess With It (Homelab Replication)
Toolchain
- Visual Studio 2022 (MSVC 14.50)
- Target: x64 DLL, Windows GUI subsystem
- Link SQLite 3.49.1 statically (amalgamation build)
- Enable GuardCF (
/guard:cf) and POGO (/genprofileor/fastgenprofile)
Key APIs to Replicate
CoInitializeEx+CoCreateInstancefor DPAPI COM interopBCryptOpenAlgorithmProvider(AES-GCM or AES-CBC) for decrypting ABE-protected keysCryptStringToBinaryAfor Base64 decoding ofapp_bound_encrypted_keySHGetKnownFolderPath(FOLDERID_LocalAppData,FOLDERID_Profile) to locate browser profilesCreateToolhelp32Snapshotto enumerate browser processesCreateMutexWfor single-instance gating
Verification
- Build a test DLL with a
Bootstrapexport - Place a Chrome
Local Statewith ABE enabled in a test profile - Call
Bootstrap; check if it producesfingerprint.jsonandcookies.json - Verify
ASTER_KEY:appears in debug output when ABE is present, andNO_ABEwhen absent
Deployable Signatures
YARA Rule
rule unclassified_msvc_browser_credential_harvester
{
meta:
description = "MSVC x64 DLL browser credential harvester with Chrome ABE bypass"
author = "PacketPursuit"
date = "2026-08-08"
hash = "9d3d5ac032a3d26671c21b3b8832c46785f30523b3631ff2d59d5eaf3494d661"
strings:
$a1 = "ASTER_KEY:" ascii wide
$a2 = "aster_app_bound_encrypted_key" ascii wide
$a3 = "app_bound_encrypted_key" ascii wide
$a4 = "NO_ABE:Browser uses legacy DPAPI encryption (App-Bound Encryption not enabled)" ascii wide
$a5 = "chrome_decrypt.dll" ascii wide
$a6 = "fingerprint.json" ascii wide
$a7 = "DecryptData failed: 0x" ascii wide
$b1 = "SELECT host_key, name, path, is_secure, is_httponly, expires_utc, encrypted_value FROM cookies" ascii wide
$b2 = "SELECT origin_url, username_value, password_value FROM logins" ascii wide
$b3 = "SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards" ascii wide
$b4 = "SELECT value_encrypted, nickname FROM local_ibans" ascii wide
$b5 = "SELECT service, encrypted_token, binding_key FROM token_service" ascii wide
$c1 = "SQLite format 3" ascii
$c2 = "COMPILER=msvc-1950" ascii
condition:
uint16(0) == 0x5A4D and
uint32(uint32(0x3C)) == 0x00004550 and
(pe.machine == pe.MACHINE_AMD64 or pe.machine == pe.MACHINE_IA64) and
pe.exports("Bootstrap") and
(2 of ($a*) or 3 of ($b*)) and
$c1 and $c2
}
Sigma Rule
title: Browser Credential Harvester Module Execution
status: experimental
description: Detects execution of a DLL with chrome_decrypt.dll export and browser credential harvesting behavior
logsource:
category: process_creation
product: windows
detection:
selection:
- Image|endswith: 'chrome_decrypt.dll'
- CommandLine|contains:
- 'Bootstrap'
- 'chrome_decrypt'
selection_file:
- TargetFilename|endswith:
- 'fingerprint.json'
- 'cookies.json'
- 'passwords.json'
- 'cards.json'
- 'iban.json'
- 'tokens.json'
condition: selection or selection_file
falsepositives:
- Legitimate security tools or browser utilities
level: high
IOC List
| Indicator | Value | Type |
|---|---|---|
| SHA-256 | 9d3d5ac032a3d26671c21b3b8832c46785f30523b3631ff2d59d5eaf3494d661 |
Hash |
| Export name | Bootstrap |
PE export |
| Module name | chrome_decrypt.dll |
PE export directory name |
| Mutex | Unknown (CreateMutexW with dynamic name expected) | Runtime |
| SQLite version | 3.49.1 (source ID 873d4e274b...) |
Build artifact |
| Output files | fingerprint.json, cookies.json, passwords.json, passwords_account.json, cards.json, iban.json, tokens.json |
Filesystem |
| ABE strings | ASTER_KEY:, aster_app_bound_encrypted_key, NO_ABE:Browser uses legacy DPAPI |
Strings |
Behavioral Fingerprint
This binary is a 1 MB x64 DLL with a single Bootstrap export. Upon load, it initializes COM, queries the OS version and username, enumerates browser processes, and walks Chrome/Brave/Edge profile directories. It attempts to decrypt Chrome's Local State using App-Bound Encryption (ABE) if available, falling back to legacy DPAPI. It then opens browser SQLite databases (Cookies, Login Data, Web Data) and exports cookies, passwords, saved credit cards, IBANs, and OAuth tokens to local JSON files. No network connections are made by this module; exfiltration is delegated to a separate stage.
Detection Signatures
| ATT&CK Tactic | Technique | Evidence |
|---|---|---|
| Credential Access | T1555.003 — Credentials from Password Stores: Browser | Chrome/Brave/Edge path strings, SQLite SELECTs for cookies/passwords/cards ^[strings.txt:249-391] |
| Credential Access | T1552.004 — Private Keys | app_bound_encrypted_key, ASTER_KEY: ABE bypass ^[strings.txt:328-333] |
| Discovery | T1082 — System Information Discovery | RtlGetVersion, GetUserNameA, GetComputerNameA, fingerprint.json ^[pefile.txt:353,382,378] |
| Discovery | T1057 — Process Discovery | CreateToolhelp32Snapshot, Process32FirstW, Process32NextW ^[pefile.txt:391-396] |
| Defense Evasion | T1622 — Debugger Evasion | IsDebuggerPresent ^[pefile.txt:471] |
| Defense Evasion | T1497.001 — Virtualization/Sandbox Evasion: Time-Based Evasion | QueryPerformanceCounter, GetTickCount ^[pefile.txt:451-452] |
| Execution | T1055 — Process Injection | DLL form + Bootstrap export with PEB-walking API resolution; intended for reflective injection ^[r2:sym.chrome_decrypt.dll_Bootstrap] |
| Collection | T1115 — Clipboard Data | Browser credential extraction implies clipboard monitoring in companion stage (not observed here) |
| Exfiltration | T1041 — Exfiltration Over C2 Channel | None in this module; delegated to separate stage |
References
- unclassified-msvc-browser-credential-harvester — Entity page for this family/cluster
- chrome-app-bound-encryption-bypass — Technique page for Chrome ABE bypass
- browser-credential-harvesting — Cross-family concept page
- Google Chrome: App-Bound Encryption — Google's announcement of ABE (Chrome 127+)
Provenance
file.txt—filev5.45exiftool.json— ExifTool v12.76pefile.txt— pefile (Python) + custom dump scriptstrings.txt—strings -n 6(GNU binutils)floss.txt— FireEye flare-floss (failed: argument parsing error)capa.txt— Mandiant capa (failed: default signature path missing)binwalk.txt— Binwalk v2.3.4rabin2-info.txt— radare2 v5.xr2:sym.chrome_decrypt.dll_Bootstrap— radare2 decompilation (pdc)dynamic-analysis.md— CAPE skipped (no Windows guest available)