TCLBANKER: Troyano bancario brasileño que se propaga a través de WhatsApp y Outlook

REF3076 emplea un instalador trojanizado de Logitech para desplegar TCLBANKER, un troyano bancario brasileño con payloads bloqueados por el entorno, superposiciones de fraude WPF y módulos gusanos de WhatsApp y Outlook autopropagables.

Elastic Security Labs identificó un nuevo troyano bancario brasileño que estamos rastreando como TCLBANKER, una familia de malware que evaluamos como una actualización importante de la familia MAVERICK/SORVEPOTEL. La campaña, registrada como REF3076, cuenta con un loader con robustas capacidades antianálisis que despliega dos módulos protegidos por .NET Reactor integrados: un troyano bancario completo y un módulo gusano para la autopropagación.

El troyano bancario monitoriza la barra de direcciones del navegador de la víctima mediante UI Automation, dirigir 59 dominios brasileños de banca, fintech y criptomonedas. Más allá de los comandos habituales de acceso remoto, su capacidad más destacada es un marco de superposición a pantalla completa basado en WPF, diseñado para la ingeniería social impulsada por el operador.

Un segundo módulo gestiona la distribución a través de agentes de spam, de los cuales recuperamos dos variantes: un gusano de WhatsApp que secuestra sesiones de navegador autenticadas para enviar mensajes a los contactos de la víctima, y un bot de correo de Outlook que envía correos de phishing a través de las propias cuentas de la víctima mediante automatización COM.

A través de este reporte, ofrecemos un desglose técnico detallado de cada etapa.

Conclusiones clave

  • TCLBANKER emplea descifrado de cargas útiles con control de entorno; Los entornos incorrectos, como los sandboxes, fallan silenciosamente en descifrar la carga útil
  • Un subsistema de vigilancia integral monitoriza continuamente herramientas de análisis, depuradores, marcos de instrumentación y violaciones de integridad durante toda la ejecución
  • El troyano bancario apunta 59 dominios brasileños de banca, fintech y criptomonedas, activando una sesión WebSocket C2 cuando una víctima accede a un sitio monitorizado
  • Un marco de superposición a pantalla completa basado en WPF permite la ingeniería social impulsada por el operador, incluyendo la obtención de credenciales, la visualización de pantallas de espera y los bloqueos falsos de Windows Update, mientras oculta superposiciones de las herramientas de captura de pantalla
  • Los módulos de gusano propagan el malware: un bot de WhatsApp y un bot de correo de Outlook
  • Toda la infraestructura C2 y de distribución está alojada en Cloudflare Workers bajo una sola cuenta, con artefactos de desarrollador (rutas de registro de depuración, nombres de procesos de prueba) y una página de phishing incompleta, lo que sugiere que la campaña fue identificada en una etapa operativa temprana

Entrega

TCLBANKER es un troyano bancario brasileño que contiene una cadena de infección dinámica con un componente pesado de carga anti-análisis capaz de desplegar dos cargas útiles integradas (gusano, banquero). La cadena de infección observada agrupa un instalador malicioso de MSI dentro de un archivo ZIP. Estos paquetes de instalación de MSI están abusando de un programa firmado de Logitech llamado Logi AI Prompt Builder.

TCLBANKER abusa de la carga lateral de DLL contra LogiAiPromptBuilder.exe, una aplicación legítima de Logitech construida sobre el framework Flutter . La screen_retriever_plugin.dll maliciosa DLL se hace pasar por un plugin legítimo de Flutter con el mismo nombre y se carga automáticamente cuando se inicia la aplicación anfitriona.

Tras la instalación de MSI, la DLL maliciosa se carga inmediatamente y comienza en el punto de entrada de DllMain.

Cargador

El componente loader de TCLBANKER está cargado de funciones, incluyendo antidepuración, comprobaciones antianálisis, cifrado de cadenas, comprobaciones del lenguaje del sistema, parcheos ETW y capacidad de watchdog. Aunque tiene muchas funciones, carece de profundidad y hace referencias a herramientas antiguas de análisis de malware. No está del todo claro si el desarrollador empleó flujos de trabajo asistidos por LLM, pero a nuestro equipo no le sorprendería que fuera así.

Al inicio de la ejecución, TCLBANKER alinea las cargas útiles correspondientes de ensamblador .NET en función de si la cadena (--renderer=sw) se usa en la línea de comandos. Dentro de su función principal de cargador, primero realiza operaciones de lista de licencias/listas de bloqueo basadas en cómo se cargó la DLL. La DLL maliciosa solo se ejecutará si el proceso anfitrión proviene de los siguientes dos procesos:

  • logiaipromptbuilder.exe
  • tclloader.exe (Posible referencia a la cadena de revelador durante las pruebas)

Si la DLL fue cargada por los siguientes procesos, se negará a ejecutar. Estos procesos son tradicionalmente empleados por los analistas para cargar y depurar DLLs.

  • rundll32.exe
  • regsvr32.exe
  • dllhost.exe
  • svchost.exe

