IntermedioYARAmalware detectionCobalt StrikehuntingDetection Engineering

Reglas YARA: Anatomía, Patrones y Tu Primera Regla de Detección

Guía completa de YARA rules: sintaxis, strings (text, hex, regex), conditions, módulos (PE, ELF, math, hash), metadata. Casos prácticos: detectar Cobalt Strike beacon, identificar packers, y hunting con YARA en VirusTotal.

MalwareIntel Research··19 min lectura
Serie: Detection Engineering — Parte 3

YARA es el bisturí del analista de malware

Si Sigma es el lenguaje universal para detectar comportamientos en logs, YARA es el lenguaje universal para detectar malware en ficheros. Cada vez que un analista examina un binario sospechoso, un documento Office con macros, o un script PowerShell ofuscado, YARA es la herramienta que permite escribir una firma precisa que diga: "este fichero contiene exactamente estos patrones, en esta combinación, bajo estas condiciones".

YARA no es un antivirus. No ejecuta nada. No descompila nada. Lee bytes, aplica patrones, y dice "match" o "no match". Esa simplicidad es su fortaleza: funciona en cualquier contexto, desde un script de respuesta a incidentes hasta un pipeline de threat hunting a escala en VirusTotal.

¿Qué es YARA? Origen y ecosistema

YARA fue creada por Victor Manuel Alvarez en 2008 mientras trabajaba en VirusTotal (adquirida por Google en 2012). El nombre es un acrónimo recursivo: Yet Another Ridiculous Acronym. A pesar del nombre, YARA se convirtió en el estándar de facto para la clasificación de malware por patrones.

Dónde se usa YARA hoy

ContextoHerramientasUso
Threat HuntingVirusTotal Hunting, RetrohuntBuscar samples nuevos y retroactivos
Incident ResponseLoki, Thor, FenrirEscanear endpoints buscando IOCs
EDR/XDRCrowdStrike Falcon, SentinelOneReglas custom de detección
SandboxANY.RUN, CAPE, CuckooClasificar samples post-ejecución
Threat IntelMISP, OpenCTI, YETICompartir firmas entre equipos
CI/CD Securityyara-ci, pre-commit hooksDetectar código malicioso en repos
Mail GatewayFiltrado de adjuntosBloquear documentos con macros maliciosas

YARA vs otras herramientas de detección

YARA:    matchea FICHEROS (binarios, docs, scripts, memoria)
Sigma:   matchea EVENTOS/LOGS (process creation, network, registry)
Snort:   matchea TRÁFICO DE RED (paquetes, payloads)
Suricata: matchea TRÁFICO DE RED (más potente que Snort)

YARA + Sigma = cobertura completa: detectas el artefacto Y el comportamiento

Anatomía de una regla YARA

Toda regla YARA tiene la misma estructura. No hay excepciones.

rule NombreDeLaRegla : tag1 tag2
{
    meta:
        author = "MalwareIntel Research"
        description = "Detecta X basándose en Y"
        date = "2026-06-05"
        reference = "https://fuente.original/report"

    strings:
        $texto1 = "cadena de texto"
        $hex1 = { 4D 5A 90 00 }
        $regex1 = /patr[oó]n\s+regex/

    condition:
        uint16(0) == 0x5A4D and
        filesize < 500KB and
        2 of ($texto*, $hex*) and
        $regex1
}

Desglose de cada sección

SecciónObligatoriaFunción
rule NombreDeLaReglaSiIdentificador único. Solo alfanuméricos y _. No puede empezar por número
: tag1 tag2NoEtiquetas para filtrar reglas (ej: apt, ransomware, loader)
meta:NoMetadatos descriptivos. No afectan al matching
strings:NoPatrones a buscar en el fichero
condition:SiLógica booleana que determina si hay match

La sección condition es la única obligatoria junto con el nombre. Una regla válida minima es:

