Aprende › Cloud, APIs, forense y más

Reglas YARA avanzadas: detección de malware families y retrohunting

· 10 min de lectura

YARA va mucho más allá de buscar strings: módulos PE/ELF, condiciones con math y hash, modificadores xor y base64, retrohunting en VirusTotal. Aprende a escribir reglas de producción que detecten familias de malware sin falsos positivos.

YARA es el lenguaje de facto para clasificar y detectar malware. Cada regla define un conjunto de patrones (strings de texto, secuencias hexadecimales, expresiones regulares) y una condición lógica que determina cuándo un archivo o proceso coincide. Las reglas básicas — buscar una cadena y verificar el magic number — funcionan para casos simples, pero el malware moderno ofusca strings, usa codificación XOR, empaqueta ejecutables, cambia nombres entre variantes y emplea técnicas anti-análisis que hacen inútiles las reglas ingenuas.

Las reglas avanzadas de YARA aprovechan módulos como pe, elf, math y hash para inspeccionar la estructura interna de los binarios, calcular entropía de secciones, verificar imports y exports, y combinar condiciones que solo coinciden con familias de malware específicas sin generar falsos positivos en software legítimo. Además, la capacidad de retrohunting (buscar retrospectivamente en repositorios masivos de muestras como VirusTotal) permite descubrir variantes que no se conocían cuando se escribió la regla.

Es la quinta lección de la Tanda 8. Asume que conoces la sintaxis básica de YARA (rule, strings, condition). Si no, la documentación oficial cubre los fundamentos en pocos minutos. Aquí vamos directo a las técnicas avanzadas que usan los analistas profesionales.

Usa YARA solo para analizar muestras obtenidas legalmente y en entornos controlados. No distribuyas muestras de malware sin seguir los protocolos de tu organización. Las reglas YARA que compartas no deben contener información que identifique víctimas.

Qué es YARA y por qué importa#

YARA fue creado por Victor Alvarez en VirusTotal para clasificar muestras de malware. Hoy lo usan prácticamente todos los equipos de seguridad del mundo: antivirus, EDRs, sandboxes, plataformas de threat intelligence y analistas individuales.

Estructura de una regla YARA: sección meta (metadatos descriptivos), sección strings (patrones a buscar), sección condition (lógica booleana)
Estructura de una regla YARA: sección meta (metadatos descriptivos), sección strings (patrones a buscar), sección condition (lógica booleana)

Una regla YARA básica busca strings en archivos y devuelve si coincide o no. Pero el poder real está en las reglas avanzadas que combinan múltiples señales: estructura del PE, imports sospechosos, entropía alta en secciones, strings ofuscadas con XOR, y condiciones que requieren la presencia simultánea de varios indicadores. Eso reduce los falsos positivos a niveles aceptables para producción.

YARA se ejecuta sobre archivos en disco, pero también se integra con Volatility (plugin yarascan) para buscar en dumps de memoria, con MISP para enriquecer eventos con detecciones, y con OSQuery para buscar en endpoints a escala.

Anatomía de una regla YARA#

Toda regla tiene tres secciones: meta, strings y condition.

rule Emotet_Loader_2024 {
    meta:
        author = "analista-whoami"
        date = "2024-03-15"
        description = "Detecta variantes del loader de Emotet Q1 2024"
        reference = "https://malpedia.caad.fkie.fraunhofer.de/details/win.emotet"
        tlp = "WHITE"
        hash = "a1b2c3d4e5f6..."

    strings:
        $mz = { 4D 5A }                           // Magic number PE
        $s1 = "RunDLL32" ascii nocase              // Ejecución vía rundll32
        $s2 = "regsvr32" ascii nocase              // Alternativa de ejecución
        $h1 = { 8B ?? ?? 89 ?? ?? E8 ?? ?? ?? ?? 85 C0 } // Patrón de llamada
        $xor1 = "http" xor(0x01-0xff)             // URL ofuscada con XOR
        $b64 = "aHR0c" base64                      // "http" en base64

    condition:
        $mz at 0 and
        filesize < 500KB and
        (2 of ($s*) or $xor1 or $b64) and
        $h1
}

meta#

Metadatos descriptivos. No afectan la detección pero son esenciales para documentar quién escribió la regla, cuándo, para qué malware, con qué referencias y qué muestras se usaron para validar.

strings#

Patrones a buscar en el archivo. Tres tipos: texto ("cadena"), hexadecimal ({ 4D 5A }), regex (/patrón/). Cada string se identifica con un nombre que empieza con $.

condition#

Lógica booleana que combina strings, tamaños, offsets, funciones de módulos y operadores. Esto es donde está la potencia real.

