Skip to content

YARA strings: text, hex and regex patterns

How to write YARA strings: text strings and escapes, modifiers like nocase, wide, xor and base64, hex strings with wildcards and jumps, and regular expressions.

Published 4 min read

Patterns — YARA calls them strings, even when they are bytes or regular expressions — are what YARA searches for before it evaluates the condition. Choosing them well decides both how precise a rule is and how fast it runs. This guide covers the three pattern types and their modifiers.

Text strings

A text string is written in double quotes and matched byte for byte:

rule Text_Strings
{
    strings:
        $a = "Global\\MyMutex_2024"
        $b = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0)"
        $c = "tab\there and a quote \" inside"
        $d = "\x4D\x5A with raw bytes"
    condition:
        any of them
}

Supported escapes are \", \\, \t, \n, \r and \xNN for an arbitrary byte. YARA-X rejects unknown escape sequences instead of silently ignoring them — a common source of errors when porting old rules (see YARA-X vs YARA).

String modifiers

Modifiers follow the value and change how it is searched.

ModifierEffectNotes
asciiMatch the bytes as writtenDefault when no encoding modifier is given
wideMatch UTF-16LE (each char followed by 00)Combine with ascii to search both
nocaseCase-insensitiveMultiplies internal variants; avoid on short strings
fullwordMust be delimited by non-alphanumeric characters"evil" then won't match "devil"
xorAlso match the string XORed with every single-byte key 1–255xor(1-255) or xor(0x20) narrows the range
base64 / base64wideMatch the string inside base64-encoded dataCustom alphabet as argument; not combinable with nocase, xor or fullword
privateMatch, but hide the string from match outputUseful for helper patterns
rule Modifier_Examples
{
    strings:
        $cfg = "ConfigBlock" wide ascii
        $cmd = "invoke-expression" nocase
        $key = "SuperSecretKey!" xor(1-255)
        $b64 = "powershell -nop" base64
        $word = "backdoor" fullword
    condition:
        2 of them
}

Keep xor, base64 and nocase for strings of at least six to eight characters: each modifier expands one pattern into many, and short expansions match random data.

Hexadecimal strings

Hex strings describe raw bytes between braces. They are the tool of choice for code sequences, file headers and binary configuration blobs.

rule Hex_Syntax
{
    strings:
        $fixed = { 4D 5A 90 00 03 00 00 00 }
        $wild = { E8 ?? ?? ?? ?? 83 C4 04 }
        $nibble = { 6A 4? 68 00 30 00 00 }
        $jump = { 55 8B EC [2-6] 83 EC 20 }
        $alt = { 68 ( 00 10 | 00 20 ) 00 00 }
    condition:
        any of them
}
SyntaxMeaning
??Any byte
4? / ?ANibble wildcard: high or low half fixed
[4], [2-6], [8-]Jump of exactly 4, between 2 and 6, or 8 or more arbitrary bytes
( AA | BB CC )Alternatives, which may differ in length
~00Any byte except 00 (YARA 4.3+ and YARA-X)

Opcodes with relative addresses (call, jmp, lea rip) should have their operand bytes wildcarded, otherwise the rule only matches one build. Keep at least four consecutive fixed bytes somewhere in the pattern so YARA can extract a good atom.

Regular expressions

Regexes are written between slashes and follow a Perl-like syntax: character classes, quantifiers, alternation, groups and anchors. Two flags may follow the closing slash: i (case-insensitive) and s (dot matches newlines). The same string modifiers as for text strings (ascii, wide, nocase, fullword, private) apply.

rule Regex_Examples
{
    strings:
        $url = /https?:\/\/[a-z0-9\-.]{3,64}\.(top|xyz|click)\/[a-z0-9]{8}/ nocase
        $ip_port = /\b(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}:[0-9]{2,5}\b/
        $mutex = /Global\\[A-F0-9]{8}-[A-F0-9]{4}/
    condition:
        any of them
}

Regex pitfalls:

  • Missing literal part. A regex like /[a-z]{10}\.exe/ has only .exe as a fixed anchor; one like /[a-z]{5,}/ has none and must be attempted almost everywhere.
  • Leading .*. Patterns are already unanchored; a leading .* only adds work.
  • Unbounded repetition. Prefer {1,64} over + or * when you know the maximum length.
  • Escapes. The forward slash must be escaped as \/. YARA-X is stricter than YARA 4 about invalid escapes.

Choosing the right type

You want to match…Use
A unique readable string (mutex, user agent, PDB path)Text string, with wide if it may be UTF-16
Code bytes, headers, binary structuresHex string with wildcards for addresses
A small set of variants of a byte sequenceHex alternatives ( … | … )
Something with a variable-length or structured part (URLs, GUIDs)Regex with a literal anchor
An obfuscated stringxor or base64 on a long enough string

Performance in one paragraph

YARA extracts a short fixed sequence (an atom) from every pattern and searches for all atoms at once; only where an atom hits does it verify the full pattern. Strings shorter than four bytes, hex patterns made of wildcards, common bytes such as 00 00 00 00, and regexes without literals all produce poor atoms and slow down the whole rule set. The performance guide explains the mechanism, and the linter flags these cases automatically.

Next: combine your patterns in YARA conditions.

FAQ

What does the wide modifier do in YARA?
wide searches for the string encoded as UTF-16LE, i.e. each ASCII character followed by a zero byte. Add ascii as well if the string may appear in both encodings.
How do I match any byte in a YARA hex string?
Use ?? for a full wildcard byte, a single ? for one nibble (for example 4? or ?A), and [n-m] for a jump of n to m arbitrary bytes.
When should I use a regex instead of a text string?
Only when the variable part cannot be expressed with a text or hex string. Regexes are slower, and they must contain a literal part of at least a few bytes to be efficient.