A continuación, TCLBBANKER elimina cualquier enganche en modo usuario reemplazando ntdll.dll del disco. Para mayor evasión, el malware genera los siguientes trampolines de llamada syscall que se usarán posteriormente:

  • NtQueryInformationProcess
  • NtSetInformationThread
  • NtSetInformationProcess
  • NtTerminateProcess
  • NtAllocateVirtualMemory
  • NtProtectVirtualMemory

Tras instalar los stubs de syscall, el malware se EtwEventWrite en ntdll.dll con la tradicional xor eax, eax; ret de desactivar la telemetría ETW en modo usuario.

TCLBANKER realiza una comprobación inicial sandbox capturando un tick inicial usando GetTickCount64(), en modo de suspensión durante 500 ms y midiendo el tiempo transcurrido. Si pasaron menos de 450 ms, el malware desaparece — esto detecta sandboxes o frameworks de emulación que activan el Sleep para que vuelva inmediatamente...

Una de las características más interesantes de TCLBANKER es una función de enumeración que genera tres huellas dactilares basadas en los siguientes criterios:

  • Comprobaciones antidepuración
  • Información del sistema de disco y comprobaciones de memoria
  • Comprobaciones de idioma

El desarrollador emplea constantes mágicas asignadas a los caminos "limpios" de cada categoría, y luego realiza un XOR contra cada una para generar el hash del entorno. Este valor hash de entorno es significativo porque afecta al descifrado posterior de la carga útil embebida.

Por ejemplo, si hay un depurador presente, producirá un hash incorrecto, por lo que cuando el malware intente derivar las claves de descifrado a partir del hash, la carga útil no se descifrará correctamente y TCLBANKER dejará de ejecutar.

Comprobaciones antidepuración

TCLBANKER implementa seis comprobaciones diferentes de antidepuración:

  • Identifica el depurador mediante la bandera Peb->BeingDebugged
  • Comprueba las banderas de heap-tail/heap-free/check-heap que se activan cuando un proceso se lanza bajo un depurador
  • Apalancamientos NtQueryInformationProcess() usar ProcessDebugPort
  • Usos NtQueryInformationProcess() usar ProcessDebugObjectHandle
  • Detección de puntos de interrupción por hardware mediante los registros de depuración (DR0-DR3)
  • Mide el tiempo transcurrido usando QueryPerformanceCounter() deltas y RDTSC recuentos cíclicos

Comprobaciones de información del sistema

TCLBANKER tiene las siguientes cinco comprobaciones diferentes basadas en la virtualización, el sistema y la información del usuario:

  • Comprobaciones de software de virtualización usando firma de proveedor
HipervisorFirma del proveedor
VMwareVMwareVMware
VirtualBoxVBoxVBoxVBox
KVMKVMKVMKVM
XenXenVMMXenVMM
ParallelsPRL Hyperv
QEMU/TCGTCGTCGTCGTCG
  • Verifica que el disco del sistema raíz (C:\\) con GetDiskFreeSpaceExW() tenga al menos 64 GB
  • Las llamadas GlobalMemoryStatusEx() para verificar que el sistema tiene más de 2 GB de RAM
  • Comprueba si 2 o procesadores de CPU mediante GetSystemInfo()
  • Comprueba nombres de usuario genéricos de sandbox/malware
    • sandbox, malware, virus, sample, john doe, currentuser

Comprobaciones de idioma

Para la última verificación de huellas dactilares ambientales, TCLBANKER obtiene información geográfica de la máquina infectada usando GetUserGeoID(), dirigida a usuarios brasileños según el ID geográfico (0x20). Una segunda comprobación de localización mediante GetUserDefaultLCID() también garantiza que el idioma predeterminado del usuario sea el portugués brasileño (pt-BR, LANGID 0x0416).

Tras estos conjuntos de comprobaciones, TCLBANKER o bien abandonará la ejecución si se detecta algo o, si no, producirá otra comprobación antidepuración parcheando DbgUiRemoteBreakin(). El malware parchea su primer byte a a ret instrucción, de modo que cualquier intento de interrumpir remotamente el proceso no sirve de nada: el hilo inyectado regresa inmediatamente y el destino sigue ejecutar, sin suspender.

Luego de esto, el malware obtiene una clave CBC AES-256 y un IV usando constantes codificadas directamente de la sección .rdata junto con el hash ambiental calculado anteriormente. TCLBanker emplea BCryptDecrypt() para descifrar la carga útil embebida, luego descomprime mediante RtlDecompressBuffer usando el algoritmo de compresión LZNT1.

Una vez descifrada la carga útil correspondiente, TCLBANKER inicializa COM vía CoInitializeEx() y emplea las APIs de alojamiento CLR para cargar el entorno de ejecución .NET en proceso. Antes de lanzar el punto de entrada de la carga útil, TCLBanker crea dos nuevos hilos: uno sirve como watchdog y el otro monitoriza el watchdog como comprobación del latido.

Guardián