Modificadores y condiciones avanzadas#

Los modificadores transforman cómo YARA busca las strings.

ModificadorEfectoEjemplo
nocaseBúsqueda case-insensitive"cmd" nocase (coincide CMD, Cmd, etc.)
wideBusca en codificación UTF-16LE"password" wide (P.a.s.s.w.o.r.d.)
asciiBusca en ASCII (por defecto)"password" ascii wide (busca ambos)
fullwordSolo si es palabra completa"run" fullword (no coincide "running")
xorBusca XOR con rango de claves"http" xor(0x01-0xff)
base64Busca codificado en base64"password" base64
privateLa string no aparece en el output$internal = "algo" private

Condiciones con operadores avanzados#

rule Condiciones_Avanzadas {
    strings:
        $s1 = "CreateRemoteThread"
        $s2 = "VirtualAllocEx"
        $s3 = "WriteProcessMemory"
        $s4 = "NtUnmapViewOfSection"
        $s5 = "ResumeThread"

    condition:
        uint16(0) == 0x5A4D and            // Es un PE
        filesize < 1MB and                  // Tamaño razonable
        3 of ($s*) and                      // Al menos 3 de las 5 strings
        for any i in (1..#s1) : (           // Para cualquier coincidencia de $s1
            @s1[i] < @s2[i] + 0x100        // $s1 está cerca de $s2 en el archivo
        )
}
  • uint16(0): lee 2 bytes en el offset 0.
  • #s1: cuenta de coincidencias de $s1.
  • @s1[i]: offset de la i-ésima coincidencia.
  • for any/all i in (range): iteración sobre coincidencias.

Cuándo escribir una regla avanzada#

  • Tienes una muestra de malware y quieres detectar toda la familia (variantes pasadas y futuras).
  • Las strings simples producen falsos positivos en software legítimo (ejemplo: "CreateRemoteThread" aparece en herramientas de debugging legítimas).
  • El malware ofusca sus strings con XOR, base64, o las fragmenta en varias variables.
  • Necesitas combinar indicadores estructurales (PE imports, secciones, entropía) con strings.
  • Quieres hacer retrohunting: buscar muestras relacionadas en repositorios masivos.

Módulos YARA: pe, elf, math, hash#

Los módulos extienden YARA con funciones especializadas.

Módulo pe#

Inspecciona la estructura de ejecutables PE (Windows).

import "pe"

rule PE_Suspicious_Imports {
    condition:
        pe.imports("kernel32.dll", "VirtualAllocEx") and
        pe.imports("kernel32.dll", "WriteProcessMemory") and
        pe.imports("kernel32.dll", "CreateRemoteThread") and
        pe.number_of_sections < 4 and
        pe.timestamp > 1704067200 and       // Compilado después de 2024-01-01
        pe.timestamp < 1735689600            // Compilado antes de 2025-01-01
}

Funciones clave del módulo pe:

FunciónQué haceUso forense
pe.imports(dll, func)Verifica si el PE importa una funciónDetectar imports de inyección
pe.exports(func)Verifica si exporta una funciónDetectar DLLs maliciosas
pe.imphash()Hash de la tabla de importsAgrupar variantes de la misma familia
pe.number_of_sectionsCantidad de seccionesPackers añaden secciones extra
pe.sections[i].nameNombre de una secciónNombres inusuales (UPX0, .ndata)
pe.timestampTimestamp de compilaciónCorrelacionar con campañas
pe.entry_pointEntry point relativoFuera de .text = packed

Módulo math#

Calcula estadísticas sobre porciones del archivo.

import "math"

rule High_Entropy_Section {
    condition:
        for any section in pe.sections : (
            math.entropy(section.raw_data_offset, section.raw_data_size) > 7.5
        )
        // Entropía > 7.5 indica datos cifrados o comprimidos (packer, payload)
}

Módulo hash#

Calcula hashes de porciones específicas del archivo.

import "hash"

rule Known_Resource_Hash {
    condition:
        // Hash SHA-256 de los primeros 1024 bytes
        hash.sha256(0, 1024) == "a1b2c3d4..."
}

Escribir una regla para una familia de malware#

El proceso de escribir una regla de producción para una familia de malware sigue un flujo sistemático.

Paso 1: recopilar muestras#

Necesitas varias muestras de la misma familia (mínimo 3-5). Puentes: VirusTotal, MalwareBazaar, Hybrid Analysis, MISP.

Paso 2: análisis estático#

# Extraer strings comunes entre muestras
strings -a muestra1.exe > strings1.txt
strings -a muestra2.exe > strings2.txt
strings -a muestra3.exe > strings3.txt

