A Elastic Security Labs identificou um novo trojan bancário brasileiro que estamos monitorando como TCLBANKER, uma família de malware que avaliamos como uma grande atualização da família MAVERICK/SORVEPOTEL . A campanha, rastreada como REF3076, apresenta um carregador com recursos robustos de anti-análise que implanta dois módulos incorporados protegidos pelo .NET Reactor: um trojan bancário completo e um módulo de worm para autopropagação.
O trojan bancário monitora a barra de endereço do navegador da vítima por meio da Automação de IU, visando domínios 59 brasileiros de bancos, fintechs e criptomoedas. Além dos comandos usuais de acesso remoto, sua capacidade mais notável é uma estrutura de sobreposição em tela cheia baseada em WPF, projetada para engenharia social conduzida pelo operador.
Um segundo módulo lida com a distribuição por meio de agentes de spam, dos quais recuperamos duas variantes: um worm do WhatsApp que sequestra sessões de navegador autenticadas para enviar mensagens aos contatos da vítima e um bot de e-mail do Outlook que envia e-mails de phishing por meio das próprias contas da vítima via automação COM.
Por meio deste relatório, fornecemos uma descrição técnica detalhada de cada etapa.
Principais conclusões
- O TCLBANKER utiliza descriptografia de payload com controle de ambiente; ambientes incorretos, como sandboxes, falham silenciosamente na descriptografia do payload.
- Um subsistema de vigilância abrangente monitora continuamente ferramentas de análise, depuradores, estruturas de instrumentação e violações de integridade durante toda a execução.
- O trojan bancário tem como alvo domínios 59 de bancos, fintechs e criptomoedas, ativando uma sessão C2 via WebSocket quando a vítima acessa um site monitorado.
- Uma estrutura de sobreposição em tela cheia baseada em WPF permite engenharia social conduzida pelo operador, incluindo coleta de credenciais, telas de espera simuladas por meio de vishing e travamentos falsos do Windows Update, enquanto oculta as sobreposições de ferramentas de captura de tela.
- Os módulos do worm propagam o malware: um bot do WhatsApp e um bot de e-mail do Outlook.
- Toda a infraestrutura de C2 e distribuição está hospedada no Cloudflare Workers sob uma única conta, com artefatos de desenvolvimento (caminhos de logs de depuração, nomes de processos de teste) e uma página de phishing incompleta, sugerindo que a campanha foi identificada em um estágio operacional inicial.
Entrega
TCLBANKER é um trojan bancário brasileiro que contém uma cadeia de infecção dinâmica com um componente de carregamento anti-análise robusto, capaz de implantar duas cargas úteis embutidas (worm e banker). A cadeia de infecção observada inclui um instalador MSI malicioso dentro de um arquivo ZIP. Esses pacotes de instalação MSI estão fazendo uso indevido de um programa assinado da Logitech chamado Logi AI Prompt Builder.
TCLBANKER abusa do sideloading de DLL contra LogiAiPromptBuilder.exe, um aplicativo legítimo da Logitech construído na estrutura Flutter . A DLL maliciosa screen_retriever_plugin.dll se disfarça de um plugin Flutter legítimo de mesmo nome e é carregada automaticamente quando o aplicativo host é iniciado.
Após a instalação do MSI, a DLL maliciosa é carregada imediatamente e inicia no ponto de entrada DllMain.
Carregador
O componente carregador do TCLBANKER vem repleto de recursos, incluindo funcionalidades anti-depuração, verificações anti-análise, criptografia de strings, verificação do idioma do sistema, aplicação de patches ETW e um recurso de monitoramento (watchdog). Embora possua muitos recursos, carece de profundidade e faz referência a ferramentas de análise de malware mais antigas. Não está totalmente claro se o desenvolvedor utilizou fluxos de trabalho assistidos por LLM, mas nossa equipe não se surpreenderia se esse fosse o caso.
No início da execução, o TCLBANKER alinha os payloads de assembly .NET correspondentes com base em se a string (--renderer=sw) é usada na linha de comando. Em sua função principal de carregamento, ele primeiro executa operações de lista de permissões/lista de bloqueios com base em como a DLL foi carregada. A DLL maliciosa só será executada se o processo hospedeiro vier de um dos dois processos a seguir:
logiaipromptbuilder.exetclloader.exe(Possível referência à string do desenvolvedor durante os testes)
Se a DLL tiver sido carregada pelos seguintes processos, ela se recusará a ser executada. Esses processos são tradicionalmente usados por analistas para carregar e depurar DLLs.
rundll32.exeregsvr32.exedllhost.exesvchost.exe
Em seguida, o TCLBBANKER remove qualquer interceptação em modo de usuário, substituindo ntdll.dll do disco. Para maior evasão, o malware gera os seguintes trampolins de chamadas de sistema, que serão usados posteriormente:
NtQueryInformationProcessNtSetInformationThreadNtSetInformationProcessNtTerminateProcessNtAllocateVirtualMemoryNtProtectVirtualMemory
Após instalar stubs de chamadas de sistema, o malware aplica patches em EtwEventWrite em ntdll.dll com o clássico xor eax, eax; ret para desativar a telemetria ETW do modo de usuário.
TCLBANKER realiza uma verificação inicial de sandbox capturando um tick de início usando GetTickCount64(), aguardando por 500 ms e medindo o tempo decorrido. Se menos de 450 ms tiverem decorrido, o malware é interrompido — isto deteta sandboxes ou estruturas de emulação que interceptam o Sleep para retornar imediatamente.
Uma das funcionalidades mais interessantes do TCLBANKER é uma função de enumeração que gera três impressões digitais com base nos seguintes critérios:
- Verificações anti-depuração
- Informações do disco do sistema e verificações de memória
- Verificações de idioma
O desenvolvedor usa constantes mágicas atribuídas a caminhos "limpos" para cada categoria e, em seguida, realiza um XOR em cada uma delas para gerar o hash do ambiente. Esse valor de hash do ambiente é importante porque afeta a descriptografia subsequente da carga útil incorporada.
Por exemplo, se um depurador estiver presente, ele produzirá um hash incorreto; portanto, quando o malware tentar derivar as chaves de descriptografia a partir do hash, a carga útil não será descriptografada corretamente e o TCLBANKER interromperá a execução.
Verificações anti-depuração
O TCLBANKER implementa seis verificações anti-depuração diferentes:
- Identifique o depurador através do sinalizador
Peb->BeingDebugged - Verifica os sinalizadores heap-tail/heap-free/check-heap definidos quando um processo é iniciado em um depurador.
- Alavanca
NtQueryInformationProcess()usandoProcessDebugPort - Usa
NtQueryInformationProcess()usandoProcessDebugObjectHandle - Detecção de ponto de interrupção de hardware através dos registradores de depuração (
DR0-DR3) - Mede o tempo decorrido usando deltas
QueryPerformanceCounter()e contagens de cicloRDTSC
Verificações de informações do sistema
O TCLBANKER realiza as seguintes cinco verificações diferentes com base em informações de virtualização, sistema e usuário:
- Verifica a presença de software de virtualização usando a assinatura do fornecedor.
| Hipervisor | Assinatura do fornecedor |
|---|---|
| VMware | VMware |
| VirtualBox | Caixa de seleção Caixa de seleção Caixa de seleção |
| KVM | KVMKVMKVM |
| Xen | XenVMMXenVMM |
| Parallels | prl hiperv |
| QEMU/TCG | TCGTCGTCGTCG |
- Verifique se a unidade raiz do sistema (
C:\\) através deGetDiskFreeSpaceExW()possui pelo menos 64 GB - Chama
GlobalMemoryStatusEx()para verificar se o sistema possui mais de 2 GB de RAM. - Verifica processadores 2 ou CPU via
GetSystemInfo() - Verifica nomes de usuário genéricos de sandbox/malware
sandbox,malware,virus,sample,john doe,currentuser
Verificações de idioma
Para a última verificação de impressão digital do ambiente, o TCLBANKER recupera informações geográficas da máquina infectada usando GetUserGeoID(), visando usuários brasileiros com base no ID geográfico (0x20). Uma segunda verificação de localidade via GetUserDefaultLCID() também garante que o idioma padrão do usuário seja o português brasileiro (pt-BR, LANGID 0x0416).
Após esses conjuntos de verificações, o TCLBANKER interromperá a execução se algo for detectado ou, caso contrário, produzirá outra verificação anti-depuração corrigindo DbgUiRemoteBreakin(). O malware modifica seu primeiro byte para a instrução a ret de modo que qualquer tentativa de invadir remotamente o processo seja inútil — a thread injetada retorna imediatamente e o alvo continua em execução, sem ser suspenso.
Depois disso, o malware deriva uma chave AES-256 CBC e IV usando constantes codificadas da seção .rdata juntamente com o hash ambiental calculado anteriormente. O TCLBanker usa BCryptDecrypt() para descriptografar a carga útil incorporada e, em seguida, descompacta via RtlDecompressBuffer usando o algoritmo de compressão LZNT1.
Assim que a carga útil correspondente for descriptografada, o TCLBANKER inicializa o COM via CoInitializeEx() e usa as APIs de hospedagem CLR para carregar o runtime .NET no processo. Antes de iniciar o ponto de entrada da carga útil, o TCLBanker cria duas novas threads: uma serve como watchdog e a outra monitora a thread do watchdog como uma verificação de pulsação.
Cão de guarda
O TCLBANKER possui um recurso abrangente de monitoramento que visa diversas ferramentas de análise, incluindo desassembladores, depuradores, produtos de instrumentação, antivírus e sandboxes. Esta seção descreverá as diversas técnicas utilizadas por este recurso:
- Verificação do depurador via
PEB→BeingDebugged - Observações para pontos de interrupção de hardware
DR0/DR1/DR2/DR3 - Verifica funções do Windows (
BCryptDecrypt(),BCryptOpenAlgorithmProvider()) em busca de ganchos embutidos, examinando os primeiros 12 bytes de cada função. - Monitores para ferramentas de instrumentação e strings relacionadas (
frida,cydia,user-path injection,hook framework) - Analisa todos os pipes nomeados do kernel que procuram por
fridaoulinjector - Executa a enumeração de processos via
CreateToolhelp32Snapshot()visando os seguintes nomes de processo:frida,de4dot,dnspy,megadumper,extremedumper,processhacker,x64dbg,x32dbg,pe-sieve,scylla,Ilspy,dotpeek,netreactorslayer,cheatengine
- Utiliza a detecção de títulos do Windows via
GetWindowTextW()com estes títulos:x64dbg,x32dbg,ida -,ida pro,ghidra,dnspy,megadumper,extremedumper,processhacker,ollydbg,windbg)_,pe_sieve,scylla
- Identifica as ferramentas de análise com base nos seguintes nomes de classe de janela via
FindWindowW():IDATopLevelWindow,idaabortwndclass,TIdaWindow,x64dbg,x32dbg,OLLYDBG,WinDbgFrameClass,ProcessHacker,SystemInformer,CheatEngine,HxdClass
- Verifica os seguintes módulos carregados
dbeng.dll,dbgcore.dll,SbieDll.dll,snxhk.dll,cmdvrt32.dll,cmdvrt64.dll,cuckoomon.dll,pstorec.dll,vmcheck.dll,wpespy.dll
- Tem como alvo os seguintes mutexes e eventos:
Ida_trusted_idbs,IDA_COMM_PIPE_,Local\\x64dbg,Local\\x32dbg,Frida,YOURAPPNAMEHERE
- Executa uma verificação de integridade
CRC32na seção.textpara evitar qualquer adulteração.
Módulo Trojan Bancário
Tcl.Agent É um cavalo de Troia bancário, o principal componente da cadeia. É protegido pelo .NET Reactor e, embora não tenhamos conseguido desofuscá-lo usando ferramentas de código aberto disponíveis, como de4dot e NETReactorSlayer, conseguimos desofuscar estaticamente este estágio até um estado satisfatório usando um pipeline de desofuscação personalizado para lidar com a criptografia de strings do .NET Reactor, o achatamento do fluxo de controle, a mutação de IL, os proxies de delegados e os corpos de métodos criptografados (Necrobit). Embora seja um malware novo, grande parte da estrutura do código ainda segue o modelo de implementação de trojan bancário da ESET para a América Latina, publicado em 2020.
Ao iniciar, o malware realiza geofencing, exigindo que pelo menos 2 dos seguintes indicadores correspondam ao Brasil; caso contrário, ele é encerrado imediatamente se não estiver em uma máquina brasileira:
| Verificar | Implementação |
|---|---|
| Código da região | novo RegionInfo(CultureInfo.CurrentCulture.LCID).TwoLetterISORegionName == "BR" |
| Fuso horário | TimeZoneInfo.Local.BaseUtcOffset.TotalHours: se >= -5.0, verifique se == -2.0 |
| LCID | CultureInfo.CurrentCulture.LCID == 1046 (Português-Brasil) |
| Teclado | GetKeyboardLayoutList() - verifica cada layout: (ToInt32() & 0xFFFF) == 1046 |
Instalação e Persistência
Na primeira execução, o malware copia todo o diretório do aplicativo para %LocalAppData%\LogiAI. Ele calcula um hash SHA-256 sobre todos os arquivos .dll e .exe no diretório de origem e o grava em um arquivo marcador .version . Em execuções subsequentes, ele compara os hashes para evitar cópias redundantes. Após a cópia, ele inicia a nova instância a partir do caminho de instalação e encerra.
Ele cria uma tarefa agendada chamada RuntimeOptimizeService usando interoperabilidade COM com o Agendador de Tarefas (CLSID 0F87369F-A4E5-4CFC-BD3E-73E6154572DD). A tarefa está configurada como oculta, habilitada, sem limite de tempo de execução, permitida na bateria, iniciar quando disponível e disparada em um gatilho de logon (type 9) com escopo para o usuário atual. Ele se registra com TASK_CREATE_OR_UPDATE e TASK_LOGON_SERVICE_ACCOUNT.
Após a persistência ser estabelecida, o agente envia um beacon POST de primeira execução para https://campanha1-api.ef971a42.workers[.]dev/api/installs com o agentId (MachineName-UserName), MachineName, UserName (redundante) e a versão do SO. A solicitação é autenticada com um token de autenticação de campanha embutido 0d21613a-2609-45fc-83ff-d0feaa0c891f. A variante mais recente adiciona registro de depuração em torno desta chamada (C:\temp\tcl-debug.txt), um artefato de desenvolvedor que inadvertidamente expõe a presença do agente no disco.
Autoatualização
O agente implementa um mecanismo de atualização automática baseado em hash que é executado no início do processo de inicialização. Ele lê um hash de versão local de flutter_engine.cfg em seu diretório de instalação (migrando de um nome de arquivo legado version.hash se presente), então busca o hash atual do endpoint do servidor de arquivos documents.ef971a42.workers[.]dev/api/version usando uma string User-Agent truncada (Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36.
A resposta é analisada em busca da chave "hash". Se o hash remoto corresponder ao hash local, a execução continua normalmente. Na primeira instalação, o hash remoto é gravado no disco e a execução prossegue sem atualização.
Quando uma incompatibilidade de hash é detectada, o agente baixa a carga útil de atualização de documents.ef971a42.workers[.]dev/api/update como um MSI para %TEMP%\update_{8hexchars}.msi, autenticado com o token Bearer b7ba9e80-0d04-4d9e-b217-c8b3cce335a2.
O download é validado com base em um tamanho mínimo de 100 KB como medida de segurança. O agente então escreve um script em lote autoexcluído para %TEMP% que verifica a lista de tarefas até que o processo atual seja encerrado, executa msiexec /i /qn REINSTALLMODE=amus para instalação silenciosa e se exclui. O arquivo em lote é executado por meio de um processo oculto cmd.exe antes que o agente termine, passando a execução para a carga útil atualizada.
Monitoramento de URL do navegador e inicialização da sessão C2
A cada segundo, o agente malicioso chama uma função de monitoramento de URL do navegador que lê a barra de endereços do navegador em primeiro plano por meio da Automação da Interface do Usuário. Ele chama GetForegroundWindow, resolve o processo proprietário, verifica o nome do processo em relação ao Chrome, Firefox, Microsoft Edge, Brave, Opera e Vivaldi e, em seguida, usa AutomationElement.FromHandle -> FindFirst(Descendants, ControlType.Edit) -> ValuePattern.Current.Value para extrair o URL, semelhante a esta implementação do Stack Overflow.
O URL extraído é comparado com uma lista fixa de bancos alvo incorporada no binário, codificada via XOR com uma chave de 16 bytes e codificação base64.
Este GitHub Gist contém uma lista de 59 domínios alvo, incluindo bancos brasileiros, plataformas fintech e corretoras de criptomoedas, agrupados pelos IDs alvo anexados a cada domínio descriptografado.
Quando uma correspondência é encontrada, o ID de destino do domínio é passado para o próximo estado, que inicializa a comunicação oficial C2 estabelecendo uma conexão WebSocket com wss://mxtestacionamentos[.]com/ws. O manipulador OnConnect é acionado, enviando um pacote de registro contendo o ID do agente (um GUID aleatório em tempo de execução), MachineName, UserName, informações da máquina, carimbo de data/hora, ID do domínio alvo (para que o C2 saiba qual site a vítima abriu) e uma assinatura.
Para produzir uma assinatura de handshake, o HMAC-SHA256 é usado para assinar o identificador da vítima (ID do agente, nome da máquina, nome do usuário, versão do SO, carimbo de data/hora) usando o GUID da campanha 70e4f943-e323-4484-97d7-35401bf6812c como chave.
Em seguida, o servidor responde com uma confirmação de registro, iniciando oficialmente a sessão, e entra no loop de despacho de comandos. Ao iniciar uma sessão, um processo que encerra o Gerenciador de Tarefas é executado a cada 500 ms para impedir que a vítima inspecione ou encerre o processo do agente.
Tabela de comandos C2
A tabela de opcodes abaixo descreve um resumo das capacidades:
| Código de operação | Objetivo |
|---|---|
| 2 | Confirmação de registro, inicie o processo que encerra o Gerenciador de Tarefas. |
| 4 | Desconexão WebSocket elegante |
| 5 | Suicídio: Mate todos os processos irmãos e saia. |
| 6 | Reinicialização forçada (shutdown.exe /r /t 0 /f) |
| 7 | Suicídio seguido de desinstalação: encerra todos os processos com o mesmo nome binário do host, exceto ele próprio (processos irmãos) → desinstala → sai |
| 16 | Captura de tela |
| 17 | Comece a transmitir a tela |
| 18 | Pare de transmitir a tela |
| 19 | Defina a qualidade da captura de tela (1-100) |
| 20 | Enumere os monitores |
| 32 | Movimento do mouse (X, Y, MonitorIndex) |
| 33 | Clique do mouse através da sobreposição: analisar {X,Y,Button,MonitorIndex} → traduzir para coordenadas absolutas da área de trabalho → encontrar a própria janela de sobreposição do implante que cobre esse ponto → criar um buraco de região 2x2 na sobreposição nesse pixel → SetCursorPos + SendInput clique/solte o mouse (que aterrissa em qualquer conteúdo real da área de trabalho que esteja sob a sobreposição). |
| 34 | Rolagem do mouse (Delta, SendInput) |
| 35 | Toque na tecla (Código da tecla, SendInput) |
| 37 | Tecla pressionada (Código da tecla, SendInput) |
| 38 | Tecla solta (Código da tecla, SendInput) |
| 39 | Iniciar keylogger (gancho WH_KEYBOARD_LL ) |
| 40 | Limpar keylogger, exfiltrar para C2 |
| 41 | Sequestro da área de transferência (Clipboard.SetText) |
| 48 | Listagem de diretórios do sistema de arquivos |
| 65 | Obtenha informações sobre os processos em execução. |
| 67 | Execução de comando Shell (cmd.exe /c) |
| 80 | Enumere todas as janelas visíveis. |
| 81 | Gerenciador de janelas: encerrar o processo de uma janela / minimizar janela / restaurar janela / trazer janela para o primeiro plano / fechar janela / mover janela para outro monitor |
| 83 | Exibir sobreposição de tela de progresso: etapas de progresso ou tela falsa do Windows Update. |
| 84 | sobreposição de desmontagem |
| 85 | Ativar/desativar imunidade à captura de tela. Ativa/desativa WDA_EXCLUDEFROMCAPTURE em todas as janelas de sobreposição para ocultá-las do compartilhamento de tela/capturas de tela. |
| 86 | Atualizar conteúdo da sobreposição |
| 87 | Exibir sobreposição recortada: fixe a janela externa dentro da sobreposição com recorte de região visível. |
| 96 | Exibir sobreposição de solicitação de credenciais |
Estrutura de interface do usuário para engenharia social
Uma funcionalidade ainda mais interessante do trojan bancário é um subsistema de sobreposição em tela cheia baseado em WPF que orquestra fluxos de fraude com temática bancária durante sessões C2 ativas.
Ciclo de vida da sobreposição
O gerenciador de sobreposição cria uma janela WPF em tela cheia por monitor. As janelas são configuradas como sem borda, no topo e ocultas da barra de tarefas (WindowStyle.None, Topmost = true, ShowInTaskbar = false), com um identificador personalizado Closing que impede o fechamento até que um sinalizador interno seja alterado pelo operador por meio do comando de desmontagem da sobreposição, impedindo que as janelas sejam fechadas.
Na inicialização, o gerenciador captura uma captura de tela PNG de cada tela através de CopyFromScreen como plano de fundo da sobreposição, criando uma aparência de "área de trabalho congelada". Dependendo da sobreposição ativa no momento, a vítima percebe seu ambiente de trabalho real por trás dela.
Um temporizador 500ms reaplica continuamente HWND_TOPMOST através de SetWindowPos para impedir qualquer janela que tente aparecer acima da sobreposição.
Além disso, um recurso anti-captura chama SetWindowDisplayAffinity com WDA_EXCLUDEFROMCAPTURE, tornando a sobreposição invisível para quaisquer ferramentas de captura de tela, permitindo que o operador veja através de sua própria sobreposição por meio dos comandos de captura de tela e transmissão de tela.
Bloqueador de entrada
No monitor principal, dois ganchos estão instalados: WH_KEYBOARD_LL e WH_MOUSE_LL. Ambos os ganchos verificam seus respectivos sinalizadores injetados (LLKHF_INJECTED para teclado, LLMHF_INJECTED para mouse), permitindo que a entrada injetada via SendInput pelos comandos remotos do operador passe sem ser alterada. O gancho do teclado bloqueia as teclas Tab, Escape, Alt+F4, Win, PrintScreen, Ctrl, Alt e todas as teclas de navegação; o gancho do mouse bloqueia o clique direito, o clique do meio e a rolagem, mas permite o clique esquerdo e o movimento, para que a vítima ainda possa interagir com os avisos sobrepostos.
Construtores de interface de usuário para engenharia social
Cinco renderizadores de conteúdo intercambiáveis se integram à estrutura de sobreposição:
Solicitação de credenciais: Suporta três modos de entrada, selecionados com base nos parâmetros de solicitação do operador.
- O modo telefone aplica mascaramento de formato brasileiro em tempo real ((##) ####-#### para linhas fixas de 10 dígitos, (##) #####-#### para celulares de 11 dígitos) com no máximo 11 dígitos.
- O modo de teclado virtual exibe um teclado numérico na tela (botões 0 a 9 mais "limpar"/limpar), mostrando a entrada como caracteres de marcador para simular a entrada de um PIN.
- O modo padrão aceita texto simples com um comprimento máximo configurável.
Todos os modos passam a entrada por um validador de qualidade que rejeita algoritmicamente sequências de dígitos iguais (000000) e sequências ascendentes/descendentes (123456, 654321) para impedir que as vítimas insiram valores descartáveis.
A ação de submissão envia os valores capturados para o C2.
Tela de espera do Vishing: Acionada depois que a vítima envia seu número de telefone no campo de credenciais. Exibe "Estamos entrando em contato" ("Estamos entrando em contato") com uma animação de imagem central "respirando" e três pontos com animações de opacidade escalonadas (deslocamento 300ms por ponto) produzindo um visual de "conexão". O operador ou um cúmplice pode então ligar para o número de telefone real da vítima, fingindo ser um funcionário da segurança do banco.
Etapas de progresso: Uma tela de espera totalmente padronizada pelo operador, exibindo uma lista de etapas de processamento fictícias com uma animação aleatória. A duração de cada etapa é aleatorizada para totalizar aproximadamente 15 minutos. Um cronômetro avança sequencialmente por cada etapa, marcando visualmente as etapas concluídas, destacando a etapa atual e escurecendo as restantes. Quando todas as etapas forem concluídas, a sequência é reiniciada para uma posição anterior com novos tempos aleatórios e continua.
Atualização falsa do Windows: Uma tela de travamento alternativa que imita a tela de atualização e reinicialização do Windows 10/11. Renderiza um fundo sólido #0078D7 (azul de destaque do Windows) com um indicador giratório de cinco elipses dispostas em círculo. A leitura percentual apresenta saltos aleatórios de 25 a 35% em intervalos aleatórios de 50 a 81 segundos para simular o comportamento irregular do progresso das atualizações reais do Windows. Legenda padrão: "Trabalhando em atualizacoes".
Sobreposição de recorte: Cria um orifício retangular na sobreposição em tela cheia, expondo a janela do aplicativo subjacente. O operador especifica as dimensões do buraco através do opcode 87, no qual o gerenciador de sobreposição constrói um cartão temático com um espaço reservado de borda transparente, calcula suas coordenadas de tela pós-layout e corta um buraco de região correspondente usando CreateRectRgn + CombineRgn(RGN_DIFF) + SetWindowRgn. A janela alvo é reposicionada embaixo do orifício. O resultado é uma janela de aplicativo real enquadrada dentro da sobreposição, e a vítima interage com o aplicativo real enquanto a sobreposição ao redor fornece um contexto enganoso.
Módulo Worm
O segundo módulo invocado pelo carregador é Tcl.WppBot, projetado para propagar mensagens de spam e phishing em escala, para distribuir TCLBANKER. Dois tipos distintos de agentes foram recuperados de dois carregadores diferentes e analisados:
- Um worm do WhatsApp que sequestra sessões do navegador.
- Um bot de e-mail do Outlook que abusa do Microsoft Outlook através da interoperabilidade COM.
Tcl.WppBot também está protegido pelo .NET Reactor com a mesma versão usada para proteger Tcl.Agent, e assim também conseguimos desofuscar estaticamente os payloads nesta etapa.
Ambos os agentes compartilham o mesmo backend C2, credenciais de autenticação e infraestrutura operacional. O URL do C2 e a chave da API são descriptografados na inicialização usando descriptografia XOR com uma chave codificada.
- URL do C2:
campanha1-api.ef971a42.workers[.]dev(aplicativo Cloudflare Workers) - Chave de API / Token Bearer:
0d21613a-2609-45fc-83ff-d0feaa0c891f
O C2 fornece um único objeto de configuração de campanha superconjunto através do endpoint https://campanha1-api.ef971a42.workers[.]dev/api/campaign . Cada variante de agente desserializa o objeto completo, mas lê apenas os campos relevantes para o seu canal.
Configuração 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
A mesma conta Cloudflare ef971a42 também hospeda o CDN de entrega de payload (domínio para fileUrl no objeto de configuração) em documents.ef971a42.workers[.]dev. Acessível através do endpoint /file , atualmente fornece um arquivo zip contendo o LogiAI Prompt Builder MSI infectado pelo trojan TCLBANKER. Essa decisão de infraestrutura permite que a operadora reimplemente a infraestrutura rapidamente, sem a necessidade de manter servidores dedicados.
Até o momento da redação deste documento, o domínio de phishing arquivos-omie[.]com identificado na configuração acima, criado em 15/04/2026, não está em estado operacional (Bem-vindo! Este portal encontra-se atualmente em manutenção programada. Por favor, tente novamente mais tarde. A campanha pode estar em seus estágios operacionais iniciais ou preparada para ser executada. Este domínio também foi nomeado para imitar um popular pacote brasileiro de Planejamento de Recursos Empresariais (ERP).
Agente 1: Bot do WhatsApp
O agente do WhatsApp assume silenciosamente o controle da sessão autenticada do WhatsApp Web da vítima para enviar mensagens de spam e distribuir o TCLBANKER para contatos brasileiros.
Sequestro de sessão
O malware começa por descobrir navegadores baseados no Chromium no sistema alvo, depois verifica as entradas de registo App Paths e os diretórios de instalação comuns do Chrome, Edge, Brave, Opera e Vivaldi. Em seguida, o sistema percorre os perfis de usuário de cada navegador (por exemplo, "Padrão", "Perfil 1", etc.), procurando evidências de uma sessão ativa do WhatsApp Web. Um perfil é sinalizado como tendo uma sessão autenticada se seu armazenamento IndexedDB contiver o diretório WhatsApp Web LevelDB em <profile_dir>/IndexedDB/https_web.whatsapp[.]com_0.indexeddb.leveldb/.
Em seguida, cada perfil é enviado para a função de clonagem de perfil e sequestro de sessão.
Para cada perfil qualificado, o malware o clona para um diretório temporário em %TEMP%\<GUID>\, copiando apenas os arquivos necessários para retomar a sessão do WhatsApp Web: IndexedDB, Local Storage, Session Storage, databases, Web Data, Login Data e Cookies. Em seguida, inicia uma instância headless do Chromium via Selenium WebDriver, com --user-data-dir apontando para o perfil clonado.
A correspondência chromedriver.exe é resolvida em tempo de execução por um binário Selenium Manager disfarçado colocado em %TEMP%\msvc-rt14\bin\hostfxr.exe, que é invocado com --browser chrome --output json e retorna o caminho de um chromedriver compatível com a versão do Chrome instalada na vítima.
Imediatamente após o lançamento, o malware injeta JavaScript para contornar as estruturas de detecção de bots, ocultando navigator.webdriver, preenchendo chrome.runtime, reconciliando a incompatibilidade de estado Notification.permission / permissions.query , falsificando um array navigator.plugins não vazio e definindo navigator.languages para ['pt-BR', 'pt', 'en-US', 'en'] para corresponder ao público-alvo.
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: {}
};
Com o perfil clonado carregado, o navegador navega para web.whatsapp[.]com e o malware espera até 45 segundos para observar o estado da página resultante. Se a interface de bate-papo aparecer (o IndexedDB clonado era válido e a sessão foi retomada sem uma leitura de QR), ela injeta uma biblioteca WA-JS (WPPConnect) incorporada e espera que WPP.contact.list e WPP.chat.sendTextMessage se tornem chamáveis antes de iniciar o loop de despacho da campanha. Se o prompt do código QR for exibido, o mecanismo retorna "qr_code" sem tentar a injeção e, em seguida, tenta o próximo perfil candidato.
Funcionalidade anti-spam
Uma vez que a injeção seja bem-sucedida, o malware recupera a campanha ativa do endpoint C2 https://campanha1-api.ef971a42.workers[.]dev/api/campaign, que fornece o corpo da mensagem, URL de anexo opcional, legenda e parâmetros de tempo. O TCLBANKER é então baixado do servidor de arquivos em https://documents.ef971a42.workers[.]dev/file e reconstruído no contexto do navegador como um objeto File, sem ser gravado em disco.
O malware então chama WPP.contact.list para coletar a agenda de endereços da vítima, filtra grupos, transmissões e números não brasileiros e começa a enviar mensagens através de WPP.chat.sendTextMessage e sendFileMessage. O malware reporta o progresso ao endpoint C2 /api/progress após cada lote e consulta /api/control para pausa remota ou reenvio de comandos do operador.
Agente 2: Bot de e-mail do Outlook
O agente do Outlook é um robô de spam que se aproveita do aplicativo Microsoft Outlook instalado na vítima para enviar e-mails de phishing a partir do endereço de e-mail da vítima, tornando-os mais difíceis de detectar como spam do que e-mails enviados de infraestrutura controlada pelo atacante.
Descoberta do Outlook e anexo COM
Se OUTLOOK.EXE ainda não estiver em execução, ele tenta localizar a instalação nas entradas de registro de App Paths e nos diretórios de instalação conhecidos e a inicia em um novo processo. O malware então se conecta ao processo via COM interop: Marshal.GetActiveObject("Outlook.Application") e valida se ele tem pelo menos uma conta de e-mail configurada.
Colheita por contato
O malware então instala um script PowerShell, %TEMP%\oc<guid>.ps1, que coleta contatos via Outlook COM de um processo separado. Ele coleta contatos de duas fontes: primeiro, lê a pasta Contatos padrão em busca de todas as entradas de contato, extraindo endereços de e-mail e nomes completos de cada item de contato. Em segundo lugar, ele itera pelas pastas raiz de cada loja para encontrar pastas semelhantes a caixas de entrada, classifica as mensagens da caixa de entrada por mais recentes e extrai os endereços de e-mail e nomes dos remetentes antes de gravá-los em um arquivo .txt no formato email|name .
Para cada e-mail de candidato, é feita uma filtragem adicional para maximizar a entregabilidade.
Funcionalidade anti-spam
Semelhante ao bot do WhatsApp, o malware recupera a campanha ativa de https://campanha1-api.ef971a42.workers[.]dev/api/campaign, e então envia e-mails através das próprias contas do Outlook da vítima via automação COM. Cada e-mail é construído através de outlookApp.CreateItem(0) (MailItem) com o destinatário em To, a linha de assunto da campanha e o conteúdo da campanha emailMessage, enviado usando a conta real da vítima através de SendUsingAccount.
Entre envios, o agente aplica um atraso aleatório e verifica periodicamente o ponto de extremidade de controle C2 /api/control para comandos de pausa ou reenvio e relata o progresso para /api/progress.
Infraestrutura
Os agentes do REF3076 aproveitaram a infraestrutura Serverless da Cloudflare worker[.]dev para C2 e hospedagem de arquivos. Essa decisão permite que eles herdem qualquer confiança que as vítimas já possam ter na Cloudflare e que façam a rotação da infraestrutura rapidamente, conforme necessário.
Com base no body-hash (91fafaa1240676afe5c55d931261e3798797c408) do site de phishing acima (arquivos-omie[.]com), conseguimos identificar domínios adicionais que provavelmente estão sendo preparados para serem usados como armas:
| Domínio | First Seen | Informações | ASN (Fornecedor) |
|---|---|---|---|
| arquivos-omie[.]com | 2026-04-17 | Squatting - SaaS brasileiro para PMEs | AS 13335 (Cloudflare) |
| documentos-online[.]com | 2026-04-11 | Generic | AS 13335 (Cloudflare) |
| afonsoferragista[.]com | 2026-04-22 | Loja de ferragens - Provavelmente usada em uma isca B2B | AS 13335 (Cloudflare) |
| doccompartilhe[.]com | 2026-04-15 | Genérico - “Compartilhar um documento” | AS 13335 (Cloudflare) |
| temmais[.]com | 2026-04-20 | Ocupação ilegal - Corretagem de crédito/empréstimo brasileira | AS 13335 (Cloudflare) |
Mais infraestrutura de phishing brasileira foi descoberta após uma mudança mais ampla no título do banner (Portal Corporativo), mas não está claro se estava diretamente relacionada ao REF3076 ou a outros atores no ecossistema de trojans bancários latino-americanos. Notavelmente, um cluster utilizou o produto de hospedagem de sites estáticos gratuito Cloudflare pages[.]dev .
O domínio C2 mxtestacionamentos[.]com apontava anteriormente para um IP hospedado no Brasil 191.96.224[.]96.
No ano passado, este IP hospedou simultaneamente um domínio C2 REF3076, um domínio de phishing REF3076 e um domínio anteriormente associado à campanha Water Saci e ao malware SORVEPOTEL/MAVERICK da TrendMicro (saogeraldoshiping[.]com).
Conclusão
O TCLBANKER reflete uma maturação mais ampla que está ocorrendo em todo o ecossistema de trojans bancários no Brasil. Técnicas que antes eram a marca registrada de agentes de ameaças mais sofisticados, como a descriptografia de payloads com controle de ambiente, a geração direta de chamadas de sistema e a orquestração de engenharia social em tempo real via WebSocket, agora estão sendo incorporadas a softwares criminosos comuns. A barreira de entrada continua a diminuir, especialmente quando LLMs poderosos estão facilmente acessíveis para geração de código.
A inclusão de módulos de worms autopropagáveis representa uma mudança notável nesse cenário. A campanha se apropria da confiança e da capacidade de entrega de comunicações legítimas ao sequestrar as sessões do WhatsApp e as contas do Outlook das vítimas. Este é um modelo de distribuição que os gateways de e-mail tradicionais e as defesas baseadas em reputação não estão bem equipados para detectar. À medida que os trojans bancários latino-americanos continuam a adotar esses mecanismos de autopropagação, as organizações devem esperar que o volume e o alcance dessas campanhas aumentem proporcionalmente.
Os artefatos de desenvolvimento ao longo de toda a cadeia, incluindo caminhos de registro de depuração, nomes de processos de teste e um site de phishing ainda em construção, sugerem que o REF3076 está em seus estágios iniciais de operação. Esta é uma campanha que ainda está sendo desenvolvida, não encerrada.
REF3076 através do MITRE ATT&CK
A Elastic usa a estrutura MITRE ATT&CK para documentar táticas, técnicas e procedimentos comuns que as ameaças usam contra redes corporativas.
Táticas
As táticas representam o porquê de uma técnica ou subtécnica. É o objetivo tático do adversário: a razão para executar uma ação.
- Acesso inicial
- Execução
- Persistência
- Defense Evasion
- Acesso a credenciais
- Descoberta
- Coleta
- Command and Control (Comando e controle)
- Exfiltração
- Impacto
Técnicas
Técnicas representam como um adversário atinge um objetivo tático executando uma ação.
- Phishing: Spearphishing Attachment
- Execução de proxy binário do sistema: Msiexec
- Fluxo de execução do Hijack: carregamento lateral de DLL
- Interpretador de comando e script: PowerShell
- Interpretador de comando e script: Shell de comando do Windows
- Tarefa/trabalho agendado: Tarefa agendada
- Deobfuscate/Decode Files or Information
- Arquivos ou informações ofuscadas
- Evasão do depurador
- Evasão de Virtualização/Sandbox: Verificações do Sistema
- Evasão de Virtualização/Sandbox: Evasão Baseada em Tempo
- Impair Defenses: Desabilitar ou modificar ferramentas
- Native API
- Injeção de processo
- Descoberta de Processos
- Descoberta da janela do aplicativo
- Descoberta de informações do sistema
- System Location Discovery: System Language Discovery
- Captura de tela
- Captura de entrada: Keylogging
- Dados da área de transferência
- Captura de entrada: Captura do portal da Web
- Sequestro de sessão do navegador
- Protocolo da Camada de Aplicação: Protocolos Web
- Serviço Web
- Transferência de ferramenta de entrada
- Coleta de e-mails: Coleta local de e-mails
- Desligamento/Reinicialização do sistema
Remediando REF3076
Prevenção
- Alteração da proteção de memória NTDLL via DLL não assinada
- A biblioteca NTDLL foi carregada pela segunda vez.
- Possível desconexão de memória NTDLL
- Parallel NTDLL Loaded from Unbacked Memory
- Alteração suspeita em um módulo central do Windows
- Bypass AMSI via memória sem backup
- Possível desvio de AMSI via SetThreadContext
YARA
O Elastic Security criou regras YARA para identificar essa atividade.
Observações
Os seguintes observáveis foram discutidos nesta pesquisa.
| Observável | Tipo | Nome | Referência |
|---|---|---|---|
| 701d51b7be8b034c860bf97847bd59a87dca8481c4625328813746964995b626 | SHA-256 | screen_retriever_plugin.dll | componente de carregamento TCLBanker |
| 8a174aa70a4396547045aef6c69eb0259bae1706880f4375af71085eeb537059 | SHA-256 | screen_retriever_plugin.dll | componente de carregamento TCLBanker |
| 668f932433a24bbae89d60b24eee4a24808fc741f62c5a3043bb7c9152342f40 | SHA-256 | screen_retriever_plugin.dll | componente de carregamento TCLBanker |
| 63beb7372098c03baab77e0dfc8e5dca5e0a7420f382708a4df79bed2d900394 | SHA-256 | XXL_21042026-181516.zip | Arquivo ZIP inicial do TCLBanker |
| campanha1-api.ef971a42[.]workers.dev | nome de domínio | TCLBanker C2 | |
| mxtestacionamentos[.]com | nome de domínio | TCLBanker C2 | |
| documentos.ef971a42.trabalhadores[.]dev | nome de domínio | Servidor de arquivos TCLBanker | |
| arquivos-omie[.]com | nome de domínio | Página de phishing do TCLBanker (em desenvolvimento) | |
| documentos-online[.]com | nome de domínio | Página de phishing do TCLBanker (em desenvolvimento) | |
| afonsoferragista[.]com | nome de domínio | Página de phishing do TCLBanker (em desenvolvimento) | |
| doccompartilhe[.]com | nome de domínio | Página de phishing do TCLBanker (em desenvolvimento) | |
| temmais[.]com | nome de domínio | Página de phishing do TCLBanker (em desenvolvimento) |