Skip to content

KREMLIN (REF9334): Brazilian banking malware forges Chrome's own integrity checks to sideload extensions, resolves C2 from Ethereum smart contracts — 15 months, seven campaigns, 1,515 systems caged via a registered kill-switch domain (Elastic Security Labs, Sep 14, 2026)

Tags

Summary

Elastic Security Labs published a 15-month retrospective (September 14, 2026) on REF9334, a Brazilian banking-malware operation whose toolkit the author named KREMLIN (Kr3mlin4rt1st in code comments — nothing about the operation is Russian: lures impersonate twelve Brazilian banks, error messages and comments are in Portuguese, and the operators' Ethereum transactions cluster in São Paulo working hours). Across seven campaigns (June 2025 – May 2026) the group evolved from delivering the commodity PULSAR RAT to shipping a malicious Chrome/Edge extension that installs itself without any user approval — the browser loads it "as though the user approved it" because the installer regenerates the Secure Preferences HMACs and App-Bound encrypted hashes that Chromium uses to detect tampering.

The durable findings:

  1. Chromium's own local-integrity controls were forged, not bypassed — the installer manipulates Secure Preferences, recomputes the required HMACs, and regenerates App-Bound encrypted hashes, so extension-existence checks and enterprise policy views see a legitimately-installed extension.
  2. Ethereum smart contracts act as dead-drop resolvers for C2 endpoints and payload hosting (the May 2026 "Ethereum transition campaign," which also introduced REMCOS alongside the custom tooling) — takedown-resistant, append-only C2 configuration.
  3. Elastic Threat Command registered the campaign's unregistered network-canary domain www[.]creamp1eonlyfans[.]net and observed 1,515 infected systems (98.75% Brazil) checking in — every implant that reaches the canary now believes it is in a sandbox and crashes, temporarily halting the campaign's final stage at the time of writing ("and counting," accelerating).

Infection chain

Stage 1 — JavaScript loader. A .js file masquerading as a banking/invoice/company document that the user double-clicks (analysis sample SHA-256 106eac79396a3ff77b8f375c391260ce422be2ae4d55d3aa75b2635cbdc0fa42). Basic obfuscation (generic itemXX names, string lookup tables, bracket-notation calls — Elastic notes it deobfuscates easily with an LLM). The loader: - Shows a fake error popup (popup_{date}_{random}.js invoking shell.Popup, self-deleting — a useful pivot name for finding sibling samples; second analyzed loader SHA-256 5ece7fd3766b0b7f8aadefa562313cea6c3c94f9398658dd389910e5be44f552). - Runs sandbox checks: ≥5 files on the Desktop and ≥50 running processes (WMI count) or it aborts; >2 CPUs and >3 GB RAM; username blacklist; VMware/VirtualBox process, driver, and DLL artifacts. - Runs a network canary check: fetches the unregistered domain hxxp://www[.]creamp1eonlyfans[.]net — any valid response means simulated sandbox networking, so the malware deliberately crashes. - Downloads a genuine Node.js runtime to execute the next JavaScript stage (certutil decodes/extraction), then beacons GET /api/log_loader?hash= with the campaign ID (observed C2 hxxps://connection[.]upgradeonline[.]site).

Stage 2 — persistence + Ethereum dead-drop resolver. Scheduled-task persistence; the second stage resolves current C2/payload locations from attacker-controlled Ethereum contract state rather than hardcoded URLs.

Installer stage — C++ components. Custom C++ installer with indirect syscalls (SSN resolution from NTDLL), DLL side-loading for entrypoint execution, reflective loading, embedded/encrypted payloads, dynamic API resolution, file-type masquerading, and per-campaign customer-ID markers + mutexes (the operation behaves like malware-as-a-service with tracked "customers").

Extension installation without the Web Store. The installer writes the extension into the browser profile and manipulates Secure Preferences, regenerating the HMACs Chromium computes over the extension entries, and regenerates the App-Bound encrypted hashes — neutralizing the exact mechanisms Chrome/Edge (and endpoint tooling that reads those structures) rely on to flag externally-installed extensions. It then recovers OSCrypt and App-Bound encryption keys to decrypt browser data.

Payload capability. Credential theft, session-token theft from Brazilian banking sessions, cookies and browser-data exfiltration; earlier campaigns pair the extension with PULSAR RAT (June–Aug 2025) or REMCOS (May 2026); loaders also fetch QR-code-themed extensions (April 2026 campaign).

Campaign timeline (as named by Elastic)

Campaign Period Notable
Codecaudiog A Jun 2025 PULSAR RAT + extension delivery
Codecaudiog B Jun 2025 three JavaScript loader variants
Acrobat Aug 2025 PULSAR RAT only, no extension
Framesync Sep 2025 earliest recovered extensions
Donalurdesconfeitos → Cremeb Dec 2025 first KREMLIN branding
Cremeb Apr 2026 QR-code extension + Node.js loaders
Ethereum transition May 2026 smart-contract C2 config + REMCOS

Recent lure filenames mimic Brazilian municipal/Compliance paperwork: LocalizacaoPublico_* (location/security/public regulation, Aug 6–10 2026), DocumetoSeguranca_* / DocumetoFuncionamento_* (misspelled "security/operating document"), CertificadoLocalizacao_*, AlvaraPublico_* / AlvaraFuncionamento_* (public permit/license) — the Portuguese misspellings are themselves a fingerprint.

Caging the canary

Elastic registered the unregistered canary domain and served it from their webhost. Infected systems make a single GET (GET // HTTP/1.1, Host: www.creamp1eonlyfans[.]net, Firefox 141 UA, Cache-Control: no-cache) — then the loader concludes "sandbox," crashes, and the infection never reaches the extension stage. As of publication: 1,515 check-ins, 98.75% from Brazil, accelerating — i.e., the campaign was scaling when it tripped. The disruption is temporary: the operators can re-point or drop the canary. Defenders get a window to hunt and remediate, not a takedown.

Durable detections

  • Chromium extension tampering: monitor for writes to Secure Preferences/Preferences outside browser update processes, extension entries with recomputed HMACs appearing without Web Store / policy provenance, and unexpected external_update/PreloadedHardwareResolution-adjacent artifacts. Extension enumeration that relies on those integrity structures will be blind — enumerate from network/endpoint behavior instead.
  • Node.js downloaded by a browser-office/script ancestry on non-developer hosts (the loader installs a real Node runtime to run stage 2).
  • popup_{date}_{random}.js creation followed by deletion; certutil -decode parented by wscript/cscript.
  • Outbound requests to Ethereum JSON-RPC endpoints from non-crypto applications followed immediately by new C2 connections (contract-state resolution).
  • GET /api/log_loader?hash= beacons; any DNS resolution attempt (even NXDOMAIN history) for creamp1eonlyfans[.]net is a prior-infection indicator — a check-in to Elastic's sinkhole means the host is infected but frozen.

Assessment notes

  • "KREMLIN" is author-chosen branding, not an attribution; no state nexus is claimed. The service-like campaign IDs, customer tracking, and commodity pairings (PULSAR, REMCOS) read as commercial Brazilian banking-malware tradecraft.
  • The canary seizure degrades only the current campaign generation — expect canary-domain rotation or removal; re-check the infrastructure sections of the source post for updated IOCs (Elastic publishes a downloadable IOC set; this page records the named domain, C2 URL pattern, and sample hashes that survived the writeup).

Indicators (recorded from the source post; Elastic publishes a fuller downloadable set)

  • Canary/sinkholed domain: www[.]creamp1eonlyfans[.]net (GET //, Firefox/141.0 UA, Cache-Control: no-cache) — resolution attempts are prior-infection indicators
  • Loader beacon: GET /api/log_loader?hash= with campaign ID; observed C2 connection[.]upgradeonline[.]site
  • Loader SHA-256 (analyzed): 106eac79396a3ff77b8f375c391260ce422be2ae4d55d3aa75b2635cbdc0fa42; popup-pivot sibling: 5ece7fd3766b0b7f8aadefa562313cea6c3c94f9398658dd389910e5be44f552
  • Lure filename patterns: LocalizacaoPublico_*, DocumetoSeguranca_*, DocumetoFuncionamento_*, CertificadoLocalizacao_*, AlvaraPublico_*, AlvaraFuncionamento_* (Portuguese misspellings)
  • Behavior: Node.js runtime download by script ancestry on non-dev hosts; Ethereum JSON-RPC reads preceding new C2 connections; Secure Preferences writes with recomputed HMACs outside browser processes

References