
Notas de engenharia reversa, código-fonte desofuscado, IOCs e regras YARA para o RAT Python Tourmaline ClickFix, abrangendo seu túnel DNS e C2 de dead-drop em blockchain.
Recentemente me deparei com um malware habilmente projetado que se autodenomina "Torumaline".
Este README foi gentilmente escrito pelo Claude, pois eu estava extremamente ocupado com provas no momento da criação deste repositório.
Explorar e descriptografar este malware consumiu uma enorme parte do meu tempo de preparação para matemática!
Leia o post do blog!
APENAS PARA FINS EDUCACIONAIS E DE PESQUISA
Todas as amostras são fornecidas para análise de malware e pesquisa defensiva. Não execute fora de um ambiente isolado (sandbox) e sem conexão com a rede.
Tourmaline (Tourmaline.exe) é um infostealer/backdoor sofisticado e multiestágio para Windows, distribuído por meio de uma campanha ClickFix — um popup falso de "Verifique se você é humano" do Cloudflare que engana os usuários para executarem manualmente um comando ou instalador malicioso.
O binário é um instalador customizado do Inno Setup 6.7.0 (Revisão 2, offsets de 64 bits) que inclui um runtime completo do Python 3.11 e dois estágios de payload Python ofuscado. Ele estabelece um backdoor persistente com:
microsoft.com)tourmaline/
├── README.md # Este arquivo
├── LICENSE # Licença de uso para pesquisa
├── .gitignore
│
├── src/ # Código-fonte extraído e desofuscado
│ ├── stage1_loader.py # Estágio 1: Loader original ofuscado com XOR time-lock (main.py)
│ ├── stage2_backdoor.py # Estágio 2: Backdoor principal desofuscado (de QGBdu.dxf)
│ └── decrypt_payload.py # Utilitário: Recuperação de chave O(1) e descriptografia do payload
│
├── iocs/ # Indicadores de Comprometimento
│ ├── indicators.json # Dados de IOC estruturados (IPs, hashes, domínios, registro)
│ ├── indicators.csv # CSV plano para importação em SIEM
│ └── rules.yar # Regras de detecção YARA
│
└── samples/ # Amostras de malware (protegidas por senha)
├── README.md # Instruções do arquivo de amostras
├── Tourmaline_sample.zip # Senha: infected - contém Tourmaline.exe
└── QGBdu.dxf # Blob bruto criptografado do Estágio 2
O malware é distribuído via ClickFix — uma técnica de engenharia social em que um site comprometido ou controlado pelo atacante sobrepõe uma página falsa de CAPTCHA do Cloudflare ou de verificação do navegador. A sobreposição instrui a vítima a:
Win+RO comando colado baixa e executa silenciosamente Tourmaline.exe. O instalador é executado com /VERYSILENT /SUPPRESSMSGBOXES /NORESTART.
| Propriedade | Valor |
|---|---|
| Nome do arquivo | Tourmaline.exe |
| Tamanho | 11.341.339 bytes (~10,8 MB) |
| MD5 | b74ac808dea2de31caf024310694ef0c |
| SHA256 | c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6 |
| Formato | Inno Setup 6.7.0 Unicode (Revisão 2, offsets de 64 bits) |
| Tipo PE | PE de 32 bits, 11 seções |
| Tamanho do overlay | 10.447.387 bytes |
| Offset do magic do Inno | 0xD9864 (890.148 bytes) |
| Nome do app | Tourmaline |
| Versão do app | 2.63.519 |
| GUID do app | {2C25872D-85FC-44C7-9B16-844E39E50A44} |
| Caminho de instalação | {commonappdata}\Tourmaline |
| Runtime incluído | Python 3.11 (embed completo) |
| Arquivos de payload | 36 arquivos em stream LZMA2 sólido |
Nota: O
innoextract 1.9padrão não consegue extrair este binário — ele só suporta a Revisão 1. A Revisão 2 usa offsets de 64 bits e requer parsing customizado (vejasrc/decrypt_payload.py).
Tourmaline.exe
│
├─ Instalador Inno Setup é executado silenciosamente
│ ├─ Extrai o runtime Python 3.11 para %APPDATA%\Tourmaline\
│ ├─ Extrai main.py (loader do Estágio 1)
│ ├─ Extrai QGBdu.dxf (blob criptografado do Estágio 2)
│ ├─ Encerra quaisquer instâncias existentes de pythonw.exe
│ └─ Registra persistência (Agendador de Tarefas / registro)
│ └─ Nome: "TourmalineUpdate" / "Hardware monitoring service"
│
├─ Estágio 1: main.py (Loader com XOR Time-Lock)
│ ├─ Conta _n de 99.999.999 → 0 (atraso anti-sandbox de ~horas em VMs lentas)
│ ├─ A cada _n, constrói chave XOR de 33 bytes: struct.pack('>I', _n) + sufixo_hardcoded
│ ├─ Testa a chave contra o cabeçalho de texto claro conhecido de QGBdu.dxf
│ └─ Em caso de correspondência: descriptografa QGBdu.dxf inteiramente e exec() o resultado
│ └─ Bypass O(1): ataque de texto claro conhecido nos primeiros 4 bytes (veja abaixo)
│
└─ Estágio 2: QGBdu.dxf → Backdoor em Python
├─ Lê MachineGuid de HKLM\SOFTWARE\Microsoft\Cryptography
├─ Deriva o mutex Global\Tourmaline_<hash>
├─ Resolve o IP do C2 via dead-drop Ethereum (testnet Sepolia)
├─ Estabelece túnel DNS para o C2
└─ Loop de poll-execute: busca tarefas, exec() Python, retorna saída
O loader (main.py) usa uma contagem regressiva de 99.999.999 para encontrar a chave de descriptografia XOR. Em uma máquina real isso é concluído em segundos (porque _n começa alto e o valor verdadeiro está próximo de 14.511.188). Em um sandbox com limite de tempo curto, o loop nunca é concluído.
Estrutura da chave:
full_key = struct.pack('>I', _n) + bytes.fromhex('2b0cffe07b06ac25793b3f00cfaa2dd5881c2d6378165247539dbbdaeb')
Como conhecemos os primeiros 16 bytes do texto claro (g1 = lambda l6, ), podemos recuperar _n instantaneamente via ataque XOR de texto claro conhecido:
key_prefix = bytes(ciphertext[i] ^ known_plaintext[i] for i in range(4))
# Resultado: key_prefix = 00dd6c54 → _n = 14,511,188
Use src/decrypt_payload.py para reproduzir isso.
| Parâmetro | Valor |
|---|---|
| IP do C2 | 158.94.211.185 |
| Porta do C2 | 53 (UDP) |
| Protocolo | Túnel DNS-over-UDP customizado |
| Domínio falsificado | microsoft.com |
| Chave ChaCha20 | 36f555c87f71581f57d83576c88193fdc00a0173f741a3e198e2d7abdc9cda59 |
| Contrato blockchain | 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5 (Sepolia) |
| Chave pública ECDSA | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt17l3rGHHR9sYdHEvV8S+JRRCUHQQveSadlGk04xM/8WClDf/67Tyritt2+T18SY8n0xv1TKKl0AgnNFuboEEQ== |
| Nome do serviço | SystemService / TourmalineUpdate |
| Mutex | Global\Tourmaline_<MachineGuid-hash> |
O malware chama um contrato inteligente Ethereum na testnet Sepolia para recuperar o endereço IP ativo do C2. Isso significa que o atacante pode alterar o IP do C2 a qualquer momento atualizando o contrato — a interrupção tradicional do C2 baseada em listas de bloqueio de IP é ineficaz.
Contrato : 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5
Seletor : 0xeb9fd6fe
Rede : Ethereum Sepolia (chainId 11155111)
RPC : https://ethereum-sepolia-rpc.publicnode.com
Resultado: Blob criptografado com ChaCha20 contendo o IP atual do C2
Os dados retornados são descriptografados com a chave ChaCha20 hardcoded para revelar o endereço ativo do C2. No momento da análise, isso resolvia para 158.94.211.185 (verificado via chamada RPC ao vivo).
Todo o tráfego do C2 é enviado como consultas DNS UDP brutas diretamente para o IP do C2 na porta 53. As consultas são estruturadas como <encoded_data>.microsoft.com, contornando a filtragem baseada em DNS e parecendo telemetria legítima do Windows.
socket.getaddrinfo do Python nem qualquer biblioteca DNSO backdoor implementa um motor de exec() Python arbitrário. As tarefas são:
exec() em um namespace persistente com captura de saídaTipos de tarefa suportados: exec Python, upload/download de arquivo, comando shell, auto-atualização.
| Tipo | Valor |
|---|---|
| IP do C2 | 158.94.211.185 |
| Porta do C2 | 53/UDP |
| Domínio falsificado | *.microsoft.com (UDP customizado, não DNS real) |
| RPC Ethereum | https://ethereum-sepolia-rpc.publicnode.com |
| Contrato Inteligente | 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5 |
| Arquivo | SHA256 |
|---|---|
Tourmaline.exe | c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6 |
Tourmaline.exe (MD5) | b74ac808dea2de31caf024310694ef0c |
| Chave | Valor |
|---|---|
HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid | Lido para fingerprinting da vítima |
%APPDATA%\Tourmaline\ | Diretório de instalação |
| Agendador de Tarefas | TourmalineUpdate |
| Nome de exibição do serviço | Hardware monitoring service |
| Mutex | Global\Tourmaline_<hash> |
Veja iocs/rules.yar para regras de detecção cobrindo:
Se este malware foi executado em uma máquina:
taskkill /F /IM pythonw.exe%APPDATA%\Tourmaline\ ou %COMMONAPPDATA%\Tourmaline\TourmalineUpdateHKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run para Tourmaline ou SystemService158.94.211.185:53/UDP; bloqueie todo tráfego UDP/53 de saída inesperadoethereum-sepolia-rpc.publicnode.compip install pyOpenSSL cryptography
# A partir da raiz do repositório:
python3 src/decrypt_payload.py samples/QGBdu.dxf decrypted_stage2.py
7z x -pinfected samples/Tourmaline_sample.zip
| Campo | Valor |
|---|---|
| Data da descoberta | Setembro de 2026 |
| Pesquisador | Vihaan Pundir (v-pun215) |
| Vetor de distribuição | ClickFix falso CAPTCHA do Cloudflare |
| Classificação | Backdoor / C2 por Túnel DNS / Dead-Drop em Blockchain |
| Plataforma | Windows (64 bits) |
Veja LICENSE. Este repositório é destinado apenas a fins educacionais e de pesquisa defensiva.