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.

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.
| Modificador | Efecto | Ejemplo |
|---|---|---|
| nocase | Búsqueda case-insensitive | "cmd" nocase (coincide CMD, Cmd, etc.) |
| wide | Busca en codificación UTF-16LE | "password" wide (P.a.s.s.w.o.r.d.) |
| ascii | Busca en ASCII (por defecto) | "password" ascii wide (busca ambos) |
| fullword | Solo si es palabra completa | "run" fullword (no coincide "running") |
| xor | Busca XOR con rango de claves | "http" xor(0x01-0xff) |
| base64 | Busca codificado en base64 | "password" base64 |
| private | La 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ón | Qué hace | Uso forense |
|---|---|---|
| pe.imports(dll, func) | Verifica si el PE importa una función | Detectar imports de inyección |
| pe.exports(func) | Verifica si exporta una función | Detectar DLLs maliciosas |
| pe.imphash() | Hash de la tabla de imports | Agrupar variantes de la misma familia |
| pe.number_of_sections | Cantidad de secciones | Packers añaden secciones extra |
| pe.sections[i].name | Nombre de una sección | Nombres inusuales (UPX0, .ndata) |
| pe.timestamp | Timestamp de compilación | Correlacionar con campañas |
| pe.entry_point | Entry point relativo | Fuera 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.

| Plataforma | Tipo | Cobertura | Acceso |
|---|---|---|---|
| VirusTotal Retrohunt | Comercial | Miles de millones de archivos | VT Enterprise (pago) |
| Hybrid Analysis | Gratuito limitado | Millones de muestras analizadas | API gratuita con límites |
| MalwareBazaar | Gratuito | Cientos de miles de muestras | API abierta, descarga de muestras |
| Repositorio interno | Privado | Lo que tu organización haya recopilado | MISP + almacenamiento local |
| YARA-CI | Automatizado | Muestras nuevas que llegan a tu pipeline | Integració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) == 0x5A4Dfunciona porque x86 es little-endian. En archivos big-endian (ELF, Mach-O) hay que ajustar. - Escribir condiciones con
any of themsin 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.