Elastic Security Labs a identifié un nouveau cheval de Troie bancaire brésilien que nous suivons sous le nom de TCLBANKER, une famille de logiciels malveillants que nous estimons être une mise à jour majeure de la familleMAVERICK/SORVEPOTEL. La campagne, répertoriée sous le nom de REF3076, comporte un chargeur doté de solides capacités anti-analyse qui déploie deux modules intégrés protégés par .NET Reactor : un cheval de Troie bancaire complet et un module ver pour l'autopropagation.
Ce cheval de Troie bancaire surveille la barre d'adresse du navigateur de la victime via UI Automation, en ciblant 59 les domaines bancaires, fintech et crypto-monnaies brésiliens. Outre les commandes d'accès à distance habituelles, sa capacité la plus remarquable est un cadre de superposition plein écran basé sur WPF, conçu pour l'ingénierie sociale pilotée par l'opérateur.
Un deuxième module gère la distribution par l'intermédiaire d'agents de spam, dont nous avons retrouvé deux variantes : un ver WhatsApp qui détourne les sessions de navigation authentifiées pour envoyer des messages aux contacts de la victime, et un bot de messagerie Outlook qui envoie des courriels d'hameçonnage par l'intermédiaire des propres comptes de la victime via l'automatisation COM.
Dans ce rapport, nous fournissons une analyse technique détaillée de chaque étape.
Principaux points abordés dans cet article
- TCLBANKER utilise un décryptage de la charge utile en fonction de l'environnement ; les environnements incorrects, tels que les bacs à sable, ne parviennent pas à décrypter la charge utile.
- Un sous-système de surveillance complet contrôle en permanence les outils d'analyse, les débogueurs, les cadres d'instrumentation et les violations de l'intégrité tout au long de l'exécution.
- Le cheval de Troie bancaire cible 59 les domaines brésiliens de la banque, de la fintech et des crypto-monnaies, activant une session C2 WebSocket lorsqu'une victime navigue vers un site surveillé
- Un cadre de superposition plein écran basé sur WPF permet une ingénierie sociale pilotée par l'opérateur, y compris la collecte d'informations d'identification, les écrans d'attente de vishing et les faux blocages de Windows Update, tout en cachant les superpositions des outils de capture d'écran.
- Des modules de ver propagent le logiciel malveillant : un bot WhatsApp et un bot de messagerie Outlook
- Toute l'infrastructure C2 et de distribution est hébergée sur Cloudflare Workers sous un compte unique, avec des artefacts de développeur (chemins de journalisation de débogage, noms de processus de test) et une page de phishing incomplète, ce qui suggère que la campagne a été identifiée à un stade opérationnel précoce.
Livraison
TCLBANKER est un cheval de Troie bancaire brésilien qui contient une chaîne d'infection dynamique avec un composant de chargement anti-analyse lourd qui peut déployer deux charges utiles intégrées (ver, banquier). La chaîne d'infection observée regroupe un programme d'installation MSI malveillant à l'intérieur d'un fichier ZIP. Ces paquets d'installation MSI abusent d'un programme Logitech signé appelé Logi AI Prompt Builder.
TCLBANKER abuse de la mise en veilleuse de DLL contre LogiAiPromptBuilder.exe, une application Logitech légitime construite sur le cadre Flutter. La DLL malveillante screen_retriever_plugin.dll se fait passer pour un plugin Flutter légitime du même nom et est chargée automatiquement au démarrage de l'application hôte.
Après l'installation MSI, la DLL malveillante est immédiatement chargée et démarre au point d'entrée DllMain.
Chargeur
Le composant de chargement de TCLBANKER est doté de nombreuses fonctions, notamment des fonctions anti-débogage, des contrôles anti-analyse, le cryptage des chaînes de caractères, des contrôles de la langue du système, des correctifs ETW et une capacité de chien de garde. Bien qu'il comporte de nombreuses fonctionnalités, il manque de profondeur et fait référence à d'anciens outils d'analyse des logiciels malveillants. Il n'est pas tout à fait clair si le développeur a utilisé des flux de travail assistés par LLM, mais notre équipe ne serait pas surprise si c'était le cas.
Au début de l'exécution, le TCLBANKER aligne les charges utiles correspondantes de l'assemblage .NET en fonction de l'utilisation de la chaîne (--renderer=sw) dans la ligne de commande. Dans sa fonction principale de chargement, il effectue d'abord des opérations de liste d'autorisation et de liste de blocage en fonction de la manière dont la DLL a été chargée. La DLL malveillante ne s'exécutera que si le processus hôte provient des deux processus suivants :
logiaipromptbuilder.exetclloader.exe(Référence possible à la chaîne de caractères du développeur pendant les tests)
Si la DLL a été chargée par les processus suivants, elle refusera de s'exécuter. Ces processus sont traditionnellement utilisés par les analystes pour charger et déboguer les DLL.
rundll32.exeregsvr32.exedllhost.exesvchost.exe
Ensuite, TCLBBANKER supprime tout accrochage en mode utilisateur en remplaçant ntdll.dll à partir du disque. Pour plus d'évasion, le logiciel malveillant génère les trampolines syscall suivants, utilisés plus tard :
NtQueryInformationProcessNtSetInformationThreadNtSetInformationProcessNtTerminateProcessNtAllocateVirtualMemoryNtProtectVirtualMemory
Après avoir installé des stubs syscall, le logiciel malveillant corrige EtwEventWrite dans ntdll.dll avec le classique xor eax, eax; ret pour désactiver la télémétrie ETW en mode utilisateur.
Le TCLBANKER effectue une vérification initiale du bac à sable en capturant un tick de démarrage à l'aide de GetTickCount64(), en dormant pendant 500 ms et en mesurant le temps écoulé. Si moins de 450 ms se sont écoulées, le logiciel malveillant se retire - cela permet de détecter les bacs à sable ou les cadres d'émulation qui accrochent le sommeil pour qu'il revienne immédiatement...
L'une des caractéristiques les plus intéressantes de TCLBANKER est une fonction d'énumération qui génère trois empreintes digitales sur la base des critères suivants :
- Contrôles anti-débogage
- Informations sur le disque du système et vérifications de la mémoire
- Contrôles linguistiques
Le développeur utilise des constantes magiques affectées à des chemins "propres" pour chaque catégorie, puis effectue un XOR contre chacun d'entre eux pour générer le hachage de l'environnement. Cette valeur de hachage de l'environnement est importante car elle affecte le décryptage en aval de la charge utile intégrée.
Par exemple, si un débogueur est présent, il produira un hachage incorrect, de sorte que lorsque le logiciel malveillant tentera de dériver les clés de déchiffrement du hachage, la charge utile ne sera pas déchiffrée correctement et TCLBANKER cessera de s'exécuter.
Contrôles anti-débogage
TCLBANKER met en œuvre six contrôles anti-débogage différents :
- Identifiez le débogueur à l'aide du drapeau
Peb->BeingDebugged - Vérifie les drapeaux heap-tail/heap-free/check-heap définis lorsqu'un processus est lancé sous un débogueur.
- Exploite le site
NtQueryInformationProcess()en utilisantProcessDebugPort - Utilise
NtQueryInformationProcess()en utilisantProcessDebugObjectHandle - Détection des points d'arrêt matériels via les registres de débogage (
DR0-DR3) - Mesure le temps écoulé en utilisant les deltas de
QueryPerformanceCounter()et les comptes de cycles deRDTSC.
Contrôle des informations sur le système
TCLBANKER effectue les cinq contrôles suivants en fonction des informations relatives à la virtualisation, au système et à l'utilisateur :
- Vérifie la présence d'un logiciel de virtualisation à l'aide de la signature du fournisseur
| Hyperviseur | Signature du vendeur |
|---|---|
| VMware | VMwareVMware |
| VirtualBox | VBoxVBoxVBox |
| KVM | KVMKVMKVM |
| Xen | XenVMMXenVMM |
| Parallels | prl hyperv |
| QEMU/TCG | TCGTCGTCGTCG |
- Vérifiez que le lecteur du système racine (
C:\\) viaGetDiskFreeSpaceExW()dispose d'au moins 64 Go. - Appelle
GlobalMemoryStatusEx()pour vérifier que le système dispose de plus de 2 Go de mémoire vive. - Vérifie la présence de 2 ou de processeurs CPU via
GetSystemInfo() - Vérifie les noms d'utilisateur génériques des bacs à sable et des logiciels malveillants.
sandbox,malware,virus,sample,john doe,currentuser
Contrôles linguistiques
Pour la dernière vérification de l'empreinte de l'environnement, TCLBANKER récupère les informations géographiques de la machine infectée à l'aide de GetUserGeoID(), en ciblant les utilisateurs brésiliens sur la base de l'ID géographique (0x20). Une deuxième vérification des paramètres linguistiques via GetUserDefaultLCID() permet également de s'assurer que la langue par défaut de l'utilisateur est le portugais brésilien (pt-BR, LANGID 0x0416).
Après ces vérifications, TCLBANKER abandonne l'exécution si quelque chose est détecté ou, si ce n'est pas le cas, produit une autre vérification anti-débogage en corrigeant DbgUiRemoteBreakin(). Le logiciel malveillant corrige son premier octet à l'instruction a ret de sorte que toute tentative d'intrusion à distance dans le processus n'aboutisse à rien - le fil d'exécution injecté revient immédiatement et la cible continue de fonctionner, sans interruption.
Ensuite, le logiciel malveillant calcule une clé AES-256 CBC et un IV en utilisant des constantes codées en dur dans la section .rdata ainsi que le hachage de l'environnement calculé précédemment. TCLBanker utilise BCryptDecrypt() pour décrypter la charge utile intégrée, puis décompresse via RtlDecompressBuffer en utilisant l'algorithme de compression LZNT1.
Une fois la charge utile déchiffrée, le TCLBANKER initialise COM via CoInitializeEx() et utilise les API d'hébergement CLR pour charger le moteur d'exécution .NET dans le processus. Avant de lancer le point d'entrée de la charge utile, TCLBanker crée deux nouveaux threads : l'un sert de chien de garde et l'autre surveille le thread du chien de garde en tant que contrôle cardiaque.
Chien de garde
TCLBANKER dispose d'une fonction de surveillance complète qui cible divers outils d'analyse, notamment les désassembleurs, les débogueurs, les produits d'instrumentation, les produits antivirus et les produits de type "bac à sable". Cette section présente les différentes techniques utilisées par cette fonction :
- Vérification du débogueur via
PEB→BeingDebugged - Recherche de points d'arrêt matériels
DR0/DR1/DR2/DR3 - Vérifie les fonctions Windows (
BCryptDecrypt(),BCryptOpenAlgorithmProvider()) pour les crochets en ligne en analysant les premiers octets 12 de chaque fonction. - Contrôle des outils d'instrumentation et des chaînes connexes (
frida,cydia,user-path injection,hook framework) - Passe en revue tous les tuyaux nommés du noyau à la recherche de
fridaou delinjector - Effectue l'énumération des processus via
CreateToolhelp32Snapshot()en ciblant les noms de processus suivants :frida,de4dot,dnspy,megadumper,extremedumper,processhacker,x64dbg,x32dbg,pe-sieve,scylla,Ilspy,dotpeek,netreactorslayer,cheatengine
- Emploie la détection des titres Windows via
GetWindowTextW()avec ces titres :x64dbg,x32dbg,ida -,ida pro,ghidra,dnspy,megadumper,extremedumper,processhacker,ollydbg,windbg)_,pe_sieve,scylla
- Identifie l'outil d'analyse sur la base des noms de classe de fenêtre suivants via
FindWindowW():IDATopLevelWindow,idaabortwndclass,TIdaWindow,x64dbg,x32dbg,OLLYDBG,WinDbgFrameClass,ProcessHacker,SystemInformer,CheatEngine,HxdClass
- Vérifie si les modules suivants ont été chargés
dbeng.dll,dbgcore.dll,SbieDll.dll,snxhk.dll,cmdvrt32.dll,cmdvrt64.dll,cuckoomon.dll,pstorec.dll,vmcheck.dll,wpespy.dll
- Cible les mutex et les événements suivants :
Ida_trusted_idbs,IDA_COMM_PIPE_,Local\\x64dbg,Local\\x32dbg,Frida,YOURAPPNAMEHERE
- Effectue un contrôle de l'intégrité de
CRC32dans la section.textafin d'éviter toute altération.
Module de cheval de Troie bancaire
Tcl.Agent est un cheval de Troie bancaire, principal composant de la chaîne. Il est protégé par .NET Reactor, et bien que nous n'ayons pas réussi à le désobfusquer en utilisant des outils open-source disponibles tels que de4dot et NETReactorSlayer, nous avons réussi à désobfusquer statiquement cette étape jusqu'à un état satisfaisant en utilisant un pipeline de désobfuscation personnalisé pour s'attaquer au cryptage des chaînes de .NET Reactor, à l'aplatissement du flux de contrôle, à la mutation IL, aux proxies de délégués et aux corps de méthodes cryptés (Necrobit). Bien qu'il s'agisse d'un nouveau logiciel malveillant, une grande partie de la structure du code suit le plan de mise en œuvre du trojan bancaire LATAM d'ESET, publié en 2020.
Au démarrage, le logiciel malveillant effectue un geofencing, nécessitant >= 2 des indicateurs suivants pour correspondre au Brésil ; sinon, il quitte immédiatement s'il ne se trouve pas sur une machine brésilienne :
| C'est par ici | Implémentation |
|---|---|
| Code de la région | new RegionInfo(CultureInfo.CurrentCulture.LCID).TwoLetterISORegionName == "BR" |
| Fuseau horaire | TimeZoneInfo.Local.BaseUtcOffset.TotalHours : si >= -5.0, vérifiez si == -2.0 |
| LCID | CultureInfo.CurrentCulture.LCID == 1046 (Portugais-Brésil) |
| Clavier | GetKeyboardLayoutList() - vérifiez chaque disposition : (ToInt32() & 0xFFFF) == 1046 |
Installation et persistance
Lors de la première exécution, le logiciel malveillant copie l'intégralité du répertoire de l'application dans %LocalAppData%\LogiAI. Il calcule un hachage SHA-256 de tous les fichiers .dll et .exe dans le répertoire source et l'écrit dans un fichier marqueur .version. Lors des exécutions suivantes, il compare les hachages pour éviter les copies redondantes. Après la copie, il lance la nouvelle instance à partir du chemin d'installation et quitte.
Il crée une tâche planifiée nommée RuntimeOptimizeService en utilisant l'interopérabilité COM avec le planificateur de tâches (CLSID 0F87369F-A4E5-4CFC-BD3E-73E6154572DD). La tâche est configurée comme étant cachée, activée, sans limite de temps d'exécution, autorisée sur batterie, démarrée lorsque disponible, et se déclenche sur un déclencheur de connexion (type 9) limité à l'utilisateur actuel. Il s'enregistre sur TASK_CREATE_OR_UPDATE et TASK_LOGON_SERVICE_ACCOUNT.
Une fois la persistance établie, l'agent envoie une balise POST de première exécution à https://campanha1-api.ef971a42.workers[.]dev/api/installs avec l'agentId (MachineName-UserName), MachineName, UserName (redondant) et la version du système d'exploitation. La demande est authentifiée par un jeton d'authentification de campagne codé en dur 0d21613a-2609-45fc-83ff-d0feaa0c891f. La nouvelle variante ajoute une journalisation de débogage autour de cet appel (C:\temp\tcl-debug.txt), un artefact de développeur qui expose par inadvertance la présence de l'agent sur le disque.
Auto-mise à jour
L'agent met en œuvre une porte d'auto-actualisation basée sur le hachage qui s'exécute au début du pipeline de démarrage. Il lit une version locale du hachage à partir de flutter_engine.cfg dans son répertoire d'installation (en migrant à partir d'un ancien nom de fichier version.hash s'il est présent), puis récupère le hachage actuel à partir du point d'extrémité du serveur de fichiers documents.ef971a42.workers[.]dev/api/version en utilisant une chaîne User-Agent tronquée (Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36.
La réponse est analysée à la recherche de la clé "hash". Si le hachage distant correspond au hachage local, l'exécution se poursuit normalement. Lors de la première installation, le hash distant est écrit sur le disque et l'exécution se poursuit sans mise à jour.
Lorsqu'une non-concordance de hachage est détectée, l'agent télécharge la charge utile de la mise à jour à partir de documents.ef971a42.workers[.]dev/api/update sous la forme d'un MSI vers %TEMP%\update_{8hexchars}.msi, authentifié avec le jeton de support b7ba9e80-0d04-4d9e-b217-c8b3cce335a2.
Le téléchargement est validé par rapport à une taille minimale de 100 Ko à titre de contrôle de sécurité. L'agent écrit ensuite un script batch d'autosuppression sur %TEMP% qui interroge la liste des tâches jusqu'à ce que le processus en cours se termine, exécute msiexec /i /qn REINSTALLMODE=amus pour une installation silencieuse et se supprime lui-même. Le fichier batch est lancé via un processus caché cmd.exe avant que l'agent ne se termine, transférant l'exécution à la charge utile mise à jour.
Contrôle de l'URL du navigateur et initialisation de la session C2
Toutes les secondes, l'agent malveillant appelle une fonction de surveillance de l'URL du navigateur qui lit la barre d'adresse du navigateur au premier plan via l'automatisation de l'interface utilisateur. Il appelle GetForegroundWindow, résout le processus propriétaire, vérifie le nom du processus dans Chrome, Firefox, Microsoft Edge, Brave, Opera et Vivaldi, puis utilise AutomationElement.FromHandle -> FindFirst(Descendants, ControlType.Edit) -> ValuePattern.Current.Value pour extraire l'URL, de la même manière que dans cette implémentation de Stack Overflow.
L'URL extrait est comparé à une liste fixe de banques ciblées intégrées dans le code binaire, codé par XOR avec une clé de 16 octets et un codage base64.
Cette Gist GitHub contient une liste de 59 domaines ciblés, notamment des banques brésiliennes, des plateformes fintech et des bourses de crypto-monnaies, regroupés en fonction des identifiants de cible annexés à chaque domaine décrypté.
Lorsqu'une correspondance est trouvée, l'identifiant du domaine cible est transmis à l'état suivant, qui initialise la communication C2 officielle en établissant une connexion WebSocket avec wss://mxtestacionamentos[.]com/ws. Le gestionnaire OnConnect se déclenche et envoie un paquet d'enregistrement contenant l'ID de l'agent (un GUID aléatoire au moment de l'exécution), le nom de la machine, le nom de l'utilisateur, les informations sur la machine, l'horodatage, l'ID de la cible du domaine (afin que le C2 sache quel site web la victime a ouvert) et une signature.
Pour produire une signature de poignée de main, HMAC-SHA256 est utilisé pour signer l'identifiant de la victime (ID de l'agent, nom de la machine, nom de l'utilisateur, version du système d'exploitation, horodatage) en utilisant le GUID de la campagne 70e4f943-e323-4484-97d7-35401bf6812c comme clé.
Le serveur répond alors par un accusé de réception d'enregistrement, démarrant officiellement la session, et entre dans la boucle de distribution des commandes. Au début de la session, un tueur du gestionnaire de tâches est déclenché toutes les 500 ms pour empêcher la victime d'inspecter le processus de l'agent ou d'y mettre fin.
Tableau des commandes C2
Un résumé des capacités est décrit dans le tableau des opcodes ci-dessous :
| Opcode | Finalité |
|---|---|
| 2 | Enregistrement ACK, démarrez le gestionnaire des tâches killer |
| 4 | Déconnexion gracieuse de WebSocket |
| 5 | Suicide : Tuer tous les processus frères et quitter |
| 6 | Redémarrage forcé (shutdown.exe /r /t 0 /f) |
| 7 | Suicide-then-Uninstall : tuer tous les processus ayant le même nom binaire d'hôte sauf lui-même (frères et sœurs) → désinstaller → sortir |
| 16 | Capture |
| 17 | Lancer la diffusion de l'écran |
| 18 | Arrêter la diffusion de l'écran |
| 19 | Définir la qualité de la capture d'écran (1-100) |
| 20 | Énumérer les moniteurs |
| 32 | Déplacement de la souris (X, Y, MonitorIndex) |
| 33 | Clic de souris à travers la superposition : analyser {X,Y,Button,MonitorIndex} → traduire en coordonnées absolues du bureau → trouver la fenêtre de superposition de l'implant couvrant ce point → percer un trou de 2x2 régions dans la superposition à ce pixel → SetCursorPos + SendInput mouse-down/up (qui atterrit sur n'importe quel contenu réel du bureau situé sous la superposition). |
| 34 | Défilement de la souris (Delta, SendInput) |
| 35 | Effleurement des touches (KeyCode, SendInput) |
| 37 | Touche vers le bas (KeyCode, SendInput) |
| 38 | Key up (KeyCode, SendInput) |
| 39 | Démarrez le keylogger (WH_KEYBOARD_LL hook) |
| 40 | Déverrouillage du keylogger, exfiltration vers C2 |
| 41 | Détournement du presse-papiers (Clipboard.SetText) |
| 48 | Liste des répertoires du système de fichiers |
| 65 | Obtenir des informations sur les processus en cours |
| 67 | Exécution de commandes Shell (cmd.exe /c) |
| 80 | Énumérer toutes les fenêtres visibles |
| 81 | Gestionnaire de fenêtres : Tuer le processus d'une fenêtre / minimiser la fenêtre / restaurer la fenêtre / ramener la fenêtre au premier plan / fermer la fenêtre / déplacer la fenêtre vers un autre moniteur |
| 83 | Afficher un écran de stabulation : soit des étapes de progression, soit un faux écran de mise à jour de Windows. |
| 84 | Recouvrement du démontage |
| 85 | Basculer l'immunité de la capture d'écran. Active/désactive WDA_EXCLUDEFROMCAPTURE sur toutes les fenêtres superposées pour les masquer en cas de partage d'écran ou de capture d'écran. |
| 86 | Actualiser le contenu de la superposition |
| 87 | Afficher l'incrustation de la découpe : épingler la fenêtre externe à l'intérieur de l'incrustation avec la découpe de la région visible |
| 96 | Afficher la superposition de l'invite d'identification |
Cadre d'interface utilisateur pour l'ingénierie sociale
Une capacité plus intéressante du cheval de Troie bancaire est un sous-système de superposition plein écran basé sur WPF qui orchestre des flux de fraude sur le thème de la banque pendant les sessions C2 actives.
Cycle de vie de la superposition
Le gestionnaire de superposition crée une fenêtre WPF plein écran par moniteur. Les fenêtres sont configurées sans bordure, en haut et cachées de la barre des tâches (WindowStyle.None, Topmost = true, ShowInTaskbar = false), avec une poignée personnalisée Closing qui refuse d'être fermée jusqu'à ce qu'un drapeau interne soit basculé par l'opérateur via la commande de démontage de l'écran, empêchant ainsi la fermeture des fenêtres.
Au démarrage, le gestionnaire effectue une capture d'écran PNG de chaque écran via CopyFromScreen comme toile de fond superposée, créant ainsi un aspect de "bureau gelé". En fonction de la couche active, la victime perçoit l'environnement réel de son bureau derrière cette couche.
Une minuterie 500ms réapplique continuellement HWND_TOPMOST via SetWindowPos afin de neutraliser toute fenêtre tentant de faire surface au-dessus de l'écran.
En outre, une fonction anti-capture appelle SetWindowDisplayAffinity avec WDA_EXCLUDEFROMCAPTURE, rendant l'incrustation invisible à tout outil de capture d'écran, ce qui permet à l'opérateur de voir à travers sa propre incrustation grâce aux commandes de capture d'écran et d'enregistrement d'écran.
Blocage d'entrée
Sur le moniteur principal, deux crochets sont installés : WH_KEYBOARD_LL et WH_MOUSE_LL. Les deux crochets vérifient leurs drapeaux injectés respectifs (LLKHF_INJECTED pour le clavier, LLMHF_INJECTED pour la souris), ce qui permet à l'entrée injectée via SendInput par les commandes à distance de l'opérateur de passer sans être touchée. Le crochet du clavier avale les touches Tab, Escape, Alt+F4, Win, PrintScreen, Ctrl, Alt et toutes les touches de navigation ; le crochet de la souris bloque le clic droit, le clic moyen et le défilement, mais autorise le clic gauche et le mouvement, de sorte que la victime peut toujours interagir avec les messages d'invite superposés.
Ingénierie sociale Constructeurs d'interface utilisateur
Cinq moteurs de rendu de contenu interchangeables se branchent sur le cadre de superposition :
Demande de justificatif : Prend en charge trois modes de saisie, sélectionnés en fonction des paramètres de la demande de l'opérateur.
- Le mode téléphone applique un masquage en temps réel du format brésilien ((##) ####-#### pour les lignes fixes à 10 chiffres, (##) #####-#### pour les mobiles à 11 chiffres) avec un maximum de 11 chiffres.
- Le mode clavier virtuel affiche un clavier numérique à l'écran (touches 0-9 plus "limpar"/clear), affichant la saisie sous forme de caractères à puce pour imiter la saisie d'un code PIN.
- Le mode par défaut accepte le texte brut avec une longueur maximale configurable.
Tous les modes font passer les entrées par un validateur de qualité qui rejette algorithmiquement les séquences de chiffres identiques (000000) et les séries ascendantes/descendantes (123456, 654321) afin d'empêcher les victimes d'entrer des valeurs inutiles.
L'action de soumission envoie les valeurs capturées au C2.
Écran d'attente d'hameçonnage : Se déclenche après que la victime a soumis son numéro de téléphone dans l'invite d'identification. Affiche "Estamos entrando em contato" ("Nous prenons contact avec") avec une animation de "respiration" de l'image centrale et trois points avec des animations d'opacité décalées (300ms décalage par point) produisant un visuel "connectant". L'opérateur ou un complice peut alors appeler le vrai téléphone de la victime en se faisant passer pour le personnel de sécurité de la banque.
Progress Steps : Un écran de décrochage entièrement modelé par l'opérateur, affichant une liste de fausses étapes de traitement avec une animation aléatoire. Les durées des étapes sont aléatoires et totalisent environ 15 minutes. Une minuterie fait avancer chaque étape de manière séquentielle, en marquant visuellement les étapes terminées, en mettant en évidence l'étape en cours et en atténuant les étapes restantes. Lorsque toutes les étapes sont terminées, la séquence revient à une position antérieure avec de nouveaux horaires aléatoires et se poursuit.
Fake Windows Update : un écran de décrochage alternatif imitant l'écran de mise à jour et de redémarrage de Windows 10/11. Affiche un arrière-plan solide #0078D7 (bleu accentué de Windows) avec un indicateur de rotation à cinq ellipses disposé en cercle. L'affichage du pourcentage varie de 25 à 35% à des intervalles de 50 à 81 secondes choisis de manière aléatoire, afin d'imiter la progression irrégulière des véritables mises à jour de Windows. Sous-titre par défaut : "Trabalhando em atualizacoes" ("Travaillant sur les mises à jour").
Découpe de l'incrustation : Découpe un trou rectangulaire dans l'incrustation plein écran, exposant ainsi la fenêtre de l'application sous-jacente. L'opérateur spécifie les dimensions du trou via l'opcode 87, dans lequel le gestionnaire d'incrustation construit une carte à thème avec un espace réservé à la bordure transparente, calcule ses coordonnées d'écran après la mise en page et découpe un trou de région correspondant à l'aide de CreateRectRgn + CombineRgn(RGN_DIFF) + SetWindowRgn. La fenêtre cible est repositionnée sous le trou. Le résultat est une fenêtre d'application réelle encadrée par la superposition, et la victime interagit avec l'application réelle tandis que la superposition environnante fournit un contexte trompeur.
Module ver
Le deuxième module invoqué par le chargeur est Tcl.WppBot, conçu pour propager des messages de spam et d'hameçonnage à grande échelle, afin de distribuer TCLBANKER. Deux types d'agents distincts ont été récupérés dans deux chargeurs différents et analysés :
- Un ver WhatsApp qui détourne les sessions de navigation
- Un robot de messagerie qui abuse de Microsoft Outlook par le biais de l'interopérabilité COM
Tcl.WppBot est également protégé par .NET Reactor avec la même version que celle utilisée pour protéger Tcl.Agent, et nous avons donc également réussi à désobfusquer statiquement les charges utiles à ce stade.
Les deux agents partagent le même backend C2, les mêmes identifiants d'authentification et la même infrastructure opérationnelle. L'URL C2 et la clé API sont décryptées au démarrage à l'aide d'un décryptage XOR avec une clé codée en dur.
- C2 URL :
campanha1-api.ef971a42.workers[.]dev(Cloudflare Workers app) - Clé API / jeton porteur :
0d21613a-2609-45fc-83ff-d0feaa0c891f
Le C2 sert un seul objet de configuration de campagne superposé via le point de terminaison https://campanha1-api.ef971a42.workers[.]dev/api/campaign. Chaque variante d'agent désérialise l'objet complet mais ne lit que les champs pertinents pour son canal.
Configuration capturée :
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
Le même compte Cloudflare ef971a42 héberge également le CDN de livraison des données utiles (domaine pour fileUrl dans l'objet de configuration) à documents.ef971a42.workers[.]dev. Accessible via le point de terminaison /file, il sert actuellement un fichier zip contenant le MSI LogiAI Prompt Builder trojanisé par TCLBANKER. Cette décision d'infrastructure permet à l'opérateur de redéployer rapidement l'infrastructure sans avoir à maintenir des serveurs dédiés.
A l'heure où nous écrivons ces lignes, le domaine de phishing arquivos-omie[.]com identifié dans la configuration ci-dessus, créé le 2026-04-15, n'est pas opérationnel (Welcome ! Ce portail fait actuellement l'objet d'une maintenance programmée. Veuillez réessayer plus tard.) La campagne peut en être à ses premiers stades opérationnels ou être prête pour l'attribution des tâches. Ce domaine est également nommé pour usurper l'identité d'un progiciel de gestion intégré (ERP) brésilien très répandu.
Agent 1 : WhatsApp Bot
L'agent WhatsApp prend silencieusement le contrôle de la session Web WhatsApp authentifiée de la victime pour envoyer des messages de spam et distribuer TCLBANKER aux contacts brésiliens.
Détournement de session
Le logiciel malveillant commence par découvrir les navigateurs basés sur Chromium sur le système cible, puis analyse les entrées du registre App Paths et les répertoires d'installation communs pour Chrome, Edge, Brave, Opera et Vivaldi. Il parcourt ensuite les profils d'utilisateur de chaque navigateur (par exemple, "Default," " Profile 1," etc.), à la recherche de preuves d'une session Web WhatsApp active. Un profil est signalé comme ayant une session authentifiée si son stockage IndexedDB contient le répertoire WhatsApp Web LevelDB à l'adresse <profile_dir>/IndexedDB/https_web.whatsapp[.]com_0.indexeddb.leveldb/.
Chaque profil est ensuite envoyé à la fonction de clonage de profil et de détournement de session.
Pour chaque profil admissible, le logiciel malveillant le clone dans un répertoire temporaire à l'adresse %TEMP%\<GUID>\, en copiant uniquement les fichiers nécessaires à la reprise de la session Web WhatsApp : IndexedDB Local Storage, Session Storage, databases, Web Data, Login Data et Cookies. Il lance ensuite une instance de Chromium sans tête via Selenium WebDriver, avec --user-data-dir pointant vers le profil cloné.
La correspondance avec chromedriver.exe est résolue au moment de l'exécution par un binaire Selenium Manager déguisé déposé à %TEMP%\msvc-rt14\bin\hostfxr.exe, qui est invoqué avec --browser chrome --output json et renvoie le chemin d'un pilote chromé compatible avec la version de Chrome installée chez la victime.
Immédiatement après le lancement, le logiciel malveillant injecte du JavaScript pour contourner les cadres de détection des robots en cachant navigator.webdriver, remplit chrome.runtime, réconcilie l'incompatibilité des états Notification.permission / permissions.query, simule un tableau navigator.plugins non vide et définit navigator.languages à ['pt-BR', 'pt', 'en-US', 'en'] pour correspondre à la population ciblée.
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: {}
};
Une fois le profil cloné chargé, le navigateur se rend à l'adresse web.whatsapp[.]com, et le logiciel malveillant attend jusqu'à 45 secondes pour observer l'état de la page qui en résulte. Si l'interface de chat apparaît (l'IndexedDB clonée était valide et la session a repris sans scan QR), elle injecte une bibliothèque WA-JS(WPPConnect) intégrée et attend que WPP.contact.list et WPP.chat.sendTextMessage deviennent appelables avant de lancer la boucle de distribution de la campagne. Si l'invite du code QR est affichée à la place, le moteur renvoie "qr_code" sans tenter d'injection, puis essaie le profil candidat suivant.
Fonctionnalité anti-spam
Une fois l'injection réussie, le logiciel malveillant récupère la campagne active à partir du point de terminaison C2 https://campanha1-api.ef971a42.workers[.]dev/api/campaign, qui fournit le corps du message, l'URL de la pièce jointe facultative, la légende et les paramètres de synchronisation. TCLBANKER est ensuite téléchargé du serveur de fichiers à l'adresse https://documents.ef971a42.workers[.]dev/file et reconstruit dans le contexte du navigateur en tant qu'objet File, sans être déposé sur le disque.
Le logiciel malveillant appelle ensuite WPP.contact.list pour récupérer le carnet d'adresses de la victime, filtre les groupes, les diffusions et les numéros non brésiliens, et commence à envoyer des messages par l'intermédiaire de WPP.chat.sendTextMessage et sendFileMessage. Le logiciel malveillant signale l'état d'avancement au point d'extrémité C2 /api/progress après chaque lot, et interroge /api/control pour obtenir des commandes de pause ou de renvoi à distance de la part de l'opérateur.
Agent 2 : Outlook Email Bot
L'agent Outlook est un spambot qui abuse de l'application Microsoft Outlook installée chez la victime pour envoyer des courriels d'hameçonnage à partir de l'adresse électronique de la victime, ce qui les rend plus difficiles à détecter en tant que spam que les courriels envoyés à partir d'une infrastructure contrôlée par l'attaquant.
Outlook Discovery & COM Attachment
Si OUTLOOK.EXE n'est pas déjà en cours d'exécution, il tente de localiser l'installation dans les entrées de registre de App Paths et les répertoires d'installation connus et la lance dans un nouveau processus. Le logiciel malveillant s'attache ensuite au processus via l'interopérabilité COM : Marshal.GetActiveObject("Outlook.Application")et vérifie qu'il dispose d'au moins un compte de messagerie configuré.
Contacter la récolte
Le logiciel malveillant dépose ensuite un script PowerShell, %TEMP%\oc<guid>.ps1,, qui récolte les contacts via Outlook COM à partir d'un processus distinct. Il récolte les contacts à partir de deux sources : tout d'abord, il lit le dossier Contacts par défaut pour toutes les entrées de contact, en extrayant les adresses électroniques et les noms complets de chaque élément de contact. Ensuite, il parcourt les dossiers racine de chaque magasin pour trouver des dossiers similaires à ceux de la boîte de réception, trie les messages de la boîte de réception par ordre chronologique et extrait les adresses électroniques et les noms des expéditeurs avant de les écrire dans un fichier .txt au format email|name.
Pour chaque courriel candidat, un filtrage supplémentaire est effectué afin de maximiser la délivrabilité.
Fonctionnalité anti-spam
À l'instar du bot WhatsApp, le logiciel malveillant récupère la campagne active sur https://campanha1-api.ef971a42.workers[.]dev/api/campaign, puis envoie des courriels par l'intermédiaire des comptes Outlook de la victime via l'automatisation COM. Chaque courrier électronique est construit via outlookApp.CreateItem(0) (MailItem) avec le destinataire dans To, l'objet de la campagne et le contenu de la campagne emailMessage, et envoyé en utilisant le compte réel de la victime via SendUsingAccount.
Entre les envois, l'agent applique un délai aléatoire et vérifie périodiquement le point de contrôle C2 /api/control pour les commandes de pause ou de renvoi, et signale les progrès à /api/progress.
Infrastructure
Les acteurs de REF3076 ont exploité l'infrastructure sans serveur de Cloudflare ( worker[.]dev ) pour l'hébergement de C2 et de fichiers. Cette décision leur permet d'hériter de la confiance que les victimes pourraient déjà avoir dans Cloudflare et de changer rapidement d'infrastructure si nécessaire.
En nous basant sur le body-hash (91fafaa1240676afe5c55d931261e3798797c408) du site d'hameçonnage ci-dessus (arquivos-omie[.]com), nous avons pu identifier d'autres domaines qui sont probablement en train d'être préparés à la militarisation :
| Domain | First Seen | Info | ASN (Providor) |
|---|---|---|---|
| arquivos-omie[.]com | 2026-04-17 | Squatting - SaaS brésilien pour les PME | AS 13335 (Cloudflare) |
| documentos-online[.]com | 2026-04-11 | Generic | AS 13335 (Cloudflare) |
| afonsoferragista[.]com | 2026-04-22 | Quincaillerie - Probablement utilisée dans un leurre B2B | AS 13335 (Cloudflare) |
| doccompartilhe[.]com | 2026-04-15 | Générique - "Partager un document" | AS 13335 (Cloudflare) |
| recebamais[.]com | 2026-04-20 | Squatting - Courtage de crédits brésiliens | AS 13335 (Cloudflare) |
D'autres infrastructures d'hameçonnage brésiliennes ont été découvertes après un pivot plus large dans le titre de la bannière (Portal Corporativo), mais il n'est pas clair si elles sont directement liées à REF3076 ou à d'autres acteurs de l'écosystème des chevaux de Troie bancaires d'Amérique latine. Notamment, un groupe a utilisé le produit d'hébergement gratuit de sites statiques Cloudflare pages[.]dev.
Le domaine C2 mxtestacionamentos[.]com pointait auparavant vers une adresse IP hébergée au Brésil 191.96.224[.]96.
L'année dernière, cette adresse IP hébergeait simultanément un domaine C2 REF3076, un domaine d'hameçonnage REF3076 et un domaine précédemment associé à la campagne Water Saci et au logiciel malveillant SORVEPOTEL/MAVERICK par TrendMicro (saogeraldoshiping[.]com).
Conclusion
TCLBANKER est le reflet d'une maturation plus large de l'écosystème des chevaux de Troie bancaires brésiliens. Les techniques qui étaient autrefois l'apanage des acteurs les plus sophistiqués : décryptage des charges utiles en fonction de l'environnement, génération directe de syscall, orchestration de l'ingénierie sociale en temps réel via WebSocket, sont aujourd'hui intégrées dans des logiciels criminels courants. La barrière à l'entrée continue de baisser, en particulier lorsque des LLM puissants sont facilement accessibles pour la génération de code.
L'inclusion de modules de vers autopropagés marque un changement notable dans ce domaine. La campagne hérite de la confiance et de la fiabilité des communications légitimes en détournant les sessions WhatsApp et les comptes Outlook des victimes. Il s'agit d'un modèle de distribution que les passerelles de courrier électronique traditionnelles et les défenses basées sur la réputation sont mal équipées pour appréhender. Comme les trojans bancaires latino-américains continuent d'adopter ces mécanismes d'autodiffusion, les organisations doivent s'attendre à ce que le volume et la portée de ces campagnes augmentent en conséquence.
Les artefacts des développeurs tout au long de la chaîne, y compris les chemins de journalisation de débogage, les noms des processus de test et un site d'hameçonnage encore en cours de construction, suggèrent que REF3076 en est à ses premiers stades opérationnels. Il s'agit d'une campagne en cours d'élaboration, et non d'une campagne en cours d'achèvement.
REF3076 par MITRE ATT&CK
Elastic utilise le cadre MITRE ATT& CK pour documenter les tactiques, techniques et procédures communes que les menaces utilisent contre les réseaux d'entreprise.
Tactiques
Les tactiques représentent le pourquoi d'une technique ou d'une sous-technique. Il s'agit de l'objectif tactique de l'adversaire : la raison pour laquelle il effectue une action.
- Accès initial
- Exécution
- Persistance
- Évasion par la défense
- Accès aux identifiants
- Découverte
- Collecte
- Commande et contrôle
- Exfiltration
- Impact
Techniques
Les techniques représentent la manière dont un adversaire atteint un objectif tactique en effectuant une action.
- Phishing: Spearphishing Attachment
- Exécution du proxy binaire du système : Msiexec
- Flux d'exécution du pirate : chargement latéral de DLL
- Interprète de commandes et de scripts : PowerShell
- Interprète de commandes et de scripts : Shell de commande Windows
- Tâche programmée/Job : Tâche programmée
- Deobfuscate/Decode Files or Information
- Masquage des fichiers ou des informations
- Evasion du débogueur
- Évasion de virtualisation/sandbox : vérifications du système
- Évasion par virtualisation/boîte à sable : Evasion basée sur le temps
- Affaiblir les défenses : Désactiver ou modifier des outils
- Native API
- Injection de processus
- Découverte du processus
- Découverte de la fenêtre d'application
- Recherche d'informations sur le système
- System Location Discovery: System Language Discovery
- Capture d'écran
- Capture d'entrée : Enregistrement du clavier
- Données du presse-papiers
- Capture d'entrée : Capture sur le portail web
- Détournement de la session du navigateur
- Protocole de la couche d'application : Protocoles Web
- Service Web
- Transfert d'outils d'infiltration
- Collecte d'emails : Collecte locale d'e-mails
- Arrêt/redémarrage du système
Remédiation REF3076
La prévention
- Modification de la protection de la mémoire NTDLL via une DLL non signée
- La bibliothèque NTDLL est chargée pour la deuxième fois
- Décrochage potentiel de la mémoire NTDLL
- Parallel NTDLL Loaded from Unbacked Memory
- Modification suspecte du module de base de Windows
- Contournement de l'AMSI par la mémoire non sauvegardée
- Contournement potentiel de l'AMSI via SetThreadContext
YARA
Elastic Security a créé des règles YARA pour identifier cette activité.
Observations
Les observables suivants ont été examinés dans le cadre de cette recherche.
| Observable | Type | Nom | Référence |
|---|---|---|---|
| 701d51b7be8b034c860bf97847bd59a87dca8481c4625328813746964995b626 | SHA-256 | screen_retriever_plugin.dll | Composant du chargeur TCLBanker |
| 8a174aa70a4396547045aef6c69eb0259bae1706880f4375af71085eeb537059 | SHA-256 | screen_retriever_plugin.dll | Composant du chargeur TCLBanker |
| 668f932433a24bbae89d60b24eee4a24808fc741f62c5a3043bb7c9152342f40 | SHA-256 | screen_retriever_plugin.dll | Composant du chargeur TCLBanker |
| 63beb7372098c03baab77e0dfc8e5dca5e0a7420f382708a4df79bed2d900394 | SHA-256 | XXL_21042026-181516.zip | Fichier ZIP initial de TCLBanker |
| campanha1-api.ef971a42[.]workers.dev | nom de domaine | TCLBanker C2 | |
| mxtestacionamentos[.]com | nom de domaine | TCLBanker C2 | |
| documents.ef971a42.workers[.]dev | nom de domaine | Serveur de fichiers TCLBanker | |
| arquivos-omie[.]com | nom de domaine | Page d'hameçonnage TCLBanker (en cours de développement) | |
| documentos-online[.]com | nom de domaine | Page d'hameçonnage TCLBanker (en cours de développement) | |
| afonsoferragista[.]com | nom de domaine | Page d'hameçonnage TCLBanker (en cours de développement) | |
| doccompartilhe[.]com | nom de domaine | Page d'hameçonnage TCLBanker (en cours de développement) | |
| recebamais[.]com | nom de domaine | Page d'hameçonnage TCLBanker (en cours de développement) |