yara::rules

tool yara signatures · detection
Basics Conditions CLI Triage Pitfalls
01Rule Building Basics
Minimal rule
rule suspicious_upx
{
  meta:
    author = "you"
    description = "find UPX packed samples"
  strings:
    $mz = { 4D 5A }
    $upx1 = "UPX0" ascii
    $upx2 = "UPX1" ascii
  condition:
    $mz at 0 and 1 of ($upx*)
}
String modifiers you will actually use
$a = "powershell" ascii nocase
$b = "cmd.exe /c" wide
$c = /https?:\/\/[A-Za-z0-9._-]+/ ascii
$d = { 68 ?? ?? ?? ?? 6A 00 6A 00 }

# useful modifiers
ascii  wide  nocase  fullword  xor  base64  base64wide  private
02Condition Patterns
Common condition examples
# at least N strings
condition:
  2 of ($api*)

# all strings in a set
condition:
  all of ($ps*)

# filesize + section checks
condition:
  filesize < 500KB and $mz at 0

# suspicious PE imports
condition:
  pe.is_pe and
  3 of ("VirtualAlloc","WriteProcessMemory","CreateRemoteThread")

# offset / count logic
condition:
  #url > 3 and @mz[1] == 0
Modules worth knowing
import "pe"
import "hash"
import "math"
import "dotnet"
import "elf"

# examples
pe.machine == pe.MACHINE_AMD64
pe.number_of_sections > 6
math.entropy(0, filesize) > 7.2
hash.md5(0, filesize) == "..."
Modifier arguments (xor / base64)
$a = "flag{" xor                 # try all 255 single-byte keys
$b = "flag{" xor(0x01-0xff)       # restrict key range
$c = "cmd.exe" xor ascii wide     # combine with encodings
$d = "http://" base64             # 3 b64 alignments as they appear mid-stream
$e = "http://" base64wide         # base64 of the UTF-16LE form
$f = "AdminToken" base64("")  # custom alphabet

# entropy gate for packed/encrypted regions
math.entropy(0, filesize) > 7.0
# xor() catches key-obfuscated strings with no known key
03CLI Usage
Scanning with yara / yara64
yara rules.yar sample.bin
yara -r rules/ samples/
yara -s rules.yar sample.bin      # print matching strings
yara -m rules.yar sample.bin      # print meta
yara -n rules.yar sample.bin      # fast mode
yarac rules.yar compiled.yarc
yara compiled.yarc sample.bin

# scan memory dumps carefully; pre-filter first
Rule debugging
yara -s rule.yar sample.bin
yara -D rule.yar sample.bin     # warnings / rule diagnostics

# develop iteratively
1. start with one reliable string
2. verify on positive sample
3. test against benign files
4. add thresholds, sizes, pe checks
5. remove noisy generic strings
04Malware Triage Recipes
Quick suspicious packer / loader rule ideas
rule loader_combo
{
  strings:
    $s1 = "VirtualAlloc" ascii wide
    $s2 = "WriteProcessMemory" ascii wide
    $s3 = "CreateRemoteThread" ascii wide
    $s4 = "powershell -enc" ascii nocase
  condition:
    pe.is_pe and 2 of ($s1,$s2,$s3) or $s4
}
Useful external helpers
strings -a sample.bin | grep -Ei "http|powershell|cmd.exe|rundll32|regsvr32"
peframe sample.exe
lief / rabin2 / objdump for imports + sections
ssdeep / tlsh for similarity clustering
YARA over a memory image
# Volatility3 — all process + kernel space
vol -f mem.raw yarascan.YaraScan --yara-rules /rules/mal.yar
vol -f mem.raw yarascan.YaraScan --yara-file mal.yar --pid 1234
vol -f mem.raw windows.vadyarascan --yara-rules "flag{"

# MemProcFS — mount, then scan the FS view
yara -r rules.yar M:/pid/1234/

# raw dump directly (noisy — scope it) / live PID
yara -r --fast-scan rules.yar mem.raw
yara -r rules.yar 1234
05Pitfalls
Wide strings matter
Windows malware often stores strings in UTF-16LE. Add wide.
Do not overfit one sample
A rule built from one hash/string may miss variants or explode with false positives.
Generic APIs are noisy
VirtualAlloc alone is weak. Combine with imports, sizes, or additional strings.