Técnicas de Cifrado en Ransomware: AES, RSA, ChaCha20 y Cifrado Híbrido
Análisis técnico profundo de los algoritmos criptográficos que usan los ransomware modernos. AES-256, RSA-2048, ChaCha20-Poly1305, Curve25519, cifrado híbrido, cifrado parcial y los errores criptográficos que han permitido descifrar familias como Hive y Akira.
Por qué la criptografía importa para los defensores
Cuando un equipo de respuesta a incidentes llega a una red cifrada por ransomware, la primera pregunta es: ¿se pueden recuperar los archivos sin pagar? La respuesta depende enteramente de la implementación criptográfica del ransomware. Un error en la generación de claves, un IV reutilizado o un PRNG predecible pueden ser la diferencia entre una recuperación completa y una pérdida total.
Este artículo analiza los algoritmos y patrones criptográficos que usan las familias de ransomware modernas. No es un curso de criptografía: asume conocimiento básico de cifrado simétrico y asimétrico. El objetivo es que un analista pueda identificar qué algoritmos usa una muestra, evaluar si la implementación tiene debilidades y saber dónde buscar artefactos criptográficos durante un análisis forense.
Cifrado simétrico: AES-256
Fundamentos
AES (Advanced Encryption Standard) es el algoritmo simétrico más usado en ransomware. Opera sobre bloques de 128 bits con claves de 128, 192 o 256 bits. La variante de 256 bits es la estándar en ransomware por razones de marketing tanto como de seguridad: "cifrado militar de 256 bits" suena más intimidante en una nota de rescate.
Modos de operación en ransomware
El modo de operación determina cómo AES procesa múltiples bloques. Cada modo tiene implicaciones de seguridad y rendimiento:
| Modo | Descripción | Familias que lo usan | Debilidades conocidas |
|---|---|---|---|
| CBC (Cipher Block Chaining) | Cada bloque se XORea con el bloque cifrado anterior | REvil, Maze, GandCrab | Requiere padding, vulnerable a padding oracle si hay retroalimentación |
| CTR (Counter) | Convierte AES en cifrado de stream usando un contador | LockBit 2.0, Ryuk | Reutilización de nonce = catastrófico (keystream reutilizado) |
| GCM (Galois/Counter Mode) | CTR + autenticación integrada (AEAD) | Hive (parcial) | Misma vulnerabilidad de nonce que CTR, más overhead |
| ECB (Electronic Codebook) | Cada bloque se cifra independientemente | Ransomware amateur | Patrones del plaintext visibles en el ciphertext. Inseguro |
ECB es un indicador de ransomware de baja calidad. Cifrar una imagen BMP en modo ECB deja visible la silueta de la imagen original porque bloques idénticos de plaintext producen bloques idénticos de ciphertext. Ninguna familia seria lo usa.
CBC es el modo más común en familias legacy. Requiere un IV (Initialization Vector) único por archivo. Si el IV se reutiliza o es predecible, puede facilitar el análisis.
CTR es preferido por familias modernas porque permite cifrado en paralelo (cada bloque se puede cifrar independientemente con su valor de contador) y no requiere padding. Pero la reutilización de nonce es fatal: si dos archivos se cifran con el mismo nonce y la misma clave, el XOR de los dos ciphertexts revela el XOR de los dos plaintexts, lo que frecuentemente permite recuperar ambos.
Pseudocódigo: cifrado AES-CTR en ransomware
# Rutina de cifrado simplificada (NO código real de malware)
def encrypt_file_aes_ctr(filepath, aes_key, nonce):
"""
Cifra un archivo con AES-256-CTR.
aes_key: 32 bytes (256 bits) generados con CSPRNG
nonce: 16 bytes unicos por archivo
"""
plaintext = read_file(filepath)
cipher = AES_CTR(key=aes_key, nonce=nonce)
ciphertext = cipher.encrypt(plaintext)
# Escribir: nonce + ciphertext cifrado
write_file(filepath + ".encrypted", nonce + ciphertext)
# Cifrar la clave AES con la clave publica RSA del atacante
encrypted_key = rsa_encrypt(aes_key, attacker_public_key)
# Almacenar la clave cifrada (en el archivo o en fichero separado)
append_to_file(filepath + ".encrypted", encrypted_key)
# Borrar el archivo original
secure_delete(filepath)
ChaCha20-Poly1305: la alternativa moderna
Por qué ChaCha20 gana terreno
ChaCha20 es un cifrado de stream diseñado por Daniel J. Bernstein como alternativa a AES. Su adopción en ransomware ha crecido significativamente desde 2020 por varias razones:
Rendimiento en software puro: en CPUs sin instrucciones AES-NI (hardware de aceleración AES), ChaCha20 es 2-3 veces más rápido que AES. Esto importa en servidores antiguos, máquinas virtuales donde AES-NI no siempre está expuesto, y dispositivos ARM (NAS, IoT).
Simplicidad de implementación: ChaCha20 usa operaciones simples (sumas de 32 bits, XOR, rotaciones) que son difíciles de implementar incorrectamente. AES-CBC requiere gestionar padding, IVs, y es vulnerable a timing attacks si se implementa con tablas de lookup en software.
AEAD integrado: ChaCha20-Poly1305 combina cifrado y autenticación en un solo paso, eliminando la necesidad de gestionar un MAC separado.
Familias que usan ChaCha20
| Familia | Variante | Notas |
|---|---|---|
| Conti | ChaCha20 (32 threads) | Adopción por rendimiento en despliegue masivo |
| Babuk | ChaCha20 + ECDH (Curve25519) | Cross-platform: Windows, Linux, ESXi |
| Royal/BlackSuit | ChaCha20 parcial | Cifrado intermitente con ChaCha20 |
| Hive | ChaCha20 + RSA-2048 | Error en generación de keystream que permitió descifrado |
| RansomExx | ChaCha20 + RSA-4096 | Variante Linux |
Parámetros de ChaCha20
ChaCha20 opera con:
- Clave: 256 bits (32 bytes)
- Nonce: 96 bits (12 bytes) en la variante estándar, 192 bits (24 bytes) en XChaCha20
- Counter: 32 bits, permite cifrar hasta 256 GB con un solo par clave/nonce
La reutilización de nonce en ChaCha20 tiene las mismas consecuencias catastróficas que en AES-CTR: el keystream se repite y el XOR de los ciphertexts expone relaciones entre los plaintexts.
Cifrado asimétrico: RSA y curvas elípticas
RSA en ransomware
RSA se usa exclusivamente para cifrar las claves simétricas (AES o ChaCha20), nunca para cifrar archivos directamente (demasiado lento). Las variantes más comunes:
- RSA-2048: 2048 bits de módulo. Considerado seguro con tecnología actual. Factorizar RSA-2048 requeriría recursos computacionales que no existen
- RSA-4096: 4096 bits. Overkill para la mayoría de escenarios, pero usado por familias que quieren proyectar sofisticación (REvil, RansomExx)
Flujo de claves RSA en ransomware
El esquema típico usa dos niveles de claves RSA:
Nivel 1: Master Key (del operador)
RSA key pair generado offline por el operador
Clave publica embebida en el builder
Clave privada almacenada de forma segura por el operador
Nivel 2: Session Key (por victima)
RSA key pair generado en la maquina de la victima
Clave publica de sesion se usa para cifrar las claves AES por archivo
Clave privada de sesion se cifra con la Master Public Key
Solo el operador puede descifrar la clave privada de sesion
Resultado:
Archivo cifrado con AES key unica
AES key cifrada con Session Public Key
Session Private Key cifrada con Master Public Key
Solo el Master Private Key del operador puede desbloquear toda la cadena
Este esquema de dos niveles permite que el builder genere payloads sin contener la clave privada maestra. Incluso si un investigador extrae todas las claves del payload, solo obtiene la clave pública maestra.
Curve25519 / X25519: la alternativa moderna
Familias recientes (Babuk, Conti v3, algunas variantes de BlackCat) usan criptografía de curva elíptica en vez de RSA:
- Curve25519: curva elíptica de Montgomery, 128 bits de seguridad
- X25519: protocolo de intercambio de claves Diffie-Hellman sobre Curve25519
- Ed25519: esquema de firma digital sobre la misma curva
Ventajas sobre RSA:
- Claves mucho más pequeñas (32 bytes vs 256-512 bytes)
- Operaciones más rápidas
- Más difícil de implementar incorrectamente (la curva fue diseñada para resistir errores de implementación)
- Daniel J. Bernstein diseñó tanto ChaCha20 como Curve25519, lo que hace que la combinación sea natural
El flujo completo: cifrado híbrido paso a paso
Pseudocódigo del flujo completo de un ransomware que usa ChaCha20 + X25519:
# FASE 1: Inicializacion (al ejecutarse en la maquina victima)
def initialize():
# Clave publica del operador (embebida en el binario)
operator_pubkey = HARDCODED_X25519_PUBLIC_KEY
# Generar par de claves de sesion para esta victima
session_privkey = x25519_generate_private_key()
session_pubkey = x25519_derive_public_key(session_privkey)
# Derivar shared secret con la clave del operador
shared_secret = x25519_key_exchange(session_privkey, operator_pubkey)
# La session_privkey se cifra con el shared_secret y se guarda
# Solo el operador puede recalcular el shared_secret usando
# su clave privada + session_pubkey de la victima
return session_pubkey, shared_secret
# FASE 2: Cifrado de archivos
def encrypt_file(filepath, shared_secret, session_pubkey):
# Generar clave y nonce unicos para este archivo
file_key = csprng(32) # 256 bits
file_nonce = csprng(12) # 96 bits
plaintext = read_file(filepath)
# Cifrar con ChaCha20-Poly1305
ciphertext, tag = chacha20_poly1305_encrypt(
key=file_key,
nonce=file_nonce,
plaintext=plaintext
)
# Cifrar la file_key con el shared_secret (AES-256-GCM o similar)
encrypted_file_key = aes_gcm_encrypt(
key=shared_secret[:32],
plaintext=file_key
)
# Escribir archivo cifrado
# Formato: [session_pubkey | nonce | encrypted_file_key | tag | ciphertext]
write_encrypted_file(filepath, session_pubkey, file_nonce,
encrypted_file_key, tag, ciphertext)
# Limpiar claves de memoria
secure_zero(file_key)
secure_zero(plaintext)
# FASE 3: Descifrado (por el operador tras el pago)
def decrypt_file(filepath, operator_privkey):
# Leer componentes del archivo cifrado
session_pubkey, nonce, encrypted_file_key, tag, ciphertext = \
parse_encrypted_file(filepath)
# Recalcular shared_secret
shared_secret = x25519_key_exchange(operator_privkey, session_pubkey)
# Descifrar la file_key
file_key = aes_gcm_decrypt(
key=shared_secret[:32],
ciphertext=encrypted_file_key
)
# Descifrar el archivo
plaintext = chacha20_poly1305_decrypt(
key=file_key, nonce=nonce,
ciphertext=ciphertext, tag=tag
)
write_file(filepath, plaintext)
Cifrado intermitente: velocidad sobre completitud
El problema del rendimiento
En una red empresarial con decenas de terabytes de datos, cifrar cada byte de cada archivo puede tardar horas. Los defensores tienen tiempo para detectar la actividad anómala de I/O, aislar sistemas y contener el ataque.
El cifrado intermitente resuelve este problema cifrando solo una fracción del archivo. Un archivo de 10 GB cifrado al 4% tarda segundos en vez de minutos, pero el archivo queda igualmente inutilizable.
Estrategias de cifrado parcial
| Estrategia | Implementación | Ventajas | Desventajas |
|---|---|---|---|
| Primeros N bytes | Cifrar los primeros 4 KB, 64 KB o 1 MB | Simple, destruye headers de formato | Datos recuperables en la porción no cifrada |
| Bloques alternos | Cifrar bloque de 1 MB, saltar 1 MB, repetir | Distribución uniforme del daño | Patrón predecible, facilita análisis |
| Porcentaje adaptativo | Archivos pequeños (menos de 5 MB) completos, grandes al 4-10% | Balance rendimiento/daño | Lógica más compleja |
| Cabeza + cola | Cifrar primeros y últimos N bytes | Destruye headers y footers | Datos intermedios intactos |
| Stripes | Bandas de N KB cifradas con gaps de M KB | Configurable en el builder | Patrón regular detectable |
Implicaciones forenses del cifrado parcial
El cifrado parcial tiene consecuencias importantes para la recuperación:
- Headers de archivo: si solo se cifran los primeros bytes, herramientas de carving pueden identificar el tipo de archivo por la extensión y intentar reparar headers
- Bases de datos: las bases de datos SQL parcialmente cifradas pueden tener registros completos recuperables en las secciones no cifradas
- Máquinas virtuales: archivos VMDK parcialmente cifrados pueden montarse con herramientas especializadas que reconstruyen la tabla de asignación
- Imágenes y vídeos: los datos de píxeles/frames en la porción no cifrada son recuperables, aunque sin headers válidos requieren reconstrucción manual
File targeting: qué se cifra y qué no
Extensiones objetivo típicas
Las familias de ransomware mantienen listas de extensiones a cifrar. Una lista representativa:
Documentos: .doc .docx .xls .xlsx .ppt .pptx .pdf .odt .ods .odp
Bases de datos: .sql .sqlite .mdb .accdb .dbf .mdf .ldf .ndf
Código fuente: .py .java .cs .cpp .h .js .ts .php .rb .go .rs
Imágenes: .jpg .jpeg .png .gif .bmp .svg .psd .ai .raw .tiff
Audio/Video: .mp3 .mp4 .avi .mkv .mov .wav .flac
Comprimidos: .zip .rar .7z .tar .gz .bz2
Virtualizacion: .vmx .vmdk .vhd .vhdx .qcow2
Backup: .bak .bkf .vbk .vrb .vib
Crypto: .wallet .key .pem .pfx
Email: .pst .ost .eml .msg
CAD: .dwg .dxf .step .stl
Exclusiones (para que el sistema siga operativo)
Directorios excluidos:
C:\Windows\
C:\Program Files\
C:\Program Files (x86)\
C:\ProgramData\Microsoft\
%AppData%\Microsoft\
$Recycle.Bin\
System Volume Information\
Boot\
Extensiones excluidas:
.exe .dll .sys .msi .drv .com .ocx
.lnk .url .ini .inf .bat .cmd
.lock (propia extension del ransomware, evitar doble cifrado)
Archivos excluidos:
ntldr, bootmgr, ntdetect.com
desktop.ini, thumbs.db, iconcache.db
La propia nota de rescate
La exclusión de .exe y .dll es deliberada: si el ransomware cifra los ejecutables del sistema, Windows deja de funcionar. La víctima no puede leer la nota de rescate, no puede abrir un navegador para acceder al portal de pago y no puede pagar. El atacante pierde dinero.
Key management: gestión de claves
Claves por archivo vs claves por sesión
| Estrategia | Descripción | Seguridad | Rendimiento |
|---|---|---|---|
| Clave por archivo | Cada archivo tiene su propia clave AES/ChaCha20 | Máxima: comprometer una clave solo afecta a un archivo | Más lento: más operaciones de generación de claves y cifrado asimétrico |
| Clave por sesión | Una sola clave para todos los archivos de la máquina | Menor: si se extrae la clave de memoria, todos los archivos se descifran | Más rápido: una sola operación asimétrica |
| Clave por directorio | Una clave por cada directorio | Compromiso intermedio | Intermedio |
Las familias profesionales (LockBit, BlackCat, Conti) usan clave por archivo o por bloque de archivos. Las familias amateur a veces usan una sola clave por sesión, lo que las hace vulnerables a extracción de claves de memoria si se actúa rápido.
Limpieza de claves en memoria
Un error crítico es no limpiar las claves de la memoria después de usarlas. Si el ransomware mantiene las claves AES en memoria y un analista puede hacer un dump de memoria (volatility, procdump) antes de que el proceso termine, las claves se pueden recuperar.
Buenas prácticas que implementan las familias sofisticadas:
SecureZeroMemory()en Windows para limpiar buffers de claves- Cifrar las claves en memoria con una master key derivada de la clave de sesión
- Terminar el proceso tras completar el cifrado (no dejar residuos)
- Evitar paginación de memoria con
VirtualLock()para que las claves no se escriban al pagefile
Errores criptográficos que permitieron descifrado
La tabla más valiosa de este artículo para un equipo de respuesta a incidentes:
| Familia | Error criptográfico | Consecuencia | Decryptor disponible |
|---|---|---|---|
| Hive | Keystream de ChaCha20 generado con bug: se podía predecir la clave maestra a partir de claves parciales | FBI infiltró la red 7 meses, distribuyó 1.300+ claves | Sí (KISA, Bitdefender) |
| GandCrab (v1-v5.0.3) | Debilidad en generación de claves RSA permitió derivar la clave privada | Bitdefender publicó decryptor gratuito | Sí (NoMoreRansom) |
| Akira (versiones tempranas) | Uso de std::random_device con seed predecible basado en timestamp | Investigadores podían reproducir las claves si conocían el timestamp de cifrado | Sí (Avast) |
| Maze | IV constante para AES-CBC en algunas versiones | Facilitó análisis y descifrado parcial | Sí (tras disolución del grupo) |
| Babuk (ESXi) | Implementación incorrecta de ECDH permitía derivar shared secret | Decryptor publicado por Avast | Sí (Avast) |
| BlackBasta (nov-dic 2023) | Bug en cifrado de archivos entre 5000 bytes y 1 GB: uso XChaCha20 con keystream predecible por flaw en counter | SRLabs publicó "Black Basta Buster" | Sí (SRLabs, parcheado por el grupo en enero 2024) |
| Conti (tras leaks) | Código fuente filtrado permitió análisis completo; no un bug per se, pero facilitó decryptors | Múltiples decryptors basados en análisis del código | Parcial (depende de la versión) |
| WannaCry | Claves RSA privadas persistían en memoria (no se limpiaban) porque el proceso no terminaba | Herramienta Wannakey extraía primos RSA de memoria antes de reinicio | Sí (en ciertas condiciones, solo XP/7) |
| Petya (original, no NotPetya) | Cifrado Salsa20 del MBR con debilidad en expansión de clave | Clave de descifrado calculable con algoritmo genético | Sí |
Cómo encuentran los investigadores estos errores
Los investigadores de seguridad analizan las implementaciones criptográficas de ransomware buscando estos patrones:
Análisis de IVs/nonces: verificar que cada archivo tiene un IV/nonce único. Si múltiples archivos comparten el mismo valor, el cifrado de stream (CTR, ChaCha20) es vulnerable.
Predicción de PRNG: si las claves se generan con un PRNG no criptográfico (rand(), srand(time(NULL))), conocer el timestamp aproximado de infección permite probar un espacio de claves reducido.
Memory forensics: analizar dumps de memoria buscando claves AES/RSA que no fueron limpiadas. Volatility puede buscar patrones de bloques AES expandidos (key schedule) o estructuras RSA (BIGNUM).
Análisis de entropía: comparar la entropía del archivo cifrado con la del original. Cifrado parcial deja secciones con entropía baja (datos originales) alternadas con secciones de entropía alta (datos cifrados).
Reverse engineering del binario: desensamblar el ransomware para identificar las APIs criptográficas usadas, los parámetros, y posibles errores de lógica. Herramientas como IDA Pro, Ghidra y CAPA automatizan parte de este análisis.
Mapeo MITRE ATT&CK
| Técnica | ID | Descripción en contexto ransomware |
|---|---|---|
| Data Encrypted for Impact | T1486 | La técnica principal: cifrado de archivos para extorsión |
| Inhibit System Recovery | T1490 | Eliminación de shadow copies y deshabilitación de recovery |
| Disk Wipe | T1561 | Algunos ransomware destruyen en vez de cifrar (wipers disfrazados) |
| Data Destruction | T1485 | Destrucción selectiva de backups |
Recursos para análisis de criptografía en ransomware
Para analistas que necesiten evaluar la implementación criptográfica de una muestra:
| Herramienta | Uso |
|---|---|
| CAPA (Mandiant) | Detección automática de capacidades de malware, incluidas APIs criptográficas |
| FindCrypt (IDA plugin) | Identifica constantes criptográficas en binarios (S-boxes AES, constantes de ChaCha20) |
| Crypto Identifier (Ghidra) | Equivalente a FindCrypt para Ghidra |
| Volatility 3 | Extracción de claves criptográficas de memory dumps |
| CyberChef | Pruebas rápidas de descifrado con diferentes algoritmos y parámetros |
| NoMoreRansom | Repositorio de decryptors gratuitos para familias con errores conocidos |
Lo que viene después
Este artículo ha cubierto la teoría y la práctica del cifrado en ransomware. El siguiente artículo de la serie analiza el otro pilar de presión del ransomware moderno: la doble extorsión. Cómo los grupos exfiltran datos antes de cifrar, cómo operan los leak sites en Tor, y qué impacto legal y reputacional tiene para las víctimas la publicación de sus datos.
Fuentes y referencias
- Aumasson, J.P. "Serious Cryptography: A Practical Introduction to Modern Encryption." No Starch Press, 2017.
- Bernstein, D.J. "ChaCha, a variant of Salsa20." SASC 2008.
- Bernstein, D.J. "Curve25519: New Diffie-Hellman Speed Records." PKC 2006.
- KISA (Korea Internet & Security Agency). "Hive Ransomware Decryption: Recovering Files Using a Master Key." 2022.
- SRLabs. "Black Basta Buster: Recovering files encrypted by Black Basta ransomware." 2024.
- Avast Threat Intelligence. "Babuk Ransomware Decryptor." 2021.
- Avast Threat Intelligence. "Akira Ransomware Decryptor." 2023.
- No More Ransom Project. https://www.nomoreransom.org/
- Mandiant. "CAPA: The FLARE Team's Open-Source Tool to Identify Capabilities in Executable Files." 2020.
- Suiche, M. "WannaCry Ransomware: Analysis of Encryption Routine." 2017.
- MITRE ATT&CK. "Data Encrypted for Impact (T1486)." https://attack.mitre.org/techniques/T1486/
- NIST. "Recommendation for Block Cipher Modes of Operation." SP 800-38A.
- The DFIR Report. Multiple ransomware analysis reports. https://thedfirreport.com/
Preguntas frecuentes
Libros recomendados
Artículos relacionados
Anatomía de un Ransomware: Cifrado, Comunicación C2 y Sistema de Pagos
Cadena de Infección de Ransomware: Del Acceso Inicial al Cifrado
Doble Extorsión: Cómo el Ransomware Moderno Roba tus Datos Antes de Cifrarlos
BlackCat/ALPHV: Doble Extorsión y Data Leak Investigation
Conti: De Cobalt Strike a Exfiltración y Cifrado en 72 Horas
LockBit 3.0: Incident Response Completo de Principio a Fin
Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.