PermitANY
Tool · Security

YARA Rule Tester

Parse a rule, search its strings in a sample you paste, and evaluate the condition as far as it can honestly be evaluated. Nothing leaves your browser.

This does not run YARA, and here is exactly why

YARA is a compiled C engine. Running the real thing in a browser means shipping a WebAssembly build of it, and this site runs on five runtime packages on purpose — so it is not here. What this page does instead is read your rule the way yarac would, search your strings in the text you paste, and evaluate the condition for the parts that do not need a file.

What it therefore cannot tell you: anything that reads the file itself. filesize, uint16(0), entrypoint, pe.*, elf.*, hash.*, math.entropy, and for loops. When your condition uses one, the verdict says cannot be decided here and names the part — it never prints a guess as a result. The same goes for hex alternation ( A1 | B2 ) and a wide-only regex: they are marked not simulated rather than quietly reported as no match.

Before you deploy anything, compile it: yarac rules.yar rules.compiled, then yara -s rules.yar /path/to/samples. This page is for the twenty iterations before that, and for the mistakes the compiler is perfectly happy with.

The sample is treated as UTF-8 bytes. Binary pasted as text will not survive the paste, so for a real file run yara rule.yar file — or paste the output of strings -a here.

rule Suspicious_Rundll32_Proxy_Exec5 strings

The condition is satisfied by this sample

Every part of the condition could be evaluated from the text you pasted, and it comes out true.

condition: $tool and any of ($path*) and $export and not $mz

$tool = "rundll32.exe" ascii wide nocase2×

0x6e (ascii) 0x9c (ascii)

$path1 = "\\AppData\\Local\\Temp\\" ascii wide1×

0xbb (ascii)

$path2 = "\\Users\\Public\\" ascii wideno match
$export = /,\s?[A-Za-z_][A-Za-z0-9_]{2,30}\s/ ascii1×

0xd9 (regex)

$mz = { 4D 5A ?? ?? ?? ?? ?? ?? ?? ?? [0-64] 50 45 00 00 }no match

Nothing to flag

    A YARA rule that compiles and still never fires

    Almost every broken rule in production compiled without a warning. The engine is checking syntax; nobody is checking meaning. These are the ones the review panel looks for.

    • wide replaces, it does not add. This is the mistake, far ahead of everything else. People read wide as “also match the UTF-16 form”. It is not: a string marked only wide is searched exclusively as UTF-16LE and no longer matches the plain ASCII bytes it used to. The rule compiles, the analyst tests it against a UTF-16 sample, it works, and it silently stops matching every ASCII artefact in the corpus. The modifier list you almost always want is ascii wide.
    • xor is 256 patterns, so a short string is 256 chances to be wrong. xor searches every single-byte key, which is exactly what you want for a C2 domain hidden in a loader and exactly what you do not want on a four-byte string: under some key, four arbitrary bytes appear in almost any file. Narrow it — xor(0x01-0x1f) — or lengthen the string. And xor cannot be combined with nocase: yarac rejects it, because once the bytes are XORed with an unknown key there is no case left to fold.
    • fullword does not mean what it looks like in a path or a URL. A word boundary in YARA is simply a byte that is not alphanumeric and not an underscore. A backslash is a boundary, a dot is a boundary, a slash is a boundary. So fullword on evil.com still matches inside sub.evil.com.attacker.net, and fullword on rundll32.exe matches inside a full path — which may be what you wanted, but it is rarely what the author thought they were asking for.
    • A string of three or four bytes identifies nothing. YARA indexes on atoms of up to four bytes, so a four-byte string gives the scanner no selectivity at all and appears by chance in anything large. Below roughly six to eight bytes a string is not evidence, it is noise — and if the condition is just any of them, that noise is the whole rule.
    • A condition that names a string you never defined. $x when the strings section defines $a. This is the same failure as a Sigma rule whose condition points at a selection that is not there — the site has that precedent already, and it is worth noticing that two different detection formats fail in exactly the same place. The mirror image is just as common: a string defined, searched on every file, and then never referenced by the condition.
    • A hex jump with no ceiling. [0-20] is fine. [-] is unbounded, so the engine tries every distance from the first fragment to the end of the file, and the cost grows with file size — the rule gets slow on precisely the large samples you care about. Related and less obvious: a hex string that starts with ?? or a jump has no fixed prefix for YARA to index on, and degrades the whole scan.
    • $a at 0 and offsets are about the file, not your paste. An offset is counted from the first byte of the scanned file. This page checks it against the text you pasted, which is only the same number if you pasted the file from byte zero — so it says so, every time, instead of letting you read a green tick as proof.

    Where to go next

    YARA and Sigma are the same craft in two formats — one looks at bytes on disk, the other at events in a log — and the failure modes rhyme. If you are writing the Sigma side, the Sigma rule builder applies the same review idea to a detection rule, and sigma-rule-validator runs those checks over a directory of them.

    For the judgement around the rule rather than the rule itself, detection-engineering covers the artefact-evasion table and measuring noise before you deploy, detection-as-code covers getting rules through CI instead of through a console, and malware-analysis-basics is where the strings you put in a rule come from in the first place.

    To pull indicators out of a report before you write the rule, ioc-extractor handles the refanging and the noise filtering, and the detection-engineer agent will draft and critique the rule with a tuning plan attached.