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.exetclloader.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.exeregsvr32.exedllhost.exesvchost.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:
NtQueryInformationProcessNtSetInformationThreadNtSetInformationProcessNtTerminateProcessNtAllocateVirtualMemoryNtProtectVirtualMemory
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()usarProcessDebugPort - Usos
NtQueryInformationProcess()usarProcessDebugObjectHandle - Detección de puntos de interrupción por hardware mediante los registros de depuración (
DR0-DR3) - Mide el tiempo transcurrido usando
QueryPerformanceCounter()deltas yRDTSCrecuentos 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
| Hipervisor | Firma del proveedor |
|---|---|
| VMware | VMwareVMware |
| VirtualBox | VBoxVBoxVBox |
| KVM | KVMKVMKVM |
| Xen | XenVMMXenVMM |
| Parallels | PRL Hyperv |
| QEMU/TCG | TCGTCGTCGTCG |
- Verifica que el disco del sistema raíz (
C:\\) conGetDiskFreeSpaceExW()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
fridaolinjector - 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
CRC32comprobación de integridad en la sección.textpara 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ébalo | Implementación |
|---|---|
| Código de región | nuevo RegionInfo (CultureInfo.CurrentCulture.LCID). TwoLetterISORegion Name == "BR" |
| Zona horaria | TimeZoneInfo.Local.BaseUtcOffset.TotalHours: si >= -5.0, comprueba si == -2.0 |
| LCID | CultureInfo.CurrentCulture.LCID == 1046 (portugués-brasileño) |
| Teclado | GetKeyboardLayoutList() - 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ón | Objetivo |
|---|---|
| 2 | Registro ACK, iniciar el asesino del Administrador de tareas |
| 4 | Desconexión WebSocket elegante |
| 5 | Suicidio: Matar todos los procesos hermanos y salir |
| 6 | Resetear forzado (shutdown.exe /r /t 0 /f) |
| 7 | Suicide-then-Uninstall: eliminar todos los procesos con el mismo nombre binario del host excepto él mismo (hermanos) → desinstalar → salir |
| 16 | Captura de pantalla |
| 17 | Empieza a hacer streaming por la pantalla |
| 18 | Deja de transmitir la pantalla |
| 19 | Configurar la calidad de la captura de pantalla (1-100) |
| 20 | Enumerar monitores |
| 32 | Movimiento del mouse (X, Y, MonitorIndex) |
| 33 | Clic 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). |
| 34 | Desplazamiento del mouse (Delta, SendInput) |
| 35 | Tecla (KeyCode, SendInput) |
| 37 | Tecla abajo (KeyCode, SendInput) |
| 38 | Teclado hacia arriba (Código de tecla, SendInput) |
| 39 | Iniciar el keylogger (WH_KEYBOARD_LL hook) |
| 40 | Keylogger de flush, exfiltración a C2 |
| 41 | Secuestro de portapapeles (Clipboard.SetText) |
| 48 | Listado de directorios del sistema de archivos |
| 65 | Obtener información sobre procesos en ejecución |
| 67 | Ejecución de comandos en shell (cmd.exe /c) |
| 80 | Enumerar todas las ventanas visibles |
| 81 | Gestor 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 |
| 83 | Mostrar superposición de estancamiento: ya sea pasos de progreso o una pantalla falsa de actualización de Windows |
| 84 | Superposición de desmontaje |
| 85 | Alterna 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. |
| 86 | Actualizar contenido de superposición |
| 87 | Mostrar superposición de recorte: fijar la ventana exterior dentro de la superposición con recorte de región visible |
| 96 | Mostrar 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:
| Dominio | First Seen | Información | ASN (Providor) |
|---|---|---|---|
| Arquivos-omie[.]com | 2026-04-17 | Ocupaciones - SaaS brasileño para pymes | AS 13335 (Cloudflare) |
| documentos-online[.]com | 2026-04-11 | Generic | AS 13335 (Cloudflare) |
| Afonsoferragista[.]com | 2026-04-22 | Ferretería - Probablemente usada en un señuelo B2B | AS 13335 (Cloudflare) |
| doccompartilhe[.]com | 2026-04-15 | Genérico - "Compartido un documento" | AS 13335 (Cloudflare) |
| recebamais[.]com | 2026-04-20 | Ocupación ilegal - Correduría brasileña de crédito/préstamos | AS 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.
- Acceso inicial
- Ejecución
- Persistencia
- Evasión de defensa
- Acceso a credenciales
- Descubrimiento
- Colección
- Comando y control
- Exfiltración
- Impacto
Técnicas
Las técnicas representan cómo un adversario logra un objetivo táctico mediante la realización de una acción.
- Phishing: Spearphishing Attachment
- Ejecución de Proxy Binario del Sistema: msiexec
- Flujo de ejecución de secuestro: carga lateral de DLL
- Intérprete de comandos y scripting: PowerShell
- Intérprete de comandos y scripting: Shell de comandos de Windows
- Tarea/Trabajo programado: Tarea programada
- Deobfuscate/Decode Files or Information
- Información o archivos ofuscados
- Evasión de depuradores
- Evasión de virtualización/sandbox: comprobaciones del sistema
- Evasión de virtualización/sandbox: evasión basada en el tiempo
- Debilitar defensas: deshabilitar o modificar herramientas
- Native API
- Inyección de proceso
- Descubrimiento de procesos
- Detección de ventanas de aplicaciones
- Detección de información del sistema
- System Location Discovery: System Language Discovery
- Captura de pantalla
- Captura de entrada: registro de teclas
- Datos del portapapeles
- Captura de entrada: Captura de portal sitio web
- Secuestro de sesiones de navegador
- Protocolo de Capa de Aplicación: Protocolos Sitio web
- Servicio sitio web
- Transferencia de herramientas de ingreso
- Recogida de emails: Recogida local de emails
- Apagado/Resetear del sistema
Remediación REF3076
Prevención
- Cambio de protección de memoria NTDLL mediante DLL sin signo
- La biblioteca NTDLL se cargó por segunda vez
- Posible desconexión de memoria NTDLL
- Parallel NTDLL Loaded from Unbacked Memory
- Cambio sospechoso en el módulo central de Windows
- Bypass de AMSI mediante memoria sin respaldo
- Posible desviación AMSI mediante SetThreadContext
YARA
Elastic Security creó reglas YARA para identificar esta actividad.
Observaciones
En esta investigación se discutieron los siguientes observables.
| Observable | Tipo | Nombre | Referencia |
|---|---|---|---|
| 701d51b7be8b034c860bf97847bd59a87dca8481c4625328813746964995b626 | SHA-256 | screen_retriever_plugin.dll | Componente del cargador TCLBanker |
| 8a174aa70a4396547045aef6c69eb0259bae1706880f4375af71085eeb537059 | SHA-256 | screen_retriever_plugin.dll | Componente del cargador TCLBanker |
| 668f932433a24bbae89d60b24ee4a24808fc741f62c5a3043bb7c9152342f40 | SHA-256 | screen_retriever_plugin.dll | Componente del cargador TCLBanker |
| 63beb7372098c03baab77e0dfc8e5dca5e0a7420f382708a4df79bed2d900394 | SHA-256 | XXL_21042026-181516.zip | Archivo ZIP inicial TCLBanker |
| campanha1-api.ef971a42[.]workers.dev | nombre-de-dominio | TCLBanker C2 | |
| mxtestacionamentos[.]com | nombre-de-dominio | TCLBanker C2 | |
| documents.ef971a42.workers[.]dev | nombre-de-dominio | Servidor de archivos TCLBanker | |
| Arquivos-omie[.]com | nombre-de-dominio | Página de phishing TCLBanker (en desarrollo) | |
| documentos-online[.]com | nombre-de-dominio | Página de phishing TCLBanker (en desarrollo) | |
| Afonsoferragista[.]com | nombre-de-dominio | Página de phishing TCLBanker (en desarrollo) | |
| doccompartilhe[.]com | nombre-de-dominio | Página de phishing TCLBanker (en desarrollo) | |
| recebamais[.]com | nombre-de-dominio | Página de phishing TCLBanker (en desarrollo) |