# Encontrar strings compartidas
comm -12 <(sort strings1.txt) <(sort strings2.txt) | comm -12 - <(sort strings3.txt) > comunes.txt

Paso 3: identificar patrones hexadecimales#

# Buscar secuencias de bytes compartidas con ssdeep (fuzzy hashing)
ssdeep -l muestra*.exe

# Comparar secciones con radiff2 (radare2)
radiff2 -s muestra1.exe muestra2.exe

Paso 4: verificar imports con pefile#

import pefile

pe = pefile.PE("muestra1.exe")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
    dll_name = entry.dll.decode()
    for func in entry.imports:
        if func.name:
            print(f"{dll_name}: {func.name.decode()}")

Paso 5: escribir la regla#

import "pe"
import "math"

rule MiMalware_Family_2024 {
    meta:
        author = "analista-whoami"
        date = "2024-03-15"
        description = "Detecta la familia MiMalware (Q1 2024)"
        reference = "https://..."

    strings:
        $unique1 = { 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 ?? E8 }
        $unique2 = "config.dat" ascii
        $mutex = "Global\\MiMalware_" ascii
        $c2_pattern = /https?:\/\/[a-z0-9]{8,12}\.(xyz|top|club)/

    condition:
        uint16(0) == 0x5A4D and
        filesize < 2MB and
        pe.imphash() == "a1b2c3d4e5f6..." or (
            2 of ($unique*, $mutex) and
            $c2_pattern and
            pe.imports("kernel32.dll", "VirtualAlloc") and
            math.entropy(pe.sections[0].raw_data_offset, pe.sections[0].raw_data_size) > 6.5
        )
}

Paso 6: testear contra goodware#

# Escanear software legítimo para buscar falsos positivos
yara -r mi-regla.yar /usr/bin/
yara -r mi-regla.yar /Windows/System32/
yara -r mi-regla.yar /corpus-goodware/

# Si hay coincidencias, ajustar la condición (más restrictiva)

Retrohunting: buscar en el pasado#

El retrohunting es el proceso de aplicar una regla YARA contra un repositorio masivo de archivos históricos para encontrar muestras que no se conocían cuando se escribió la regla.

Flujo de retrohunting: analizar muestra, identificar patrones, escribir regla, testear falsos positivos, lanzar retrohunt, analizar coincidencias
Flujo de retrohunting: analizar muestra, identificar patrones, escribir regla, testear falsos positivos, lanzar retrohunt, analizar coincidencias
PlataformaTipoCoberturaAcceso
VirusTotal RetrohuntComercialMiles de millones de archivosVT Enterprise (pago)
Hybrid AnalysisGratuito limitadoMillones de muestras analizadasAPI gratuita con límites
MalwareBazaarGratuitoCientos de miles de muestrasAPI abierta, descarga de muestras
Repositorio internoPrivadoLo que tu organización haya recopiladoMISP + almacenamiento local
YARA-CIAutomatizadoMuestras nuevas que llegan a tu pipelineIntegración con MISP o sandbox

Retrohunt en VirusTotal#

# Crear un ruleset de hunting en VT
# (requiere VT Enterprise o VT Intelligence)
vt hunting ruleset create mi-regla.yar --name "MiMalware Q1 2024"

# Lanzar retrohunt (busca en el histórico completo)
vt hunting retrohunt create mi-regla.yar

# Listar notificaciones (muestras que coincidieron)
vt hunting notifications list

Retrohunt en repositorio local#

# Escanear un directorio con miles de muestras
yara -r -s mi-regla.yar /malware-repo/

# Con múltiples reglas
yara -r -s todas-las-reglas.yar /malware-repo/ > resultados.txt

# Con timeout por archivo (evitar cuelgues con archivos grandes)
yara -r -t 30 mi-regla.yar /malware-repo/

Herramientas complementarias#

yarGen#

yarGen genera reglas YARA automáticamente a partir de muestras de malware. Compara las strings del malware contra una base de datos de goodware (strings de Windows legítimo) y crea una regla con las strings que son únicas del malware.

# Generar regla automática
python yarGen.py -m /muestras-malware/ -o regla-generada.yar

# Resultado: regla con strings seleccionadas y condition básica
# Siempre revisar y ajustar manualmente

YARA-X#

YARA-X es la reescritura oficial de YARA en Rust por VirusTotal. Más rápido, más seguro (memory-safe), con mejor manejo de errores y warnings. Está diseñado para reemplazar a YARA eventualmente.

# Instalar YARA-X
cargo install yara-x

