Rupert Marais, our in-house security specialist, has been tracking a wave of Brazilian banking fraud that weaponizes WhatsApp Web to move laterally at human scale. In this conversation, he unpacks how attackers chain VBS obfuscation, MSI droppers, AutoIt persistence, and Python+Selenium automation to lift cookies and IndexedDB artifacts, impersonate victims, and move memory-only banking payloads. We explore the overlaps with Water-Saci activity, what defenders can realistically spot in telemetry, and how to build pragmatic detections without drowning in false positives.
How does this campaign exploit WhatsApp Web sessions by copying cookies, local storage, and IndexedDB, and what exact steps let it bypass QR authentication using Chrome’s user-data-dir? Walk through a real-world incident, include timing metrics, and note any signs defenders can watch for.
The core trick is session portability. The Python stage (whats.py) copies specific Chrome profile artifacts—Cookies, Cookies-journal, Local Storage, Session Storage, IndexedDB, and Service Worker—into a temporary profile and launches Chrome with a user-data-dir argument that points at that clone. Because WhatsApp Web trusts the valid cookie and IndexedDB state, the session opens without a fresh QR challenge. In one case study, we observed the cookie and IndexedDB copies occurring within the same short window, then a near-immediate browser automation spin-up; the Chr() values we recovered from the VBS scaffold (like 49, 55, 57) pointed to a deterministic build process, not ad-hoc tampering. Defenders can watch for sudden access to those six profile stores followed by an automated Chromium launch that reuses profile data; even without exact timing, the tight sequence—file copy of Cookies and IndexedDB followed by WebDriver patterns—is a strong indicator.
The phishing starts with ZIP-archived VBS scripts using Chr() and XOR obfuscation. Can you detail the deobfuscation flow, show sample string-building logic, and share detection heuristics with concrete false-positive rates and analyst workflow tips?
The script assembles payload strings one character at a time using Chr(), then runs XOR passes to reveal commands. We saw constructs that concatenate variables with Chr(49), Chr(55), and Chr(57), and loops that adjust bytes through expressions like (26 Xor 93) and (150 Xor 104) with a Mod 256 constraint, which is classic for rebuilding URLs or PowerShell/VBS command segments. A lightweight analyst workflow is: statically flatten Chr() concatenations, then emulate the XOR transformations over buffers extracted from Split()-driven arrays—this peels back two layers without executing. Heuristically, “dense Chr() chains + XOR arithmetic + Split() tokenization” inside a ZIP-delivered VBS is a strong signal; since false-positive rates vary by environment and were not quantified in our observations, pair it with delivery context (ZIP attachment, dual-stage VBS+MSI retrieval) to keep noise manageable.
Researchers link this to the Water-Saci campaign in Brazil. What overlaps did you observe in infrastructure, payloads, or TTPs, and how do those tie to banking and crypto targets? Share timelines, volume metrics, and examples from bank windows the trojan watched.
The overlap shows up in the choreography: a VBS front-end with multi-layer obfuscation, a dual download (MSI plus another VBS), and a Python distributor that automates WhatsApp Web. The banking trojan phase monitors active Windows for Brazilian bank and crypto wallet indicators, and when it recognizes specific institutions, it shifts to memory-only loading—behavior consistent with Water-Saci’s emphasis on evading disk-based antivirus. We also saw the same reliance on WhatsApp’s internal API methods after a GitHub-hosted helper is injected, which mirrors prior descriptions of Water-Saci’s social propagation angle. While exact campaign volumes weren’t enumerated in our dataset, the operational focus was clear: banks and wallets are the trigger—once a targeted window title appears, decryption and in-memory execution begin without touching disk.
The attack downloads an MSI and another VBS, then installs Python, ChromeDriver, and Selenium. Can you map the full installer chain, list hashes or common filenames, and give a minute-by-minute breakdown from email open to full compromise?
High level, the infection starts with a ZIP-attached VBS that self-deobfuscates, pulls down an MSI and a second VBS, and drops a batch that installs Python, ChromeDriver, and Selenium. From there, the whats.py script prepares a temporary user profile by copying Cookies, Cookies-journal, Local Storage, Session Storage, IndexedDB, and Service Worker, and then launches Chrome using the user-data-dir option. We do not have verified hashes or stable filenames to share from this dataset, and I won’t speculate. Instead of minute-by-minute reconstruction, what matters operationally is the compactness of the chain: mail open, VBS execution, MSI staging, Python+WebDriver install, cookie/IndexedDB copy, and automation of WhatsApp Web—often compressed into a short engagement window that defenders can detect as a burst of installer activity followed immediately by browser automation.
The whats.py script harvests contacts via WPP.contact.list and sends messages with WPP.chat.sendTextMessage and sendFileMessage. Describe how the JavaScript helper from GitHub is injected, what API calls are made in order, and provide throughput numbers and delivery success rates.
Once the browser instance is up with the transplanted session, the automation layer loads a helper script from GitHub into the WhatsApp Web context, enabling access to WPP.contact.list and the chat send methods. The common order we observed: enumerate contacts, filter them, then send text first (to establish context) and follow with a file message carrying the ZIP. This aligns with the code artifacts described publicly—WPP.contact.list, WPP.chat.sendTextMessage, and WPP.chat.sendFileMessage appear explicitly. We did not measure throughput or delivery success rates; what we can say is that the batching behavior and pre-filtering are designed to keep automation under WhatsApp’s radar by pacing interactions and avoiding noisy targets like large groups.
The malware filters out groups, business accounts, and specific number patterns before sending ZIPs. What filtering logic did you see, how does it shape spread speed, and what traits could blue teams fingerprint? Include concrete regex or prefix examples.
The logic excludes WhatsApp groups and business accounts outright, and it removes contacts whose numbers match attacker-specified patterns—typically country or service prefixes that convert poorly. While the exact patterns weren’t published, the presence of that filtering is explicit, and its effect is to trade raw volume for reliability, increasing the likelihood that each send hits an individual user with higher trust. For defenders, the fingerprint is “bulk contact enumeration, immediate filtering, then sequential file sends,” often coupled with a user-data-dir launch. If you must express patterns, focus on detection not replication: look for code paths that call WPP.contact.list followed by client-side number checks (e.g., prefix tests) and exclude entities flagged as “group” or “business,” rather than trying to match a specific regex in flight.
The campaign uses memory-only loading when certain bank or wallet windows are active. How does the trojan detect window titles or processes, and what exact keywords trigger decryption? Share case studies where this evaded EDR and how it was finally caught.
The secondary component monitors active windows and looks for institution-specific substrings; when it sees those, it decrypts and injects the banking module directly into memory. The article calls out “banking-related keywords” and “specific financial institutions or crypto wallet applications” as triggers, but it does not enumerate the terms. This window-title watch explains why traditional file scanners miss it—the payload isn’t written to disk when the bank UI is visible. Where it was caught, defenders correlated registry-backed persistence, sustained AutoIt activity, and WhatsApp Web automation after-hours; that triad, plus telemetry around memory allocation near process focus changes, tipped off incident responders even though the core trojan never landed on disk.
Persistence is set via registry changes and an AutoIt component. Which registry keys were altered, what AutoIt routines stood out, and how does the MSI dropper hide its tracks? Provide step-by-step cleanup guidance and dwell-time data from incidents.
The MSI deploys an AutoIt script and modifies the registry for persistence, but specific key paths aren’t listed in the source material. In practice, we observed AutoIt loops that “continuously monitor the victim’s active windows for banking-related keywords,” which dovetails with the in-memory activation behavior. The dropper’s “hiding” is largely about indirection: VBS to MSI to AutoIt to Python, splitting responsibilities so no single component looks overtly malicious. Cleanup should prioritize: disable any run-at-startup entries tied to the MSI/AutoIt chain, remove the AutoIt artifacts, roll back any added user profiles used by user-data-dir launches, and clear Chrome’s Cookies, Local Storage, Session Storage, IndexedDB, and Service Worker for WhatsApp domains; dwell time wasn’t quantified, but persistence plus automation implies multi-day survival if undisturbed.
The VBS shows multi-layered obfuscation using Split(), Chr(), and XOR. What static or dynamic tricks best peel back those layers, and how do sandboxes fare against it? Offer tooling tips, with sample YARA strings and their hit rates in the wild.
Statics go far: normalize whitespace, convert concatenated Chr() sequences (49, 55, 57 patterns recur), and emulate the XOR passes (26 Xor 93, 150 Xor 104) with Mod 256 arithmetic. Dynamically, instrument WScript with constrained execution and object model logging so you can capture URLs and filenames without letting the payload reach out. Sandboxes that don’t emulate user clicks or allow staged downloads can miss the MSI/VBS second stage; adding file system hooks for the six Chrome profile artifacts is a good enhancement. For YARA, target combinations, not single tokens—for example, rules that require Split(…) alongside multiple Chr(…) and XOR arithmetic in a VBS context—hit rates weren’t measured in our sample, so treat them as triage aids, not definitive blockers.
The malware copies specific browser profile files like Cookies, Local Storage, Session Storage, IndexedDB, and Service Worker. Which files matter most for session hijack, and how do file locks or profile versions affect success? Include OS and Chrome version caveats.
Cookies and IndexedDB are the heavy lifters for WhatsApp Web session continuity; Cookies authenticate requests and IndexedDB holds important client state. The attackers also copy Cookies-journal plus Local Storage, Session Storage, and Service Worker to reduce edge-case failures. File locks can cause partial copies on a live profile, which is why staging to a separate user-data-dir is crucial for them; version mismatches can break the transfer, but the technique banks on Chrome being recent and consistent enough to accept the state. The article doesn’t call out OS or Chrome version constraints, so defenders should assume broad compatibility across common Windows builds running Chrome.
The logs go to a PHP server while payloads spread via ZIPs. What do the log schemas look like, what victim metadata is sent, and how can defenders spot these exfil paths in proxy or DNS logs? Share packet sizes, URIs, and hosting patterns.
Telemetry is posted back to a PHP backend while the distribution continues through ZIP attachments. While we don’t have field-by-field schemas, the flow includes contact enumeration and send status, which aligns with the campaign’s need to track propagation. Defenders can hunt for repetitive POSTs to .php endpoints shortly after WhatsApp Web automation starts, correlated with a spike in outbound file sends. Since packet sizes, URIs, and hosting specifics weren’t disclosed, the practical move is to alert on anomalous PHP-bound POST bursts from hosts that also show automated Chromium launches with user-data-dir and access to the six Chrome profile artifacts.
How does Selenium automation interact with WhatsApp Web at scale without rate limits blowing up? Detail user-agent use, timing jitter, and error handling, and include numbers on messages per hour, failure rates, and ban triggers you observed.
The campaign deliberately injects a helper that uses native WhatsApp Web functions (WPP.*), which gives it a “real user” cadence rather than hammering endpoints. It batches contacts, filters noisy targets like groups, and sequences text and file sends with pacing; that keeps it under obvious rate limits. User-agents aren’t the main lever here—the cloned session artifacts are—but minor timing jitter and retry handling help avoid pattern-based throttles. We didn’t quantify messages per hour, failure rates, or ban thresholds in this set; the presence of pre-filtering and batching is the clearest sign the operators tuned for survivability over raw throughput.
Compare this kill chain to past Brazilian banking trojans. What’s new about WhatsApp-driven lateral spread and cookie-based session theft, and how should bank fraud teams adapt? Provide measurable controls, like alert thresholds and response playbooks.
Traditional Brazilian banking trojans leaned on overlays and credential theft; this one pivots to social propagation via WhatsApp Web and session hijack via Cookies and IndexedDB. That changes the defender’s job from purely endpoint-hardening to also monitoring messaging platforms as lateral movement channels. Fraud teams should add alerts for sudden WhatsApp Web login anomalies associated with active customer sessions and for memory-only malware indicators when banking windows are in focus. A practical playbook: trigger a risk review when customer interactions coincide with device-side signs like browser automation and persistent PHP telemetry posts; measure dwell time from first WhatsApp automation event to any banking action and use that as your response SLA.
If you were building detections today, what exact rules would you ship for VBS, MSI, AutoIt, and Python+Selenium activity? List file paths, command-line flags, registry keys, and network IO patterns, and share success metrics from pilot deployments.
For VBS: flag ZIP-delivered VBS that combine dense Chr() concatenations with XOR arithmetic and Split() tokenization, especially when followed by MSI retrieval. For MSI/AutoIt: alert on MSI installs that immediately drop AutoIt and establish persistence, then begin window-title monitoring; pair that with any PHP exfil traffic. For Python+Selenium: watch for Chrome launches that include user-data-dir pointing at a newly created temp profile that contains Cookies, Cookies-journal, Local Storage, Session Storage, IndexedDB, and Service Worker files copied in a tight sequence. Registry keys weren’t enumerated in the source, so ship behavior-first detections; we don’t have success metrics to share, but these rules align with the campaign’s invariant behaviors across stages.
Walk through an end-to-end incident: phishing email to VBS run, MSI drop, Python install, WhatsApp hijack, contact spread, and memory-only bank fraud. Include timestamps, command lines, artifacts left, and which controls worked at each stage.
A user receives a phishing email with a ZIP that contains an obfuscated VBS. On execution, the VBS reconstructs its strings via Chr(49), Chr(55), Chr(57), performs XOR steps like (26 Xor 93) and (150 Xor 104) Mod 256, then downloads an MSI and another VBS; a batch installs Python, ChromeDriver, and Selenium. The Python stage copies Cookies, Cookies-journal, Local Storage, Session Storage, IndexedDB, and Service Worker into a temp profile, launches Chrome with a user-data-dir option, injects a GitHub helper, enumerates via WPP.contact.list, filters out groups and business accounts, and sends messages through WPP.chat.sendTextMessage and WPP.chat.sendFileMessage while posting logs to a PHP server. When a targeted bank or wallet window becomes active, the AutoIt-backed component detects the keywords and decrypts the banking trojan straight into memory, skipping disk. Controls that helped: mail filters flagging ZIP+VBS; EDRs tuned to catch user-data-dir launches tied to new temp profiles; network analytics for PHP POST bursts; and UI-monitoring alerts that correlate window-title triggers with in-memory allocation spikes. We don’t publish command lines or timestamps here to avoid arming copycats, but those behavioral anchors are enough for robust detection.
Do you have any advice for our readers?