rule MatchTodo
{
    condition:
        true
}

Esa regla matchea cualquier fichero. No es útil, pero ilustra la estructura.

Strings: tres tipos de patrones

YARA soporta tres tipos de strings. Cada uno tiene su sintaxis y sus modificadores.

1. Text strings (cadenas de texto)

Buscan secuencias de caracteres ASCII o Unicode en el fichero.

strings:
    $s1 = "cmd.exe /c"
    $s2 = "powershell -enc"
    $s3 = "CreateRemoteThread"
    $s4 = "http://malicious.domain/beacon"

Modificadores de text strings

ModificadorEfectoEjemplo
nocaseIgnora mayúsculas/minúsculas$s1 = "cmd.exe" nocase
wideBusca en encoding UTF-16LE (cada char ocupa 2 bytes)$s1 = "password" wide
asciiBusca en ASCII (por defecto)$s1 = "password" ascii
wide asciiBusca en ambos encodings$s1 = "password" wide ascii
fullwordSolo matchea si está delimitado por caracteres no alfanuméricos$s1 = "evil" fullword
xorBusca con XOR aplicado (todas las keys 0x00-0xFF)$s1 = "This program" xor
xor(0x01-0xFF)XOR con rango de keys específico$s1 = "password" xor(0x01-0x0F)
base64Busca la string en las 3 variantes de offset base64$s1 = "admin" base64
privateNo aparece en el output, solo se usa en condition$s1 = "interno" private

El modificador wide es fundamental para malware en Windows. Muchas APIs de Windows usan strings UTF-16LE, donde "cmd.exe" se almacena como c\x00m\x00d\x00.\x00e\x00x\x00e\x00. Sin wide, YARA no lo encontraría.

2. Hex strings (patrones hexadecimales)

Buscan secuencias exactas de bytes. Son imprescindibles para matchear código máquina, cabeceras de fichero, y payloads binarios.

strings:
    // Cabecera PE (MZ)
    $mz = { 4D 5A }

    // Secuencia exacta de opcodes x86
    $shellcode = { 6A 40 68 00 10 00 00 6A 00 }

    // Con wildcards: ?? matchea cualquier byte
    $pattern = { 4D 5A ?? ?? ?? ?? ?? ?? 50 45 }

    // Con jumps: [min-max] bytes de separación
    $jump = { 4D 5A [4-8] 50 45 00 00 }

    // Jump sin límite superior
    $wide_jump = { E8 [0-100] C3 }

    // Alternativas con paréntesis y pipes
    $alt = { 4D 5A ( 90 00 | 00 00 | 50 00 ) }

    // Nibble wildcards: ? matchea medio byte (4 bits)
    $nibble = { 4D 5? }

Wildcards y jumps explicados

??        → cualquier byte (0x00-0xFF)
?A        → nibble alto variable, nibble bajo 0xA (0x0A, 0x1A, 0x2A...)
[4]       → exactamente 4 bytes de cualquier valor
[4-8]     → entre 4 y 8 bytes de cualquier valor
[0-100]   → entre 0 y 100 bytes (cuidado con performance)
(AA|BB)   → byte 0xAA o byte 0xBB en esa posición

Los jumps son especialmente útiles para patrones que varían entre versiones de un mismo malware. Por ejemplo, un C2 beacon que mantiene la misma estructura pero cambia offsets entre compilaciones.

3. Regex (expresiones regulares)

YARA soporta un subconjunto de PCRE (Perl Compatible Regular Expressions). Las regex van delimitadas por /.

