Anatomía de una regla: meta, strings y condition
Una regla YARA se lee mejor entera antes de desarmarla. Esta describe la nota de rescate de "LockCR", una familia ficticia inventada para este curso. Mírela un minuto sin preocuparse por los detalles; la mayoría se entiende sola.
Una regla completa
rule LockCR_Nota_Rescate : ransomware nota
{
meta:
author = "Equipo SOC Ejemplo"
description = "Nota de rescate de la familia ficticia LockCR"
date = "2026-10-21"
version = "1"
strings:
$f1 = "sus archivos han sido cifrados" nocase
$f2 = "LEAME_RECUPERAR" ascii wide
$f3 = "lockcr.example" nocase
$id = /ID de victima: [A-F0-9]{16}/
condition:
filesize < 20KB and 2 of ($f*) or $id
}Cabecera
La palabra rule abre la regla, seguida de un nombre único sin espacios. Después de los dos puntos van etiquetas opcionales (ransomware, nota) que ayudan a filtrar resultados. Todo el cuerpo va entre llaves y los comentarios se escriben con //.
meta: la ficha de la regla
La sección meta no cambia el resultado. Guarda datos para las personas: autor, descripción, fecha, versión y, si existe, la referencia al caso. Parece trámite hasta que un día dispara una regla de hace un año sin ficha y nadie sabe si borrarla o escalar.
strings: lo que se busca
Cada patrón tiene un nombre que empieza con $, y hay tres tipos.
Los de texto van entre comillas, con modificadores que cambian cómo se busca: nocase ignora mayúsculas, wide busca el texto con dos bytes por carácter (muy común en ejecutables de Windows), ascii lo busca normal y fullword exige que no esté pegado a otras letras. Si pone wide sin ascii, solo busca la versión de dos bytes; es un olvido frecuente.
Los hexadecimales van entre llaves y sirven para firmas binarias; admiten comodines con ??. Las expresiones regulares van entre barras, como $id en el ejemplo.
$mz = { 4D 5A } // "MZ", inicio de un ejecutable de Windows
$comod = { 6A 40 ?? ?? 00 00 } // ?? acepta cualquier bytecondition: cuándo se cumple
La condición es una expresión lógica que decide si hay coincidencia. Algunas piezas frecuentes:
any of them // cualquiera de los strings
all of ($f*) // todos los que empiezan con $f
2 of ($f1, $f2, $f3) // al menos dos de esa lista
#f1 > 3 // $f1 aparece más de tres veces
$mz at 0 // $mz está justo al inicio del archivo
filesize < 1MB // limita el tamaño
uint16(0) == 0x5A4D // los dos primeros bytes son MZSe combinan con and, or, not y paréntesis. El and se evalúa antes que el or, igual que en casi todos los lenguajes. Yo pongo paréntesis siempre que mezclo los dos, aunque no hagan falta: quien lea la regla después no tiene que acordarse de la precedencia.
Leer la regla del ejemplo en voz alta
Traducir la condición a una frase en español destapa errores que a la vista pasan. La de LockCR dice: "coincide si el archivo pesa menos de 20 KB y contiene al menos dos de las frases que empiezan con f, o si contiene un identificador de víctima de dieciséis caracteres hexadecimales". Al leerla así aparece un detalle: por la precedencia, el límite de tamaño no se aplica al identificador. Si esa no era la intención, la condición necesita paréntesis alrededor del or. En el laboratorio corregirá justamente eso.