TCLBANKER cuenta con una función de vigilancia integral que se dirige a diversas herramientas de análisis, incluyendo desensambladores, depuradores, productos de instrumentación, productos antivirus y productos sandbox. Esta sección describirá las distintas técnicas empleadas por esta sección:

  • Comprobación del depurador mediante PEB→BeingDebugged
  • Relojes para puntos de interrupción de hardware DR0/DR1/DR2/DR3
  • Comprueba funciones de Windows (BCryptDecrypt(), BCryptOpenAlgorithmProvider()) en busca de ganchos en línea escaneando los primeros 12 bytes de cada función
  • Monitores para herramientas de instrumentación y cuerdas relacionadas (frida, cydia, user-path injection, hook framework)
  • Revisa todas las tuberías con nombre de kernel que buscan frida o linjector
  • Realiza la enumeración de procesos mediante CreateToolhelp32Snapshot() dirigida a los siguientes nombres de procesos:
    • frida, de4dot, dnspy, megadumper, extremedumper, processhacker, x64dbg, x32dbg, pe-sieve, scylla, Ilspy, dotpeek, netreactorslayer, cheatengine

  • Emplea detección de títulos en Windows mediante GetWindowTextW() con estos títulos:
    • x64dbg, x32dbg, ida -, ida pro, ghidra, dnspy, megadumper, extremedumper, processhacker, ollydbg, windbg)_, pe_sieve, scylla
  • Identifica las herramientas de los analistas basar en los siguientes nombres de clases de ventana mediante FindWindowW():
    • IDATopLevelWindow, idaabortwndclass, TIdaWindow, x64dbg, x32dbg, OLLYDBG, WinDbgFrameClass, ProcessHacker, SystemInformer, CheatEngine, HxdClass
  • Comprobaciones para los siguientes módulos cargados
    • dbeng.dll, dbgcore.dll, SbieDll.dll, snxhk.dll, cmdvrt32.dll, cmdvrt64.dll, cuckoomon.dll, pstorec.dll, vmcheck.dll, wpespy.dll
  • Apunta a los siguientes mutexes y eventos:
    • Ida_trusted_idbs, IDA_COMM_PIPE_, Local\\x64dbg, Local\\x32dbg, Frida, YOURAPPNAMEHERE
  • Realiza CRC32 comprobación de integridad en la sección .text para evitar cualquier manipulación

Módulo de Troyano Bancario

Tcl.Agent es un troyano bancario, el componente principal de la cadena. Está protegido por .NET Reactor y, aunque no logramos desofuscarlo usando herramientas de código abierto disponibles como de4dot y NETReactorSlayer, logramos desofuscar esta etapa estáticamente hasta un estado satisfacible usando una tubería de desofuscación personalizada para abordar el cifrado de cadenas de .NET Reactor, aplanamiento de flujo de control, mutación IL, proxies de delegado y cuerpos de métodos cifrados (Necrobit). Aunque es un malware nuevo, gran parte de la estructura del código sigue el plan de implementación del troyano bancario LATAM de ESET, publicado en 2020.

Al principio, el malware realiza geovallado, requiriendo >= 2 de los siguientes indicadores para coincidir con Brasil; de lo contrario, sale inmediatamente si no es en una máquina brasileña:

CompruébaloImplementación
Código de regiónnuevo RegionInfo (CultureInfo.CurrentCulture.LCID). TwoLetterISORegion Name == "BR"
Zona horariaTimeZoneInfo.Local.BaseUtcOffset.TotalHours: si >= -5.0, comprueba si == -2.0
LCIDCultureInfo.CurrentCulture.LCID == 1046 (portugués-brasileño)
TecladoGetKeyboardLayoutList() - revisa cada diseño: (ToInt32() & 0xFFFF) == 1046

Instalación y persistencia

En la primera ejecución, el malware copia todo el directorio de la aplicación en %LocalAppData%\LogiAI. Calcula un hash SHA-256 sobre todos los archivos .dll y .exe en el directorio fuente y lo escribe en un archivo marcador .version . En las ejecuciones posteriores, compara hashes con saltar copias redundantes. Luego de copiar, lanza la nueva instancia desde la ruta de instalación y sale.

Crea una tarea programada llamada RuntimeOptimizeService usando interoperación COM con el Planificador de Tareas (CLSID 0F87369F-A4E5-4CFC-BD3E-73E6154572DD). La tarea está configurada como oculta, habilitada, sin límite de tiempo de ejecución, permitida en batería, iniciada cuando esté disponible, y se dispara en un disparador de inicio de sesión (type 9) con alcance al usuario actual. Se registra con TASK_CREATE_OR_UPDATE y TASK_LOGON_SERVICE_ACCOUNT.

Una vez establecida la persistencia, el agente envía una baliza POST de primera ejecución para https://campanha1-api.ef971a42.workers[.]dev/api/installs con el Identificador del agente (MachineName-UserName), NombreMáquina, Nombre de usuario (redundante) y la versión del sistema operativo. La solicitud se autentica con un token de autenticación de campaña codificado 0d21613a-2609-45fc-83ff-d0feaa0c891f. La variante más reciente agrega registro de depuración alrededor de esta llamada (C:\temp\tcl-debug.txt), un artefacto de desarrollador que expone inadvertidamente la presencia del agente en el disco.