# Escanear (misma sintaxis de reglas)
yr scan mi-regla.yar archivo.exe

# Chequear reglas sin ejecutar
yr check mi-regla.yar

Integración con Volatility#

# Buscar en un dump de memoria con Volatility 3
vol -f dump.raw windows.yarascan --yara-file mi-regla.yar

# Buscar en la memoria de un proceso específico
vol -f dump.raw windows.yarascan --yara-file mi-regla.yar --pid 4120

Integración con MISP#

MISP puede almacenar reglas YARA como atributos de tipo yara dentro de eventos. Cuando una nueva muestra llega al sandbox de tu organización, se escanea contra todas las reglas YARA de MISP automáticamente.

Errores comunes al escribir reglas YARA#

  • Usar solo strings de texto genéricas (como "http://" o "cmd.exe") sin combinar con condiciones estructurales: genera miles de falsos positivos.
  • No testear contra goodware antes de poner la regla en producción.
  • Reglas demasiado específicas que solo detectan una muestra exacta y no variantes de la familia.
  • Ignorar el rendimiento: reglas con muchas expresiones regulares complejas o wildcards hexadecimales extensos ralentizan el escaneo dramáticamente.
  • No versionar las reglas: cuando modificas una regla, pierde trazabilidad si no tienes control de versiones.
  • Olvidar el meta block: sin author, date, description y reference, nadie sabe por qué existe la regla.
  • No considerar el endianness: uint16(0) == 0x5A4D funciona porque x86 es little-endian. En archivos big-endian (ELF, Mach-O) hay que ajustar.
  • Escribir condiciones con any of them sin restricción de filesize: coincidirá con archivos enormes que casualmente contengan una string.

Preguntas frecuentes#

¿Cuántas strings necesita una buena regla?#

No hay número mágico. Una regla puede funcionar con una sola string hexadecimal muy específica (un opcode único del malware) o necesitar 10 strings combinadas. Lo que importa es la tasa de falsos positivos: si con una string y condiciones estructurales la regla no produce FP en tu corpus de goodware, es suficiente.

¿YARA puede detectar malware empaquetado?#

Depende. Si el packer cifra completamente el payload, las strings del malware no son visibles y la regla no coincidirá. Pero puedes detectar el packer (UPX, Themida, VMProtect tienen firmas conocidas) y generar una alerta de "binario empaquetado sospechoso". Otra opción: escanear después de la ejecución en sandbox, cuando el malware se desempaqueta en memoria.

¿Qué diferencia hay entre YARA y Sigma?#

YARA opera sobre archivos y memoria (malware, binarios, documentos). Sigma opera sobre logs (eventos de Windows, Sysmon, Zeek, Suricata). Son complementarios: YARA detecta el qué (el archivo malicioso), Sigma detecta el cómo (el comportamiento en los logs).

¿Dónde encuentro reglas YARA de la comunidad?#

Los repositorios principales son YARA-Rules (GitHub), Florian Roth's signature-base, Elastic protections-artifacts, ESET malware-ioc, y las reglas embebidas en eventos de MISP y OTX. Siempre evalúa las reglas antes de ponerlas en producción: las de comunidades grandes suelen estar bien testeadas, pero las de repositorios individuales pueden tener falsos positivos.

¿YARA-X reemplaza a YARA?#

Eventualmente, sí. YARA-X es el sucesor oficial, desarrollado por el mismo equipo en VirusTotal. Soporta las mismas reglas con mejoras. Pero YARA clásico sigue siendo la versión dominante en producción y la que integran la mayoría de herramientas. La migración será gradual.

¿Cómo mido el rendimiento de mis reglas?#

YARA tiene un modo de profiling que muestra cuánto tarda cada regla. Las reglas con muchas expresiones regulares o wildcards largos ({ ?? ?? ?? ?? ?? } de muchos bytes) son las más lentas. El módulo pe es más eficiente que buscar strings de imports porque accede directamente a la estructura del PE.

Resumen#

  • YARA es el estándar para detectar y clasificar malware mediante patrones en archivos y memoria.
  • Las reglas avanzadas combinan strings (texto, hex, regex) con módulos (pe, math, hash) y condiciones booleanas complejas.
  • Modificadores como xor, base64, wide y nocase permiten detectar strings ofuscadas.
  • El módulo pe inspecciona imports, exports, secciones, timestamps e imphash de ejecutables Windows.
  • El retrohunting aplica reglas a repositorios históricos para descubrir variantes no conocidas.
  • Siempre testear contra goodware antes de poner una regla en producción.

Fuentes y lecturas recomendadas#

Practícalo en estos laboratorios

Ver todos los laboratorios de esta categoría