Rules that run here are standard YARA and run unchanged in yara 4.x. Only a subset is implemented, and anything outside it fails with a specific error instead of being guessed at. The newest syntax used here (~ in hex strings, #a in (..), rule sets in of, defined) needs a recent 4.x release.
private rule helper { condition: filesize < 1MB }
global rule only_pe { condition: uint16(0) == 0x5A4D }
rule name : tag1 tag2
{
meta:
author = "you" version = 2 draft = true
strings:
$a = "text"
condition:
helper and $a
}
A private rule is evaluated and usable by name but never reported. If any global rule is false, no rule matches.
$t = "a\tb\x00\"q\"" // \" \\ \t \n \r \xNN
$w = "config" wide ascii // UTF-16LE and plain
$n = "cookies" nocase fullword
$x = "key" xor // keys 0x00 to 0xFF
$y = "key" xor(0x01-0xff) // or xor(5)
$p = "secret" private // used, not reported
$h = { 4D 5A ?? 4? ~00 [2] [1-4] [8-] ( 90 | 4D ?? ) }
$r = /https?:\/\/[a-z0-9.]{4,40}/ nocase
$ = "anonymous" // via of and for..of
Hex jumps cannot start or end a string. Inside ( | ) jumps must be bounded and at most 200. Regular expressions take the i and s flags; \w \s \d \b are the ASCII classes.
$a #a @a[1] !a[1] $a at 0x3C $a in (0..1KB) #a in (0..filesize) filesize uint16(0) uint32be(4) and or not == != < <= > >= + - * \ % & | ^ ~ << >> any of them all of ($a*) none of ($x, $y) 2 of them 50% of them any of (rule_a, helpers*) for any of ($a*) : ( $ at 0 ) for all i in (1..#a) : ( @a[i] < 0x1000 ) for any i in (0, 4, 8) : ( uint8(i) == 0 ) defined @a[5]
Division is \ and is integer division. Values that do not exist, such as @a[9] when $a matched twice or uint32 past the end of the file, are undefined: comparisons with them are undefined, not keeps them undefined, and a condition that ends undefined is false.
import (pe, elf, math, hash, dotnet...), external variablesincludebase64 and base64wide modifiersof ... in and of ... at, percentages in for, boolean sets in ofFiles up to 16 MB, or 4 MB where the browser blocks the background worker and the scan runs in the page itself. Each string stops at 10,000 matches. A scan stops after 15 seconds. A regular expression match is at most 4,096 bytes, as in YARA's scanner. Hex strings split at jumps longer than 200 bytes and match piece by piece, as YARA does; bounded jumps go up to 1,000,000 bytes and an open jump such as [8-] spans any distance. Hex jumps report the shortest match at each offset; in a few alternation cases YARA can report a longer one.