Saltearse al contenido

Ofuscación y packing

El malware oculta su lógica real para dificultar el análisis y evadir la detección por firmas. Dos grandes técnicas: la ofuscación (transformar el código/strings para que sean ilegibles pero funcionalmente iguales) y el packing (comprimir/cifrar el ejecutable entero, que solo se descomprime en memoria al ejecutarse). Para el analista, desofuscar y desempacar es el paso previo a entender la muestra; para el defensor, ambas técnicas rompen las firmas estáticas simples.

Packing (empaquetado/cifrado del ejecutable)

Sección titulada «Packing (empaquetado/cifrado del ejecutable)»
# un packer envuelve el binario original: en disco se ve el "stub" + datos cifrados;
# al ejecutarse, el stub descomprime/descifra el código real en memoria y salta a él (OEP)
# señales de packing (estático):
- entropía alta en las secciones (datos cifrados/comprimidos)
- pocos imports (se resuelven en runtime), IAT minúscula
- nombres de sección raros (UPX0, .packed) o secciones RWX
- strings casi inexistentes en estático pero muchas en runtime
# herramientas de detección
Detect It Easy (DIE), PEiD, PEstudio -> identifican el packer
# packers estándar
upx -d muestra.exe # UPX (si no está modificado)
# packers custom/comerciales (VMProtect, Themida, ...) -> dinámico:
1. ejecutar bajo debugger hasta el OEP (tras el desempacado en memoria)
2. volcar el proceso ya desempacado (ver rev-dynamic)
pe-sieve / Scylla / Process Hacker -> dump
3. reconstruir la IAT y analizar el dump estáticamente
# automatizado: sandboxes (CAPE) a menudo dumpean el payload desempacado
control flow flattening aplanar el flujo -> el grafo es ilegible
opaque predicates condiciones siempre V/F que confunden el análisis
dead code / junk instrucciones basura
API hashing en vez de nombres de API, hashes que se resuelven en runtime
-> rompe el análisis por imports (hay que resolver los hashes)
code virtualization un intérprete propio ejecuta bytecode custom (lo más duro)

El API hashing es muy común: el malware no importa VirtualAlloc por nombre (lo cual sería un IOC), sino que calcula un hash del nombre y lo resuelve en runtime, ocultando qué APIs usa al análisis estático.

# strings cifradas/apiladas que se construyen en runtime
# estático: FLOSS las extrae (ver mal-static); o localizar la rutina de descifrado
# dinámico: ejecutar y volcar memoria -> las strings aparecen descifradas
# técnicas: base64, concatenación, reemplazo de caracteres, compresión (Gzip/Deflate),
# invocación indirecta (IEX), variables de entorno, encoding
# desofuscar:
- CyberChef (la navaja suiza: base64, gunzip, XOR, etc. encadenados)
- PowerShell: reemplazar IEX por Write-Output para VER el script en vez de ejecutarlo
- box-js / malware-jail para JavaScript; olevba para VBA
# Script Block Logging (4104) captura el PowerShell ya desofuscado (ver fund-ps)
  • Detección por comportamiento (no por firma estática): la ofuscación/packing rompe firmas, pero el comportamiento en runtime (inyección, red, cifrado) sigue siendo detectable por EDR.
  • AMSI / Script Block Logging: capturan scripts tras desofuscar (el momento clave).
  • Reglas YARA sobre memoria (no solo disco): la muestra desempacada en memoria sí tiene firmas (Reglas YARA).
  • Detección de packers/entropía alta y de API hashing como señales sospechosas.
  • Detectar packing (entropía, pocos imports, DIE/PEiD)
  • Desempacar (UPX -d; o dinámico: OEP + dump)
  • Reconstruir IAT y analizar el dump
  • Identificar ofuscación de código (flattening, API hashing)
  • Resolver API hashing (scripts/plugins)
  • Extraer strings ofuscadas (FLOSS / volcado de memoria)
  • Desofuscar scripts (CyberChef, olevba, Script Block Logging)
  • YARA sobre memoria tras desempacar (Reglas YARA)