Analisando Mecanismos de Criptografia de Ransomware
Quando Usar
- Um ataque de ransomware ocorreu e a recuperação exige entender o esquema de criptografia usado
- Avaliar se a descriptografia é possível sem pagar o resgate (falhas de implementação, descriptografadores conhecidos)
- Fazer engenharia reversa de ransomware para identificar o algoritmo de criptografia, derivação de chave e mecanismo de armazenamento de chave
- Desenvolver uma ferramenta de descriptografia quando uma fraqueza na implementação criptográfica do ransomware é identificada
- Classificar uma amostra de ransomware por sua abordagem de criptografia para atribuí-la a uma família conhecida
Não use para operações de recuperação de dados em produção sem primeiro verificar o método de descriptografia em cópias de teste dos arquivos criptografados.
Pré-requisitos
- Ghidra ou IDA Pro para engenharia reversa do binário do ransomware
- Python 3.8+ com a biblioteca
pycryptodomepara testar rotinas de criptografia/descriptografia - Arquivos criptografados de amostra e seus originais em texto plano correspondentes (pares de texto-plano conhecido)
- Acesso ao binário do ransomware (desempacotado, se aplicável)
- Familiaridade com algoritmos criptográficos simétricos (AES, ChaCha20) e assimétricos (RSA)
- Banco de dados NoMoreRansom.org para verificar descriptografadores gratuitos existentes
Fluxo de Trabalho
Etapa 1: Identificar o Algoritmo de Criptografia
Determine qual algoritmo criptográfico o ransomware usa:
# Verificar uso da Crypto API do Windows nas importações
import pefile
pe = pefile.PE("ransomware.exe")
crypto_apis = {
"CryptAcquireContextA": "Windows CryptoAPI",
"CryptAcquireContextW": "Windows CryptoAPI",
"CryptGenKey": "Windows CryptoAPI - geração de chave",
"CryptEncrypt": "Windows CryptoAPI - criptografia",
"CryptImportKey": "Windows CryptoAPI - importação de chave",
"BCryptOpenAlgorithmProvider": "Windows CNG (cripto moderna)",
"BCryptEncrypt": "Windows CNG - criptografia",
"BCryptGenerateKeyPair": "Windows CNG - geração de par de chaves assimétricas",
}
print("Importações da Crypto API:")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
if imp.name and imp.name.decode() in crypto_apis:
print(f" {entry.dll.decode()} -> {imp.name.decode()}: {crypto_apis[imp.name.decode()]}")
Esquemas Comuns de Criptografia de Ransomware:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AES-256-CBC + RSA-2048: Esquema híbrido mais comum (LockBit, REvil, Conti)
AES-256-CTR + RSA-4096: Variante de modo de fluxo (BlackCat/ALPHV)
ChaCha20 + RSA-4096: Cifra de fluxo moderna (Hive, Royal)
Salsa20 + ECDH: Troca de chaves Curve25519 (Babuk)
AES-128-ECB: Modo fraco - potencial descriptografia via texto-plano conhecido
Apenas XOR: Criptografia trivial - sempre recuperável
Algoritmo personalizado: Frequentemente contém falhas de implementação
Etapa 2: Analisar Geração e Gerenciamento de Chaves
Faça engenharia reversa de como as chaves de criptografia são geradas e armazenadas:
Padrões de Gerenciamento de Chaves em Ransomware:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. FORTE (nenhuma recuperação possível sem a chave):
- Chave AES por arquivo gerada com CryptGenRandom
- Chave AES criptografada com chave pública RSA embutida
- Chave criptografada anexada a cada arquivo ou armazenada separadamente
- Chave privada RSA mantida apenas pelo servidor C2 do atacante
2. FRACO (recuperação potencial):
- Chave AES derivada de semente previsível (timestamp, PID)
- Mesma chave AES usada para todos os arquivos (comprometer uma chave = recuperação total)
- Chave transmitida ao C2 antes da criptografia iniciar (PCAP pode conter a chave)
- XOR com chave curta e repetitiva (força bruta possível)
- PRNG semeado com GetTickCount ou time() (espaço de chaves limitado)
3. IMPLEMENTAÇÃO COM FALHAS:
- Modo ECB (preserva padrões do texto plano)
- Reutilização de vetor de inicialização (IV) entre arquivos
- Chave armazenada em texto plano na memória (recuperável de dump de memória)
- Criptografia parcial (apenas os primeiros N bytes criptografados)
Etapa 3: Examinar a Rotina de Criptografia de Arquivos
Faça engenharia reversa da lógica de processamento de arquivos:
// Fluxo típico de criptografia de arquivo de ransomware (pseudo-código descompilado do Ghidra):
void encrypt_file(char *filepath) {
// 1. Verificar extensão do arquivo contra a lista de alvos
if (!is_target_extension(filepath)) return;
// 2. Gerar chave AES por arquivo (32 bytes para AES-256)
BYTE aes_key[32];
CryptGenRandom(hProv, 32, aes_key);
// 3. Gerar IV aleatório (16 bytes)
BYTE iv[16];
CryptGenRandom(hProv, 16, iv);
// 4. Ler conteúdo do arquivo
HANDLE hFile = CreateFile(filepath, GENERIC_READ, ...);
BYTE *plaintext = read_entire_file(hFile);
// 5. Criptografar com AES-256-CBC
aes_cbc_encrypt(plaintext, file_size, aes_key, iv);
// 6. Criptografar chave AES com chave pública RSA
BYTE encrypted_key[256]; // Saída RSA-2048
rsa_encrypt(aes_key, 32, rsa_pubkey, encrypted_key);
// 7. Escrever: dados_criptografados + chave_criptografada + IV no arquivo
write_file(filepath, encrypted_data, encrypted_key, iv);
// 8. Renomear arquivo com extensão do ransomware
rename_file(filepath, strcat(filepath, ".locked"));
}
Etapa 4: Verificar Fraquezas Criptográficas
Teste a implementação em busca de falhas exploráveis:
from Crypto.Cipher import AES
import os
import struct
# Teste 1: Verificar se a mesma chave é usada para vários arquivos
# Comparar versões criptografadas de arquivos conhecidos
def check_key_reuse(file1_enc, file2_enc):
with open(file1_enc, "rb") as f:
data1 = f.read()
with open(file2_enc, "rb") as f:
data2 = f.read()
# Extrair IVs (localização depende da família de ransomware)
# Se os IVs são os mesmos e os arquivos compartilham blocos criptografados -> mesma chave
iv1 = data1[-16:] # Exemplo: IV no final
iv2 = data2[-16:]
if iv1 == iv2:
print("[!] Mesmo IV detectado - reutilização de chave provável")
# Teste 2: Verificar derivação de chave previsível
# Se a chave é derivada de timestamp, iterar valores possíveis
def brute_force_timestamp_key(encrypted_file, known_header, timestamp_range):
with open(encrypted_file, "rb") as f:
encrypted_data = f.read()
for ts in timestamp_range:
# Derivar chave da mesma forma que o ransomware faz
import hashlib
key = hashlib.sha256(str(ts).encode()).digest()
iv = encrypted_data[-16:]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(encrypted_data[:16])
if decrypted[:len(known_header)] == known_header:
print(f"[!] Chave encontrada! Timestamp: {ts}")
return key
return None
# Teste 3: Verificar modo ECB (preservação de padrões)
def check_ecb_mode(encrypted_file):
with open(encrypted_file, "rb") as f:
data = f.read()
# ECB produz texto cifrado idêntico para blocos de texto plano idênticos
blocks = [data[i:i+16] for i in range(0, len(data), 16)]
unique = len(set(blocks))
total = len(blocks)
if unique < total * 0.95:
print(f"[!] Modo ECB provável: {total-unique} blocos duplicados de {total}")
Etapa 5: Tentar Recuperação de Chave
Use fraquezas identificadas para recuperação de chave:
# Método de Recuperação 1: Extrair chave de dump de memória
# Plugin Volatility para escanear schedules de chave AES
# vol3 -f memory.dmp windows.yarascan --yara-rule "aes_key_schedule"
# Método de Recuperação 2: Ataque de texto-plano conhecido (algoritmos fracos)
def xor_key_recovery(encrypted_file, known_plaintext):
"""Recuperar chave XOR de par texto-plano conhecido / texto cifrado"""
with open(encrypted_file, "rb") as f:
ciphertext = f.read()
key = bytes(c ^ p for c, p in zip(ciphertext, known_plaintext))
# Encontrar comprimento da chave repetitiva
for key_len in range(1, 256):
candidate = key[:key_len]
if all(key[i] == candidate[i % key_len] for i in range(min(len(key), key_len * 4))):
print(f"Chave XOR (comprimento {key_len}): {candidate.hex()}")
return candidate
return None
# Método de Recuperação 3: Verificar NoMoreRansom para descriptografadores existentes
# https://www.nomoreransom.org/en/decryption-tools.html
Etapa 6: Documentar a Análise de Criptografia
Compile as descobertas em um relatório estruturado:
A análise deve documentar:
- Algoritmo identificado (AES, RSA, ChaCha20, personalizado)
- Tamanho da chave e modo de operação (CBC, CTR, ECB, GCM)
- Método de geração de chave (CSPRNG, semente previsível, chave estática)
- Local de armazenamento da chave (anexada ao arquivo, registro, transmissão C2)
- Padrão de modificação do arquivo (criptografia total, parcial, apenas cabeçalho)
- Extensões de arquivo alvo
- Formato da nota de resgate e infraestrutura de pagamento
- Avaliação de viabilidade de descriptografia (possível/impossível/parcial)
- Abordagem de recuperação recomendada
Conceitos-Chave
| Termo | Definição |
|---|---|
| Criptografia Híbrida | Combina simétrica (AES) para criptografia rápida de arquivos com assimétrica (RSA) para encapsulamento seguro de chave; a abordagem padrão de ransomware |
| Encapsulamento de Chave | Criptografar a chave simétrica por arquivo com a chave pública RSA do atacante para que apenas a chave privada do atacante possa descriptografá-la |
| Modo ECB | O modo Electronic Codebook criptografa cada bloco independentemente; preserva padrões no texto plano, uma fraqueza crítica que permite recuperação parcial |
| Ataque de Texto-Plano Conhecido | Usar um arquivo original conhecido e sua versão criptografada para derivar a chave de criptografia; eficaz contra XOR e cifras de fluxo fracas |
| Key Schedule (Agenda de Chaves) | A forma expandida de uma chave AES na memória; escaneável em dumps de memória para recuperar chaves de criptografia antes que sejam apagadas |
| CSPRNG | Gerador de Números Pseudo-Aleatórios Criptograficamente Seguro; ransomware usando CryptGenRandom produz chaves imprevisíveis |
| Criptografia Parcial | Alguns ransomwares criptografam apenas os primeiros N bytes ou a cada N bloco por velocidade; porções não criptografadas podem auxiliar na recuperação |
Ferramentas e Sistemas
- Ghidra: Suíte de engenharia reversa para analisar rotinas de criptografia de ransomware no nível de assembly
- PyCryptodome: Biblioteca criptográfica Python para implementar e testar rotinas de descriptografia
- NoMoreRansom.org: Repositório gratuito de ferramentas de descriptografia mantido pela Europol e fornecedores de segurança para famílias conhecidas de ransomware
- Volatility: Framework de perícia forense de memória para extrair chaves de criptografia de dumps de RAM de sistemas infectados
- CryptoTester: Ferramenta para identificar algoritmos criptográficos com base em constantes e padrões de código
Cenários Comuns
Cenário: Avaliando a Viabilidade de Descriptografia para um Incidente de Ransomware
Contexto: Uma organização é atingida por ransomware que criptografa servidores de arquivos. A gerência precisa saber se a descriptografia é possível sem pagar o resgate antes de tomar uma decisão de recuperação.
Abordagem:
- Identificar a família de ransomware pela nota de resgate, extensão do arquivo e hash da amostra (verificar ID Ransomware)
- Verificar NoMoreRansom.org por descriptografadores gratuitos existentes para esta família
- Fazer engenharia reversa da rotina de criptografia no Ghidra para identificar o algoritmo e o gerenciamento de chaves
- Testar por fraquezas de implementação (reutilização de chave, sementes previsíveis, modo ECB)
- Verificar se o PCAP do incidente capturou a transmissão da chave para o C2 (se a chave foi enviada antes da criptografia)
- Escanear dumps de memória das máquinas afetadas por schedules de chave AES na RAM
- Relatar descobertas: descriptografia possível/impossível com justificativa técnica específica
Armadilhas:
- Testar métodos de descriptografia na única cópia dos arquivos criptografados (trabalhe sempre em cópias)
- Assumir que todos os arquivos usam a mesma chave sem verificar (alguns ransomwares usam chaves por arquivo)
- Não verificar cópias de sombra de volume (vssadmin) que o ransomware pode ter falhado em excluir
- Confundir o algoritmo de criptografia de arquivo com o algoritmo de encapsulamento de chave em relatórios
Formato de Saída
ANÁLISE DE CRIPTOGRAFIA DE RANSOMWARE
==========================================
Amostra: lockbit3.exe
Família: LockBit 3.0 / LockBit Black
SHA-256: abc123def456...
ESQUEMA DE CRIPTOGRAFIA
Cifra de Arquivo: AES-256-CTR (chave única por arquivo)
Encapsulamento de Chave: RSA-2048 (chave pública embutida no binário)
Geração de Chave: CryptGenRandom (CSPRNG - imprevisível)
Geração de IV: 16 bytes aleatórios por arquivo
Estrutura do Arquivo: [dados_criptografados][chave_rsa_criptografada(256B)][iv(16B)][magic(8B)]
EXTENSÕES ALVO
Total: 412 extensões visadas
Categorias: Documentos (.doc, .xls, .pdf), Bancos de Dados (.sql, .mdb),
Arquivos Compactados (.zip, .7z), Código Fonte (.py, .java, .cs)
Excluídas: .exe, .dll, .sys, .lnk (arquivos de sistema preservados)
ANÁLISE DE IMPLEMENTAÇÃO
Força da Chave: FORTE - chaves aleatórias por arquivo, sem reutilização
Segurança do Modo: FORTE - modo CTR com nonces únicos
Armazenamento de Chave: Chave criptografada com RSA anexada a cada arquivo
Cópias de Sombra: Excluídas via vssadmin e WMI
VIABILIDADE DE DESCRIPTOGRAFIA
Sem a Chave: NÃO É POSSÍVEL
- Nenhuma falha de implementação identificada
- Encapsulamento de chave RSA-2048 impede força bruta
- CSPRNG impede previsão de chave
- Nenhum descriptografador gratuito existente disponível
OPÇÕES DE RECUPERAÇÃO
1. Restaurar a partir de backups offline (recomendado)
2. Verificar por cópias de sombra de volume (baixa probabilidade - ransomware as exclui)
3. Perícia forense de memória se a máquina não foi reinicializada (chave pode persistir na RAM)
4. Negociar com o atacante (último recurso - sem garantia de descriptografia)