strings:
    // URL con dominio variable
    $url = /https?:\/\/[a-z0-9\-\.]+\.(xyz|top|tk|ml)\/[a-z0-9]{8,}/

    // User-Agent sospechoso
    $ua = /User-Agent:\s*Mozilla\/[45]\.0\s+\(compatible;\s*MSIE\s+[6-9]/

    // Base64 de longitud sospechosa
    $b64 = /[A-Za-z0-9+\/]{100,}={0,2}/

    // Registry key de persistencia
    $reg = /HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run/i

    // PowerShell encoded command
    $ps = /powershell[^;]{0,30}-e(nc|ncodedcommand)/i

Modificadores de regex

ModificadorEfecto
/iCase insensitive
/sEl punto . matchea también newlines
wideBusca en UTF-16LE
asciiBusca en ASCII
fullwordSolo matchea como palabra completa

Las regex en YARA son más lentas que text strings y hex strings. Usarlas solo cuando los otros tipos no son suficientes.

Conditions: la lógica de detección

La sección condition determina si un fichero matchea la regla. Usa operadores booleanos, funciones sobre strings, y funciones sobre el fichero.

Operadores booleanos

condition:
    // AND: todas deben cumplirse
    $s1 and $s2 and $s3

    // OR: al menos una
    $s1 or $s2

    // NOT: negación
    $s1 and not $s2

    // Paréntesis para agrupar
    ($s1 or $s2) and $s3

Conteo y cuantificadores

condition:
    // Al menos 2 de las strings definidas
    2 of ($s*)

    // Todas las strings que empiezan por $api_
    all of ($api_*)

    // Cualquiera de las strings
    any of them

    // Exactamente 3 de un conjunto
    3 of ($s1, $s2, $s3, $s4, $s5)

    // Número de ocurrencias de una string
    #s1 > 5    // $s1 aparece más de 5 veces

Funciones sobre el fichero

condition:
    // Tamaño del fichero
    filesize < 500KB
    filesize > 1MB and filesize < 10MB

    // Primeros bytes del fichero (magic bytes)
    uint16(0) == 0x5A4D                    // PE file (MZ header)
    uint32(0) == 0x464C457F                // ELF file
    uint32(0) == 0x04034B50                // ZIP file

    // Offset: string en posición específica
    $mz at 0                               // $mz debe estar en offset 0

    // Rango: string dentro de un rango
    $s1 in (0..1024)                       // $s1 en los primeros 1024 bytes

    // Entrypoint (solo PE y ELF)
    $code at entrypoint                    // código en el entry point
    $s1 in (entrypoint..entrypoint + 100)  // primeros 100 bytes desde EP

Expresiones for

Las expresiones for permiten iterar sobre ocurrencias de strings o sobre rangos.

condition:
    // Para cada ocurrencia de $s1, verificar que está en los primeros 1024 bytes
    for all i in (1..#s1) : (@s1[i] < 1024)

    // Al menos una ocurrencia de $s1 seguida de $s2 en los 100 bytes siguientes
    for any i in (1..#s1) : (
        for any j in (1..#s2) : (
            @s2[j] > @s1[i] and @s2[j] < @s1[i] + 100
        )
    )

Donde #s1 es el número de ocurrencias, @s1[i] es el offset de la i-esima ocurrencia, y !s1[i] es la longitud de la i-esima ocurrencia.

Metadata: documentar para compartir

La sección meta no afecta al matching, pero es fundamental para la operativa de un equipo de detección. Sin metadata, una regla que matchea no sirve: nadie sabe qué hacer con el resultado.

meta:
    // Obligatorios (convención de la comunidad)
    author = "MalwareIntel Research"
    description = "Detecta Cobalt Strike beacon con configuración por defecto"
    date = "2026-06-05"
    reference = "https://malwareintel.es/blog/cobalt-strike-analysis"

    // Clasificación
    tlp = "WHITE"
    mitre_att_ck = "T1071.001, T1059.001"
    malware_family = "Cobalt Strike"
    malware_type = "C2 Framework"
    actor = ""

    // Calidad
    hash1 = "a1b2c3d4e5f6..."
    hash2 = "f6e5d4c3b2a1..."
    score = 75
    quality = "production"
    false_positive_rate = "low"
    last_modified = "2026-06-05"

    // Contexto operativo
    severity = "critical"
    in_the_wild = true
    source = "internal_research"

Convención de metadatos en MalwareIntel

CampoTipoDescripción
authorstringAutor o equipo
descriptionstringQué detecta y cómo
datestringFecha de creación (YYYY-MM-DD)
referencestringURL del análisis o report
tlpstringTraffic Light Protocol (WHITE/GREEN/AMBER/RED)
mitre_att_ckstringTécnicas ATT&CK relacionadas
hash1..hashNstringHashes de samples de referencia
scoreintegerConfianza de la regla (0-100)

Módulos: potencia extendida

Los módulos de YARA extienden la funcionalidad base con parsers especializados. Los más usados en análisis de malware:

Módulo PE

El módulo pe parsea la cabecera PE (Portable Executable) de Windows. Es el módulo más importante para análisis de malware.

import "pe"

rule SuspiciousPE
{
    condition:
        // Timestamp de compilación en el futuro
        pe.timestamp > 1900000000

        // Menos de 3 secciones (posible packer)
        pe.number_of_sections < 3

        // Importa función sospechosa
        pe.imports("kernel32.dll", "VirtualAllocEx")

        // Entry point en sección diferente a .text
        not pe.sections[pe.section_index(pe.entry_point)].name startswith ".text"

        // Overlay presente (datos después de la última sección)
        pe.overlay.size > 0

        // Firmado con certificado expirado o inválido
        pe.number_of_signatures > 0 and
        not pe.signatures[0].verified
}

Funciones PE más usadas

FunciónUso
pe.imports("dll", "func")Verifica imports por nombre
pe.exports("func")Verifica exports
pe.sections[i].nameNombre de sección
pe.sections[i].characteristicsFlags de sección (RWX)
pe.entry_pointOffset del entry point
pe.timestampTimestamp de compilación
pe.number_of_resourcesRecursos embebidos
pe.rich_signature.keyRich header XOR key
pe.imphash()Import hash (clasificación rápida)

Módulo ELF

Equivalente al módulo PE para binarios Linux.

import "elf"

rule SuspiciousELF
{
    condition:
        elf.type == elf.ET_EXEC and
        elf.number_of_sections < 5 and
        elf.entry_point != 0
}

Módulo math

Calcula propiedades estadísticas del fichero. La entropía es especialmente útil para detectar ofuscación y cifrado.

import "math"

rule HighEntropySection
{
    condition:
        // Entropía global alta (posible packing/cifrado)
        math.entropy(0, filesize) > 7.5

        // O entropía alta en los primeros 1024 bytes
        // math.entropy(0, 1024) > 7.0
}
Valor de entropíaInterpretación
0-1Datos muy uniformes (nulls, repeticiones)
1-4Texto plano, código fuente
4-6Código compilado normal
6-7Datos comprimidos o parcialmente cifrados
7-8Cifrado fuerte, compresión alta, o packing

Módulo hash

Calcula hashes de secciones específicas del fichero.

import "hash"

rule KnownMaliciousSection
{
    condition:
        // Hash de los primeros 1024 bytes
        hash.sha256(0, 1024) == "a1b2c3..."

        // Hash de una sección específica (combinado con pe)
        // hash.md5(pe.sections[0].raw_data_offset,
        //          pe.sections[0].raw_data_size) == "d4e5f6..."
}

Caso practico 1: detectar Cobalt Strike beacon

Cobalt Strike es el C2 framework más usado tanto por red teams como por grupos APT. Detectar un beacon con la configuración por defecto es un ejercicio clasico.

import "pe"

rule CobaltStrike_Beacon_Default
{
    meta:
        author = "MalwareIntel Research"
        description = "Detecta Cobalt Strike beacon con indicadores de configuración por defecto"
        date = "2026-06-05"
        reference = "https://malwareintel.es/blog/cobalt-strike-beacon"
        tlp = "WHITE"
        mitre_att_ck = "T1071.001, T1059.001, T1055"
        malware_family = "Cobalt Strike"
        score = 80

    strings:
        // Config block markers
        $config1 = { 00 01 00 01 00 02 ?? ?? 00 02 00 01 00 }
        $config2 = { 69 68 69 68 69 6B 69 6B 69 6A }

        // Named pipe patterns (default)
        $pipe1 = "\\\\.\\pipe\\msagent_" ascii wide
        $pipe2 = "\\\\.\\pipe\\MSSE-" ascii wide
        $pipe3 = "\\\\.\\pipe\\postex_" ascii wide
        $pipe4 = "\\\\.\\pipe\\status_" ascii wide

        // Default User-Agent
        $ua = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)" ascii

        // Beacon commands
        $cmd1 = "beacon.dll" ascii
        $cmd2 = "beacon.x64.dll" ascii
        $cmd3 = "%s%s: %s" ascii
        $cmd4 = "ReflectiveLoader" ascii

        // Sleep mask / XOR routines
        $xor1 = { 8B ?? 83 ?? 04 33 ?? 89 ?? 83 ?? 04 3B }
        $xor2 = { 0F B6 ?? 30 ?? ?? FF ?? 3B }

    condition:
        uint16(0) == 0x5A4D and
        filesize < 1MB and
        (
            (1 of ($config*) and 1 of ($pipe*)) or
            (2 of ($cmd*) and 1 of ($xor*)) or
            ($ua and 1 of ($cmd*) and 1 of ($pipe*))
        )
}

Por qué funciona esta regla

La regla combina tres estrategias de detección independientes, unidas con or:

  1. Config block + named pipe: el beacon almacena su configuración en un bloque con estructura fija. Los named pipes por defecto son conocidos.
  2. Beacon commands + XOR routine: la cadena "ReflectiveLoader" es característica de la inyección reflectiva, y los patrones XOR corresponden al sleep mask.
  3. User-Agent + commands + pipe: la combinación del UA por defecto con otros indicadores es suficientemente específica.

Cada rama por separado podría dar falsos positivos. La combinación los reduce drásticamente.

Caso practico 2: identificar UPX packing

UPX es el packer más común. Detectar binarios empacados con UPX es útil como paso previo al análisis (desempacar antes de aplicar reglas de detección).

import "pe"
import "math"

rule UPX_Packed_PE
{
    meta:
        author = "MalwareIntel Research"
        description = "Detecta ejecutables PE empacados con UPX"
        date = "2026-06-05"
        tlp = "WHITE"
        score = 90
        false_positive_rate = "very_low"

    strings:
        // UPX magic en secciones
        $upx0 = "UPX0" ascii
        $upx1 = "UPX1" ascii
        $upx2 = "UPX2" ascii
        $upx_sig = "UPX!" ascii

        // String de versión UPX
        $version = /UPX\s+[0-9]+\.[0-9]+/ ascii

    condition:
        uint16(0) == 0x5A4D and
        filesize < 20MB and
        (
            // Secciones nombradas UPX0/UPX1
            (
                for any i in (0..pe.number_of_sections - 1) : (
                    pe.sections[i].name == "UPX0" or
                    pe.sections[i].name == "UPX1"
                )
            )
            or
            // Magic string UPX!
            ($upx_sig and ($upx0 or $upx1))
        ) and
        // Entropía alta confirma packing
        math.entropy(0, filesize) > 6.5
}

La combinación de nombres de sección UPX con entropía alta es casi infalible. UPX comprime el código, lo que eleva la entropía significativamente por encima de un PE normal.

Caso practico 3: detectar macro maliciosa en Office

Los documentos Office con macros maliciosas siguen patrones reconocibles en su estructura OLE.

rule Office_Malicious_Macro
{
    meta:
        author = "MalwareIntel Research"
        description = "Detecta documentos Office con macros que descargan o ejecutan payloads"
        date = "2026-06-05"
        tlp = "WHITE"
        mitre_att_ck = "T1566.001, T1204.002, T1059.005"
        score = 70

    strings:
        // OLE magic (documentos Office legacy .doc, .xls)
        $ole_magic = { D0 CF 11 E0 A1 B1 1A E1 }

        // Indicadores de macro VBA
        $vba1 = "VBAProject" ascii wide
        $vba2 = "ThisDocument" ascii wide
        $vba3 = "AutoOpen" ascii wide nocase
        $vba4 = "Document_Open" ascii wide nocase
        $vba5 = "Auto_Open" ascii wide nocase
        $vba6 = "Workbook_Open" ascii wide nocase

        // Funciones de ejecución
        $exec1 = "Shell" ascii wide fullword
        $exec2 = "WScript.Shell" ascii wide
        $exec3 = "CreateObject" ascii wide
        $exec4 = "PowerShell" ascii wide nocase
        $exec5 = "cmd.exe" ascii wide nocase
        $exec6 = "MSXML2.XMLHTTP" ascii wide
        $exec7 = "URLDownloadToFile" ascii wide

        // Ofuscación típica
        $obf1 = "Chr(" ascii wide
        $obf2 = "ChrW(" ascii wide
        $obf3 = "StrReverse" ascii wide
        $obf4 = "Replace(" ascii wide

    condition:
        $ole_magic at 0 and
        $vba1 and
        1 of ($vba3, $vba4, $vba5, $vba6) and
        (
            2 of ($exec*) or
            (1 of ($exec*) and 2 of ($obf*))
        )
}

La lógica: el fichero debe ser OLE (no OOXML), contener un VBAProject con auto-ejecución, y tener al menos dos funciones de ejecución o una funcion de ejecución combinada con técnicas de ofuscación.

Hunting con YARA en VirusTotal

VirusTotal ofrece dos funcionalidades para hunting con YARA:

VT Hunting (Livehunt)

Livehunt aplica tus reglas YARA a todos los ficheros que se suben a VirusTotal en tiempo real. Cuando un sample matchea, recibes una notificación.

Configuración:
  1. Cuenta VirusTotal con licencia (Intelligence o Enterprise)
  2. Subir regla YARA al panel Livehunt
  3. Configurar notificaciones (email, webhook, Slack)
  4. Definir filtro de prioridad (por score, por tag, por fuente)

Límites:
  Free:        0 reglas Livehunt
  Premium:     25 reglas Livehunt
  Enterprise:  100+ reglas Livehunt

VT Retrohunt

Retrohunt aplica tus reglas YARA retroactivamente sobre los ficheros ya almacenados en VirusTotal (varios petabytes, meses de historia). Es la herramienta definitiva para responder: "¿ha existido este malware antes de que lo descubriéramos?"

Uso típico de Retrohunt:
  1. Descubres un nuevo sample de malware
  2. Escribes una regla YARA basada en sus patrones únicos
  3. Lanzas Retrohunt para buscar variantes anteriores
  4. Encuentras samples de hace 6 meses: el actor llevaba tiempo activo
  5. Extraes IOCs adicionales de los samples históricos

Tips para reglas de Hunting en VT

1. Especificidad alta: VT procesa millones de ficheros/día.
   Una regla con muchos falsos positivos es inútil.

2. Combinar strings con condiciones estructurales:
   "filesize < 1MB and pe.imports(...)" reduce el espacio de búsqueda.

3. Evitar regex costosas: /.*/ o patrones con backtracking
   causan timeouts en Retrohunt.

4. Usar pe.imphash() para familias conocidas:
   el import hash agrupa variantes compiladas con el mismo código.

5. Testear antes con VT Intelligence search:
   content:"cadena" type:peexe size:500kb-

Herramientas complementarias

HerramientaFunciónURL
yarGenGenera reglas YARA automáticamente a partir de samplesgithub.com/Neo23x0/yarGen
yaraQAValida calidad de reglas (performance, falsos positivos)github.com/Neo23x0/yaraQA
YARA-XRewrite oficial de YARA en Rust. Más rápido, mejor soporte regexgithub.com/VirusTotal/yara-x
yara-ciIntegración CI/CD para validar reglas en PRsgithub.com/Neo23x0/yara-ci
LokiScanner IOC/YARA para endpoints (incident response)github.com/Neo23x0/Loki
Thor LiteScanner avanzado con reglas Signature Base incluidasnextron-systems.com
YARA Editor (VSCode)Extensión con syntax highlighting y snippetsmarketplace.visualstudio.com
YARAifyServicio de abuse.ch para escanear samples con reglas YARAyaraify.abuse.ch

yarGen: generar reglas a partir de samples

yarGen analiza un directorio de samples maliciosos y genera reglas YARA basadas en strings únicas (excluyendo strings comunes de software legítimo usando Goodware strings DB).

# Instalar
pip install yargen

# Generar reglas a partir de un directorio de samples
yargen -m /path/to/malware_samples/ -o rules_output.yar

# Excluir strings comunes (reduce falsos positivos)
yargen -m /path/to/malware_samples/ \
       --excludegood \
       -o rules_output.yar

Las reglas generadas por yarGen son un punto de partida. Siempre necesitan revisión manual: eliminar strings genéricas, ajustar conditions, y añadir metadata.

Errores comunes y best practices

Errores que producen falsos positivos

ErrorProblemaSolución
Strings demasiado genéricas"http://" matchea cualquier binario con URLsCombinar con strings más específicas
Sin restricción de filesizeMatchea PDFs de 100MB o ISOsAñadir filesize < X
Sin magic bytesMatchea ficheros de tipos inesperadosAñadir uint16(0) == 0x5A4D para PE
Regex sin anclar/[a-z]+/ matchea cualquier textoSer más específico: /\/api\/v[12]\/[a-z]{8,}/
Solo 1 string en conditionUna string sola rara vez es suficienteCombinar: 2 of ($s*)

Errores que afectan performance

ErrorProblemaSolución
Regex con .*Backtracking exponencialLimitar: .{0,100}
Muchas regexCada regex se evalúa independientementePreferir text/hex strings
Jumps muy amplios{ AA [0-10000] BB } escanea muchoReducir rango o reestructurar
Sin short-circuitConditions costosas primeroPoner filesize y uint16(0) al inicio

Best practices

1. SIEMPRE incluir filesize en condition
   → Evita escanear ficheros enormes innecesariamente

2. SIEMPRE incluir magic bytes cuando aplique
   → uint16(0) == 0x5A4D para PE, OLE magic para Office

3. Usar al menos 2-3 strings en combinación
   → Reduce falsos positivos drásticamente

4. Testear contra goodware antes de desplegar
   → Escanear contra Windows System32, Office, browsers

5. Documentar con metadata completa
   → author, description, date, reference, hash, mitre_att_ck, tlp

6. Versionado en git con CI
   → Cada regla es código. Revisión por pares obligatoria

7. Organizar reglas por familia/actor/tipo
   → apt28.yar, cobalt_strike.yar, ransomware_generic.yar

8. Performance: short-circuit conditions
   → filesize < 500KB and uint16(0) == 0x5A4D and (strings...)
   Los checks baratos primero, los costosos después

Recursos y referencias

Siguiente paso

Con la anatomía de YARA dominada, el siguiente artículo de la serie aplica estos conceptos a un caso real: escribir reglas YARA para detectar infostealers (RedLine, Lumma, Vidar) basándose en sus patrones de comunicación C2 y sus artefactos en disco.

Preguntas frecuentes

Artículos relacionados

Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.