YARA es un lenguaje declarativo para describir familias de malware, comportamientos o artefactos mediante patrones de bytes, cadenas y propiedades de archivos. Una regla YARA combina strings (literales, regex, hex) con una conditionexpresiva que decide el match, apoyándose en módulos (p. ej., pe, elf, math, hash). Aquí verás su sintaxis a fondo, prácticas de rendimiento y ejemplos listos para producción.
Anatomía de una regla
Una regla típica define metadatos, patrones (strings) y una condición booleana:
rule EXAMPLE_Minimal {
meta:
author = "Mario"
description = "Ejemplo mínimo"
reference = "interno"
confidence = 80
tags = "loader,windows"
strings:
$mz = { 4D 5A } // firma MZ (PE)
$s1 = "VirtualAlloc" nocase // literal
$re = /cmd\.exe\s*\/c/i // regex
condition:
$mz at 0 and any of ($s*)
}Notas: meta no afecta al match; sirve para trazabilidad. Los patrones se referencian con $nombre. El sufijo at 0ancla el offset.
Patrones: literales, regex y hex
- Literales: modificadores
ascii,wide,nocase,fullword,xor(1-255),base64,base64wide. - Regex: sintaxis PCRE (escapea correctamente
\si tu fuente es JS/TS). - Hex: soporta comodines
??, saltos[n-m]y conjuntos de bytes.
strings:
$url = "http://mal.example" ascii
$wideut = "CreateProcessW" wide fullword
$enc = "API-KEY=" base64
$xorname = "MALWARE" xor(1-255) ascii
$rgx = /powershell\s+-enc\s+[A-Za-z0-9+/=]{20,}/ nocase
$shell = { E8 ?? ?? ?? 68 2E 65 78 65 00 } // call + push ".exe\0"
$jmp = { 6A 40 68 00 30 00 00 [4-20] 68 ?? ?? ?? ?? } // rango variableRendimiento: prioriza literales/hex con buenos “átomos” (subcadenas únicas). Evita wide/xor indiscriminado; úsalo solo cuando sea necesario. Ancla con at o delimita con in (a..b) para reducir búsqueda.
Condiciones expresivas
condition:
// combinadores
all of them and filesize < 8MB and
// conteos
#url >= 1 and 1 of ($shell,$jmp) and
// offsets y ventanas
$mz at 0 and $rgx in (0..filesize) and
// lectura de enteros (LE/BE)
uint32(0) == 0x5A4D and
// llamadas a módulos
pe.is_pe and pe.number_of_sections >= 4Operadores útiles: for any i in (0..N): ( ... ), for all of ($a*) : ( ... ), comparadores con filesize y funciones de módulos.
Módulos clave
import "pe"
import "elf"
import "math"
import "hash"pe:pe.imphash(),pe.imports(dll, func),pe.sections[i].name,pe.sections[i].entropy,pe.is_dll,pe.overlay.offset.elf:elf.type,elf.machine,elf.segments[i].math:math.entropy(offset, size)para ventanas arbitrarias.hash:hash.md5(0, filesize),hash.sha1(...), etc.
Ejemplos prácticos
1) PE sospechoso por secciones y API
import "pe"
import "math"
rule PE_Suspicious_Entropy_And_APIs {
meta:
author = "Mario"
purpose = "Detección genérica de loaders"
tlp = "AMBER"
strings:
$a1 = "VirtualAlloc" ascii nocase fullword
$a2 = "WriteProcessMemory" ascii nocase fullword
$a3 = "CreateRemoteThread" ascii nocase fullword
$mz = { 4D 5A }
condition:
$mz at 0 and
pe.is_pe and
2 of ($a*) and
// alta entropía en alguna sección ejecutable
for any i in (0..pe.number_of_sections - 1) :
( pe.sections[i].characteristics & 0x20000000 /* IMAGE_SCN_MEM_EXECUTE */ and
pe.sections[i].raw_data_size > 0 and
math.entropy(pe.sections[i].raw_data_offset, pe.sections[i].raw_data_size) > 7.2 )
}2) Patrón XOR genérico para payloads
rule XOR_Encoded_Marker {
meta:
description = "Detecta marcador 'MZ' u otros literales bajo XOR"
strings:
$x = "ThisIsASecret" xor(1-255) ascii
condition:
#x >= 1 and filesize < 20MB
}3) Uso de imports específicos
import "pe"
rule PE_Specific_Imports {
condition:
pe.is_pe and
pe.imports("KERNEL32.dll", "VirtualAlloc") and
pe.imports("ADVAPI32.dll", "CryptEncrypt")
}Reglas auxiliares, etiquetas y alcance
Usa private para reglas helpers que no quieres reportar, y etiquetas (p. ej. : loader windows) para agrupar. Evita reglas excesivamente genéricas que disparen falsos positivos.
private rule HELP_HighEntropyExec {
import "pe"
import "math"
condition:
pe.is_pe and
for any i in (0..pe.number_of_sections - 1) :
( (pe.sections[i].characteristics & 0x20000000) != 0 and
pe.sections[i].raw_data_size > 0 and
math.entropy(pe.sections[i].raw_data_offset, pe.sections[i].raw_data_size) > 7.2 )
}
rule FAMILY_Loader_Alpha : loader windows {
meta: family = "Alpha"
strings: $s = "AlphaLoader" ascii
condition: $s and HELP_HighEntropyExec
}Variables externas y parametrización
Puedes pasar variables con -d desde CLI y usarlas en condiciones:
rule SIZE_Greater_Than {
condition: filesize > MIN_SIZE
}yara -d MIN_SIZE=1048576 rules.yar /ruta/objetivosRendimiento y calidad
- Prefiere pocos patrones fuertes a muchos débiles; evita
.*en regex. - Usa
at, ventanasin (start..end)y límites defilesize. - Desactiva
wide/xor/base64si no aportan señal real. - Valida con corpus limpio/sucio y mide tasa de FP/FN.
Pruebas con CLI
# Recursivo con strings que disparan
yara -r -s rules.yar /ruta/muestras
# Con etiquetas y nombres de reglas
yara -r -m -g rules.yar /ruta/muestras
# Mostrar tiempos y profiling (si tu build lo soporta)
yara -r --print-stats rules.yar /ruta/muestrasIntegra YARA en pipelines de CI (artefactos, contenedores) y en tu EDR/NSM para inspección bajo demanda. Versiona reglas y exige code review como cualquier pieza de software.
La clave de YARA no es coleccionar cadenas, sino capturar invariantes de familia/actividad: estructuras PE, secuencias de API, distribución de entropía, offsets característicos y rasgos del pipeline de compilación. Con reglas pequeñas, explicables y medibles, la detección escala.