Autoactualización

El agente implementa una puerta de autoactualización basada en hash que se ejecuta al principio de la cadena de arranque. Lee un hash de versión local de flutter_engine.cfg en su directorio de instalación (migrando desde un nombre de archivo version.hash heredado si está presente), y luego obtiene el hash actual desde el punto final del servidor de archivos documents.ef971a42.workers[.]dev/api/version usando una cadena truncada de User-Agent (Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36.

La respuesta se analiza para la clave "hash". Si el hash remoto coincide con el hash local, la ejecución continúa normalmente. En la primera instalación, el hash remoto se escribe en el disco y la ejecución continúa sin actualizar.

Cuando se detecta una discrepancia de hash, el agente descarga la carga útil de actualización desde documents.ef971a42.workers[.]dev/api/update como MSI a %TEMP%\update_{8hexchars}.msi, autenticado con el token portador b7ba9e80-0d04-4d9e-b217-c8b3cce335a2.

La descarga se valida con un tamaño mínimo de 100KB como comprobación de la cordura. El agente entonces escribe un script por lotes auto-eliminante en %TEMP% que consulta la lista de tareas hasta que el proceso actual sale, ejecuta msiexec /i /qn REINSTALLMODE=amus para una instalación silenciosa y se elimina a sí mismo. El archivo batch se lanza mediante un proceso oculto de cmd.exe antes de que el agente termine, pasando la ejecución a la carga útil actualizada.

Monitor de URL del navegador e inicialización de sesión C2

Cada segundo, el agente de malware llama a una función de monitor de URL del navegador que lee la barra de direcciones del navegador en primer plano mediante la automatización de la interfaz de usuario. Llama a GetForegroundWindow, resuelve el proceso propietario, comprueba el nombre del proceso con Chrome, Firefox, Microsoft Edge, Brave, Opera y Vivaldi, y luego emplea AutomationElement.FromHandle -> FindFirst(Descendants, ControlType.Edit) -> ValuePattern.Current.Value para extraer la URL, similar a esta implementación de Stack Overflow.

La URL extraída se compara con una lista fija de bancos objetivo incrustados en el binario, codificados mediante XOR con una clave de 16 bytes y codificación base64.

Este resumen de GitHub contiene una lista de 59 dominios objetivo, incluyendo banca brasileña, plataformas fintech y exchanges de criptomonedas, agrupados por los IDs objetivo añadidos a cada dominio descifrado.

Cuando se produce una coincidencia, el ID del destino de dominio se pasa al siguiente estado, que inicializa la comunicación oficial C2 estableciendo una conexión WebSocket a wss://mxtestacionamentos[.]com/ws. El gestor de OnConnect se ejecuta, enviando un paquete de registro que contiene el ID del agente (un GUID aleatorio en tiempo de ejecución), NombreMáquina, Nombre de Usuario, información de la máquina, marca de tiempo, ID de destino de dominio (para que el C2 sepa qué sitio web abrió la víctima) y una firma.

Para producir una firma de handshake, se emplea HMAC-SHA256 para firmar el identificador de la víctima (ID del agente, NombreMáquina, Nombre de Usuario, OSVersion, marca de tiempo) usando el 70e4f943-e323-4484-97d7-35401bf6812c GUID de campaña como clave.

El servidor responde entonces con un acuse de recibo de registro, iniciando oficialmente la sesión, y entra en el bucle de despacho de comandos. Al inicio de la sesión, se activa un asesino del Administrador de tareas cada 500 ms para evitar que la víctima inspeccione o termine el proceso del agente.

Tabla de comandos C2

Un resumen de capacidades se describe a través de la tabla de opcode a continuación:

Código de operaciónObjetivo
2Registro ACK, iniciar el asesino del Administrador de tareas
4Desconexión WebSocket elegante
5Suicidio: Matar todos los procesos hermanos y salir
6Resetear forzado (shutdown.exe /r /t 0 /f)
7Suicide-then-Uninstall: eliminar todos los procesos con el mismo nombre binario del host excepto él mismo (hermanos) → desinstalar → salir
16Captura de pantalla
17Empieza a hacer streaming por la pantalla
18Deja de transmitir la pantalla
19Configurar la calidad de la captura de pantalla (1-100)
20Enumerar monitores
32Movimiento del mouse (X, Y, MonitorIndex)
33Clic del mouse a través de la superposición: analizar {X,Y,Button,MonitorIndex} → traducir en coordenadas absolutas de escritorio → encontrar la propia ventana de superposición del implante que cubra ese punto → perforar un agujero de región 2x2 en la superposición a ese → SetCursorPos de pixel + SendInput con el mouse hacia abajo/arriba (que cae sobre el contenido real de escritorio que hay debajo de la superposición).
34Desplazamiento del mouse (Delta, SendInput)
35Tecla (KeyCode, SendInput)
37Tecla abajo (KeyCode, SendInput)
38Teclado hacia arriba (Código de tecla, SendInput)
39Iniciar el keylogger (WH_KEYBOARD_LL hook)
40Keylogger de flush, exfiltración a C2
41Secuestro de portapapeles (Clipboard.SetText)
48Listado de directorios del sistema de archivos
65Obtener información sobre procesos en ejecución
67Ejecución de comandos en shell (cmd.exe /c)
80Enumerar todas las ventanas visibles
81Gestor de ventanas: Eliminar el proceso de una ventana / minimizar ventana / restaurar ventana / llevar la ventana al primer plano / cerrar ventana / mover ventana a otro monitor
83Mostrar superposición de estancamiento: ya sea pasos de progreso o una pantalla falsa de actualización de Windows
84Superposición de desmontaje
85Alterna la inmunidad a la captura de pantalla. Activa/desactiva WDA_EXCLUDEFROMCAPTURE en todas las ventanas superpuestas para ocultarlas de compartir pantalla o capturas de pantalla.
86Actualizar contenido de superposición
87Mostrar superposición de recorte: fijar la ventana exterior dentro de la superposición con recorte de región visible
96Mostrar superposición de aviso de credenciales

Marco de UI de Ingeniería Social

Una capacidad más interesante del troyano bancario es un subsistema de superposición a pantalla completa basado en WPF que orquesta flujos de fraude temáticos bancarios durante sesiones C2 activas.

Ciclo de vida superpuesto

El gestor de superposición genera una ventana WPF a pantalla completa por monitor. Las ventanas se configuran como sin bordes, superiores y ocultas de la barra de tareas (WindowStyle.None, Topmost = true, ShowInTaskbar = false), con un control de Closing personalizado que se niega a ser descartado hasta que el operador active una bandera interna mediante el comando de desmontaje superpuesto, impidiendo que las ventanas se cierren.

Al iniciar, el gestor captura una captura de pantalla PNG de cada pantalla a través de CopyFromScreen como fondo superpuesto, creando un aspecto de "escritorio congelado". Dependiendo de la superposición activa, la víctima percibe su entorno de escritorio real detrás de ella.

Un temporizador de 500ms se reaplica continuamente HWND_TOPMOST mediante SetWindowPos para anular cualquier ventana que intente aparecer por encima de la superposición.

Además, una función anti-captura llama a SetWindowDisplayAffinity con WDA_EXCLUDEFROMCAPTURE, haciendo que la superposición sea invisible para cualquier herramienta de captura de pantalla, permitiendo al operador ver a través de su propia superposición mediante los comandos de captura de pantalla y de transmisión de pantalla.

Bloqueador de entrada

En el monitor principal se instalan dos ganchos: WH_KEYBOARD_LL y WH_MOUSE_LL. Ambos ganchos comprueban sus respectivas banderas inyectadas (LLKHF_INJECTED para teclado LLMHF_INJECTED para mouse), permitiendo que la entrada inyectada mediante SendInput por los comandos remotos del operador pase sin ser tocada. El gancho del teclado absorbe las teclas Tab, Escape, Alt+F4, Win, PrintScreen, Ctrl, Alt y todas las teclas de navegación; El gancho del mouse bloquea el clic derecho, el clic del medio y el desplazamiento, pero permite el clic izquierdo y el movimiento, por lo que la víctima puede seguir interactuando con las indicaciones superpuestas.

Constructores de interfaces de usuario de ingeniería social

Cinco renderizadores de contenido intercambiables se conectan al marco de superposición:

Prompt de credencial: Soporta tres modos de entrada, seleccionados según los parámetros de la solicitud del operador.

  • El modo teléfono aplica enmascaramiento en formato brasileño en tiempo real ((##) ####-##### para líneas fijas de 10 dígitos, (##) #####-#### para celulares de 11 dígitos) con un máximo de 11 dígitos.
  • El modo de teclado virtual muestra un teclado numérico en pantalla (botones 0–9 más "limpar"/clear), mostrando la entrada como viñetas para imitar la entrada de PIN.
  • El modo predeterminado acepta texto plano con una longitud máxima configurable.

Todos los modos se ejecutan mediante un validador de calidad que rechaza algorítmicamente las secuencias de los mismos dígitos (000000) y las secuencias ascendentes/descendentes (123456, 654321) para evitar que las víctimas introduzcan valores desechables.

La acción de submisión dispara los valores capturados al C2.

Pantalla de espera de vishing: Se activa después de que la víctima envíe su número de teléfono en el prompt de credencial. Muestra "Estamos entrando em contato" ("Nos estamos poniendo en contacto") con una imagen central que muestra una animación de "respiración" y tres puntos con animaciones de opacidad escalonadas (desplazamiento300ms por punto) que producen una imagen "conectiva". El operador o un cómplice puede entonces llamar al teléfono real de la víctima, hacer pasar por personal de seguridad del banco.

Pasos de progreso: Una pantalla de bloqueo totalmente con plantilla de operador que muestra una lista de pasos de procesamiento falsos con una animación aleatoria. Las duraciones de los pasos se aleatorizan para sumar aproximadamente 15 minutos. Un temporizador avanza secuencialmente en cada paso, marcando visualmente los pasos completados, resaltando el actual y atenuando los restantes. Cuando todos los pasos se completan, la secuencia se resetear a una posición anterior con nuevos tiempos aleatorios y continúa.

Actualización falsa de Windows: Una pantalla alternativa de bloqueo que imita la pantalla de actualización-resetear de Windows 10/11. Renderiza un fondo estable de #0078D7 (acento azul de Windows) con un indicador giratorio de cinco elipsis dispuesto en círculo. Un porcentaje de lectura aumenta aleatoriamente entre un 25 y un 35% en intervalos seleccionados aleatoriamente de 50 a 81 segundos para imitar el comportamiento irregular de progreso de las actualizaciones reales de Windows. Subtítulo por defecto: "Trabajando em atualizações" ("Trabajando en actualizaciones").

Superposición de recortes: Corta un agujero rectangular en la superposición de pantalla completa, exponiendo la ventana de aplicación subyacente. El operador especifica las dimensiones de los agujeros mediante el código de operación 87, en el que el gestor de superposición construye una tarjeta temática con un marcador de borde transparente, calcula sus coordenadas de pantalla tras el diseño y corta un agujero de región correspondiente usando CreateRectRgn + CombineRgn(RGN_DIFF) + SetWindowRgn. La ventana objetivo se reposiciona debajo del agujero. El resultado es una ventana real de aplicación enmarcada dentro de la superposición, y la víctima interactúa con la aplicación real mientras la superposición circundante proporciona un contexto engañoso.

Módulo de gusano

El segundo módulo invocado por el cargador es Tcl.WppBot, está diseñado para propagar mensajes de spam y phishing a gran escala, con el fin de distribuir TCLBANKER. Se recuperaron dos tipos distintos de agentes de dos cargadores diferentes y se analizaron:

  • Un gusano de WhatsApp que secuestra las sesiones del navegador
  • Un bot de correo de Outlook que abusa de Microsoft Outlook mediante interoperabilidad COM

Tcl.WppBot también está protegido por .NET Reactor con la misma versión empleada para proteger Tcl.Agent, por lo que también logramos desofuscar estáticamente las cargas útiles en esta etapa.

Ambos agentes comparten el mismo backend C2, credenciales de autenticación e infraestructura operativa. La URL C2 y la clave API se descifran al inicio usando descifrado XOR con una clave codificada en formato rígido.

  • URL de C2: campanha1-api.ef971a42.workers[.]dev (aplicación Cloudflare Workers)
  • Clave API / Token portador: 0d21613a-2609-45fc-83ff-d0feaa0c891f

El C2 sirve a un único objeto de configuración de campaña con superconjunto a través del extremo https://campanha1-api.ef971a42.workers[.]dev/api/campaign . Cada variante de agente deserializa el objeto completo pero solo lee los campos relevantes para su canal.

Configuración capturada:

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

La misma cuenta de Cloudflare ef971a42 también aloja el CDN de entrega de la carga útil (dominio para fileUrl en el objeto de configuración) en documents.ef971a42.workers[.]dev. Accesible a través del punto final /file , actualmente sirve a un archivo zip que contiene el LogiAI Prompt Builder MSI TCLBANKER-trojanizado. Esta decisión de infraestructura permite al operador redistribuir rápidamente la infraestructura sin mantener servidores dedicados.

En el momento de escribir esto, el dominio de phishing arquivos-omie[.]com identificado en la configuración anterior, creada el 15-04-2026, no está en un estado operativo (¡Bienvenidos! Este portal está actualmente en mantenimiento programado. Por favor, inténtalo de nuevo más tarde.) La campaña podría estar en sus primeras fases operativas o preparada para misiones. Este dominio también lleva el nombre de una popular suite brasileña de planeación de recursos empresariales (ERP).

Agente 1: Bot de WhatsApp

El agente de WhatsApp toma silenciosamente el control de la sesión sitio web autenticado de WhatsApp de la víctima para enviar mensajes spam y distribuir TCLBANKER a contactos brasileños.

Secuestro de Sesión

El malware comienza descubriendo navegadores basados en Chromium en el sistema objetivo, y luego escanea tanto las entradas del registro App Paths como los directorios de instalación comunes de Chrome, Edge, Brave, Opera y Vivaldi. Luego recorre los perfiles de usuario de cada navegador (por ejemplo, "Predeterminado", "Perfil 1", etc.), buscando pruebas de una sesión sitio web activo de WhatsApp. Un perfil se marca como con una sesión autenticada si su almacenamiento en IndexedDB contiene el directorio Sitio web LevelDB de WhatsApp en <profile_dir>/IndexedDB/https_web.whatsapp[.]com_0.indexeddb.leveldb/.

Después, cada perfil se envía a la función de clonación de perfiles y secuestro de sesión.

Para cada perfil que cumple los requisitos, el malware lo clona en un directorio temporal en %TEMP%\<GUID>\, copiando solo los archivos necesarios para reanudar la sesión sitio web de WhatsApp: IndexedDB, Local Storage, Session Storage, databases, Web Data, Login Datay Cookies. Luego lanza una instancia de Chromium sin interfaz a través de Selenium WebDriver, con --user-data-dir apuntando al perfil clonado.

La chromedriver.exe coincidente se resuelve en tiempo de ejecución mediante un binario disfrazado de Selenium Manager que se lanza en %TEMP%\msvc-rt14\bin\hostfxr.exe, que se invoca con --browser chrome --output json y devuelve la ruta de un Chromedriver compatible con la versión instalada de Chrome de la víctima.

Inmediatamente luego del lanzamiento, el malware inyecta JavaScript para eludir los frameworks de detección de bots ocultando navigator.webdriver, se llena chrome.runtime, reconcilia la discreción de estado Notification.permission / permissions.query , falsifica un array de navigator.plugins no vacío y configura navigator.languages para que ['pt-BR', 'pt', 'en-US', 'en'] coincida con el público objetivo.

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: {}

};

Con el perfil clonado cargado, el navegador navega hasta web.whatsapp[.]com, y el malware espera hasta 45 segundos para observar el estado resultante de la página. Si aparece la interfaz de chat (el IndexedDB clonado era válido y la sesión se reanudó sin escaneo QR), inyecta una biblioteca WA-JS (WPPConnect) embebida y espera a que WPP.contact.list y WPP.chat.sendTextMessage sean llamables antes de iniciar el bucle de despacho de campaña. Si en su lugar aparece el aviso del código QR, el motor devuelve "qr_code" sin intentar la inyección y luego prueba el siguiente perfil candidato.

Funcionalidad de spam

Una vez que la inyección tiene éxito, el malware recupera la campaña activa del punto final C2 https://campanha1-api.ef971a42.workers[.]dev/api/campaign, que proporciona el cuerpo del mensaje, la URL opcional del archivo adjunto, el subtítulo y los parámetros de tiempo. TCLBANKER se descarga entonces desde el servidor de archivos en https://documents.ef971a42.workers[.]dev/file y se reconstruye en el contexto del navegador como un objeto Archivo, sin ser dejado caer en el disco.

El malware llama entonces a WPP.contact.list para recopilar la agenda de la víctima, filtra grupos, emisiones y números no brasileños, y comienza a enviar mensajes a través de WPP.chat.sendTextMessage y sendFileMessage. El malware informa del progreso al /api/progress final C2 tras cada lote y /api/control busca comandos de pausa remota o reenvío del operador.

Agente 2: Bot de correo de Outlook

El agente de Outlook es un bot de email que abusa de la aplicación Microsoft Outlook instalada por la víctima para enviar correos de phishing desde la dirección de email de la víctima, lo que hace que sea más difícil detectarlos como spam que los correos enviados desde infraestructuras controladas por los atacantes.

Descubrimiento de Outlook y Adjunto COM

Si OUTLOOK.EXE no está ya ejecutar, intenta localizar la instalación en App Paths entradas del registro y directorios conocidos y la lanza en un nuevo proceso. El malware se conecta entonces al proceso mediante interoperación COM: Marshal.GetActiveObject("Outlook.Application"), y valida que tiene al menos una cuenta de correo configurada.

Cosecha de contactos

El malware luego lanza un script PowerShell, %TEMP%\oc<guid>.ps1, que recolecta contactos a través de Outlook COM desde un proceso separado. Recoge contactos de dos fuentes: primero, lee la carpeta predeterminada de Contactos para todas las entradas de contacto, extrayendo direcciones de email y nombres completos de cada elemento de contacto. Segundo, itera las carpetas raíz de cada tienda para encontrar carpetas tipo bandeja de entrada, ordena los mensajes por última y extrae direcciones de correo y nombres de los remitentes antes de escribirlos en un archivo .txt en email|name formato.

Para cada correo del candidato, se realiza un filtrado adicional para maximizar la entregabilidad.

Funcionalidad de spam

Similar al bot de WhatsApp, el malware recupera la campaña activa de https://campanha1-api.ef971a42.workers[.]dev/api/campaign, y luego envía emails a través de las propias cuentas de Outlook de la víctima mediante automatización COM. Cada correo se construye mediante outlookApp.CreateItem(0) (MailItem) con el destinatario en To, el asunto de la campaña y el contenido de la campaña emailMessage, enviado usando la cuenta real de la víctima a través de SendUsingAccount.

Entre envíos, el agente aplica un retardo aleatorio y revisa periódicamente el /api/control final de control C2 para comandos de pausa o reenvío, informando del progreso a /api/progress.

Infraestructura

Los actores REF3076 aprovecharon la infraestructura serverless de worker[.]dev Cloudflare para C2 y alojamiento de archivos. Esta decisión les permite heredar cualquier fideicomiso que las víctimas ya puedan tener en Cloudflare y rotar la infraestructura rápidamente según sea necesario.

Pivotando sobre el hash de cuerpo (91fafaa1240676afe5c55d931261e3798797c408) del sitio de phishing anterior (arquivos-omie[.]com), pudimos identificar dominios adicionales que probablemente se estén preparando para su uso como arma:

DominioFirst SeenInformaciónASN (Providor)
Arquivos-omie[.]com2026-04-17Ocupaciones - SaaS brasileño para pymesAS 13335 (Cloudflare)
documentos-online[.]com2026-04-11GenericAS 13335 (Cloudflare)
Afonsoferragista[.]com2026-04-22Ferretería - Probablemente usada en un señuelo B2BAS 13335 (Cloudflare)
doccompartilhe[.]com2026-04-15Genérico - "Compartido un documento"AS 13335 (Cloudflare)
recebamais[.]com2026-04-20Ocupación ilegal - Correduría brasileña de crédito/préstamosAS 13335 (Cloudflare)

Se descubrió más infraestructura de phishing brasileña tras un giro más amplio en el título del banner (Portal Corporativo), pero no está claro si estaba directamente relacionada con REF3076 o con otros actores del ecosistema troyano bancario latinoamericano. Cabe destacar que un clúster aprovechó el producto gratis de alojamiento estático de Cloudflare pages[.]dev .

El dominio C2 mxtestacionamentos[.]com apuntaba previamente a una IP alojada en Brasil 191.96.224[.]96.

El año pasado, esta IP alojaba simultáneamente un dominio REF3076 C2, un dominio REF3076 phishing y un dominio previamente asociado con la campaña Water Saci y el malware SORVEPOTEL/MAVERICK de TrendMicro (saogeraldoshiping[.]com).

Conclusión

TCLBANKER refleja una maduración más amplia que se está produciendo en todo el ecosistema de troyanos bancarios brasileños. Técnicas que antes eran la seña de identidad de actores de amenazas más sofisticados: descifrado de cargas útiles controladas por el entorno, generación directa de llamadas sys, orquestación de ingeniería social en tiempo real sobre WebSocket, ahora se están empaquetando en el software criminal de mercancía. La barrera de entrada sigue bajando, especialmente cuando los LLM poderosos están fácilmente disponibles para la generación de código.

La inclusión de módulos de gusano autopropagantes marca un cambio notable en este ámbito. La campaña hereda la confianza y la capacidad de entrega de comunicaciones legítimas al secuestrar las sesiones de WhatsApp y las cuentas de Outlook de las víctimas. Este es un modelo de distribución que las pasarelas de email tradicionales y las defensas basadas en reputación no están preparadas para detectar. A medida que los troyanos bancarios latinoamericanos continúan adoptando estos mecanismos de autodifusión, las organizaciones deberían esperar que el volumen y alcance de estas campañas escalen en consecuencia.

Artefactos de desarrolladores a lo largo de la cadena, incluyendo rutas de registro de depuración, nombres de procesos de prueba y un sitio de phishing aún en construcción, sugieren que REF3076 está en sus primeras fases operativas. Esta campaña sigue en desarrollo, no está en proceso de finalización.

REF3076 a través de MITRE ATT&CK

Elastic usa el marco MITRE ATT&CK para documentar tácticas, técnicas y procedimientos comunes que las amenazas emplean contra las redes empresariales.

Táctica

La táctica representa el porqué de una técnica o subtécnica. Es el objetivo táctico del adversario: la razón para realizar una acción.

Técnicas

Las técnicas representan cómo un adversario logra un objetivo táctico mediante la realización de una acción.

Remediación REF3076

Prevención

YARA

Elastic Security creó reglas YARA para identificar esta actividad.

Observaciones

En esta investigación se discutieron los siguientes observables.

ObservableTipoNombreReferencia
701d51b7be8b034c860bf97847bd59a87dca8481c4625328813746964995b626SHA-256screen_retriever_plugin.dllComponente del cargador TCLBanker
8a174aa70a4396547045aef6c69eb0259bae1706880f4375af71085eeb537059SHA-256screen_retriever_plugin.dllComponente del cargador TCLBanker
668f932433a24bbae89d60b24ee4a24808fc741f62c5a3043bb7c9152342f40SHA-256screen_retriever_plugin.dllComponente del cargador TCLBanker
63beb7372098c03baab77e0dfc8e5dca5e0a7420f382708a4df79bed2d900394SHA-256XXL_21042026-181516.zipArchivo ZIP inicial TCLBanker
campanha1-api.ef971a42[.]workers.devnombre-de-dominioTCLBanker C2
mxtestacionamentos[.]comnombre-de-dominioTCLBanker C2
documents.ef971a42.workers[.]devnombre-de-dominioServidor de archivos TCLBanker
Arquivos-omie[.]comnombre-de-dominioPágina de phishing TCLBanker (en desarrollo)
documentos-online[.]comnombre-de-dominioPágina de phishing TCLBanker (en desarrollo)
Afonsoferragista[.]comnombre-de-dominioPágina de phishing TCLBanker (en desarrollo)
doccompartilhe[.]comnombre-de-dominioPágina de phishing TCLBanker (en desarrollo)
recebamais[.]comnombre-de-dominioPágina de phishing TCLBanker (en desarrollo)