YARA Rules for Incident Response
How to write YARA rules for incident response — durable signatures that survive a packer change, scanning files and memory, and tuning false positives.
YARA is how you turn a single malware sample into a repeatable sweep of your whole estate. Where Sigma matches behavior in logs, YARA matches patterns in the artifacts — files and process memory — which makes it the signature language of incident response and threat hunting. The skill is writing rules that survive a recompile or a packer change instead of breaking on the next variant. This guide is how to write durable YARA and use it across files and memory.
YARA-detectable evasion (packing, obfuscation) maps to MITRE ATT&CK T1027 — Obfuscated Files or Information. It complements the behavioral detections across the pillar — Sigma finds the activity, YARA identifies the file or memory behind it.
What is YARA and why use it in incident response?
YARA is a tool for describing malware families by rules — sets of strings and conditions that match a file’s or process’s contents. During an incident, an analyst who has one sample can extract its distinctive traits into a YARA rule and then scan every endpoint, every file share, and process memory across the fleet for the same threat. That converts a point-in-time finding into a scalable, repeatable answer to “where else is this?”
Its unique value is reaching what log-based detection cannot: the file on disk, the memory of a running process, the artifact itself. Fileless malware that never spawns a suspicious process still has strings and structures in memory that YARA can match.
What can you do with YARA in IR?
| Use case | What YARA does | Why it matters |
|---|---|---|
| Fleet sweep | Scan all endpoints for a sample’s traits | Find every affected host fast |
| Memory scan | Match in-process strings/structures | Catch fileless / injected implants |
| Triage | Classify a suspicious file | Speed up analyst decisions |
| Threat hunt | Search for a family’s characteristics | Find variants, not just the one hash |
| Retro-hunt | Match new rules against stored samples | Discover past compromise |
The common thread: YARA answers content questions at scale. Pair it with the behavioral detections and the threat-hunting hypotheses that tell you where to look.
How to write a durable YARA rule
A brittle rule keys on one hash or a byte sequence that a recompile changes; it matches the sample you have and nothing else. A durable rule keys on characteristics that persist across variants — meaningful strings, code idioms, structural traits — combined so the match is specific.
rule darkpwn_generic_webshell {
meta:
author = "Colson"
description = "Heuristic indicators of common PHP web shells"
reference = "https://darkpwn.com/posts/file-upload-security-a-blue-team-checklist/"
attack = "T1505.003"
strings:
$eval = "eval(" nocase
$b64 = "base64_decode(" nocase
$sys = "system(" nocase
$req = /\$_(GET|POST|REQUEST)\s*\[/
condition:
filesize < 50KB and 3 of them
} This keys on the behavioral constructs a web shell needs (dynamic evaluation, encoded payloads, request-driven input) rather than a specific file, and constrains by size — so it catches variants while staying bounded. It ties directly to file upload security.
The modules that do the heavy lifting
Raw string matching gets you a long way and then stops. YARA’s modules are what let a rule reason about a file’s structure, which is what survives when an attacker changes the strings.
| Module / construct | What it gives you | Typical use |
|---|---|---|
uint16(0) == 0x5A4D | The MZ header check | Restrict a rule to PE files before anything expensive runs |
pe.imphash() | Import hash of the PE | Groups samples built from the same source tree, survives string changes |
pe.number_of_sections, pe.sections[i].name | Section layout | Catch packers and unusual section names |
pe.characteristics & pe.DLL | File type flags | Distinguish DLL implants from EXEs |
math.entropy(0, filesize) | Shannon entropy | Flag packed or encrypted payloads |
hash.md5(0, filesize) | Content hash inside the condition | Pin an exact known-bad while keeping heuristics in the same rule |
pe.imphash() deserves particular attention in an IR context. Because the import hash is derived
from the imported functions and their order, it tends to stay stable across recompiles of the same
codebase while changing completely between unrelated families. That is exactly the durability
property a hash normally lacks — it identifies the build, not the bytes.
Entropy is the classic packer heuristic and the classic false-positive generator. High entropy means compressed or encrypted, which describes most malware packers and also describes every installer, every archive, and a great deal of legitimate signed software. Use it as one condition among several, never as the rule.
How do you keep YARA rules fast at fleet scale?
A rule that takes 40 milliseconds on your laptop takes an hour across a large estate, and the first thing anyone does with a slow scan is stop running it. Rule performance is therefore a correctness property, not an optimisation.
YARA builds a fast pre-filter by extracting atoms — short substrings, at most a few bytes — from every string in your rules, and running a single pass over the data looking for them. Only when an atom hits does the full string match run. Everything about performance follows from that one mechanism:
- Short strings are slow. A two-byte string produces a two-byte atom that hits constantly, and every hit costs a full match attempt. YARA emits a warning for these; run with warnings visible and treat them as errors in review rather than noise to scroll past.
- Unanchored regular expressions are the worst offenders. A regex with no literal prefix gives the atom extractor nothing to work with. Add a literal anchor — a fixed substring the pattern must contain — and the regex only runs where that anchor hits.
- Order the condition from cheap to expensive. YARA short-circuits, so
filesize < 100KB and uint16(0) == 0x5A4D and $expensive_regexevaluates the two trivial checks first and skips the regex entirely on the overwhelming majority of files. nocaseon a long string multiplies the atom set. Use it where case genuinely varies, not reflexively.- Scope before you scan. A rule that only applies to PE files should say so structurally, not discover it after matching twenty strings.
Florian Roth’s YARA performance guidelines are the standard reference here, and yaraQA will
mechanically flag the common problems in an existing rule library. Running a linter over a rule
set you inherited is usually a bad afternoon followed by a much faster scanner.
How to tune YARA false positives
A rule that fires on benign files is worse than no rule — it erodes trust and slows IR. Tune for precision:
- Require a combination —
N of them, not any single string, so coincidental matches don’t trigger. - Constrain the scope — file size, magic bytes (
uint16(0) == 0x5A4Dfor PE), or file type — so the rule only considers plausible candidates. - Name the false positives in the
metaand test against a clean corpus (goodware) before deploying. - Version the rule and track its matches, the same lifecycle discipline as the Sigma rule lifecycle.
Triage rules and production rules are not the same thing
Most arguments about YARA false positives are really a category error: two rules with completely different jobs are being held to one standard.
| Triage rule | Production rule | |
|---|---|---|
| Runs against | A handful of samples an analyst is already looking at | The whole estate, continuously |
| Acceptable FP rate | High — a human reads every hit | Near zero — hits drive action |
| Breadth | Deliberately broad; catching variants matters more than precision | Narrow and specific |
| Lifetime | Often hours, scoped to one incident | Months to years, versioned |
| Failure mode | Misses a variant | Floods the queue, gets disabled, and is not there next time |
A broad heuristic rule is a good triage rule and a bad production rule, and the same text is being judged correct in one context and wrong in the other. Label rules by which they are, keep them in separate directories, and apply the clean-corpus test only where it belongs. An incident-scoped rule that fires on twenty benign files is doing its job if it also finds the implant on host seventeen.
The promotion path matters too. A triage rule that proves useful gets narrowed — extra conditions, a scope constraint, clean-corpus tested — and then moves into the production set with a version and an owner. That is the same lifecycle the Sigma rules follow, and it is worth running the two libraries with one process rather than two.
Metadata is what makes a rule library usable
A rule with no meta block is unmaintainable within a month, because nobody can tell whether it
is still needed. Require these fields on every production rule:
authoranddate— who to ask, and how stale it is.reference— the sample, report, or incident that motivated it. A rule with no provenance cannot be retired safely, because nobody can establish what it was for.description— what a hit means, written for whoever gets paged at 3 a.m., not for you.hash— at least one sample the rule is known to match, so a regression test is possible.- A score or confidence field — lets downstream tooling distinguish “investigate” from “act.”
The hash field is the one that converts a rule library into something testable. With a known
matching sample recorded, a CI job can verify every rule still matches what it claims to, which
catches the silent breakage that happens when someone edits a shared string.
How to use YARA across files and memory
- Files: scan endpoints, shares, and quarantines; retro-hunt stored samples with new rules.
- Memory: scan process memory for injected or fileless implants that never hit disk — essential alongside process injection detection.
- Automation: integrate YARA into your EDR/AV, mail/file gateways, and IR tooling so a new rule sweeps automatically.
What memory scanning actually costs
Memory scanning is where YARA earns its place in IR, and it behaves differently enough from file scanning that treating them as one operation produces bad results.
- You scan a process, not a file. Scoping matters: sweeping every process on every host is expensive and rarely necessary. Scope to the processes your behavioural detections already flagged — the ones with injection indicators, unexpected network egress, or an unusual parent chain.
- The scan is a point in time. An implant that is unpacked only briefly, or that re-encrypts its own strings between beacons, can be absent from the exact snapshot you took. A negative memory scan is weak evidence; a positive one is strong.
- Strings behave differently in memory. Malware that is packed on disk is unpacked in memory, which is precisely why memory scanning works — but it also means the disk rule and the memory rule are looking for different things. Rules built from a packed sample frequently fail against the same malware running.
- Structural conditions may not apply. Beyond
filesize, PE-module conditions can behave unexpectedly against a mapped image whose headers have been modified or stripped, which is a common anti-analysis step. - It is heavy. Scanning process memory reads real pages and competes with the workload on a production host. Budget it as an investigation action with a cost, not a background sweep.
The practical pattern is: behavioural detection narrows the host and the process, then YARA answers what is running inside it. Using memory scanning as the primary discovery mechanism inverts that and is expensive enough that it usually gets switched off.
When should you not reach for YARA?
YARA is not a general-purpose detection layer, and treating it as one is a common way to spend months building a rule library that catches nothing your EDR did not already have.
Skip it when behavioural telemetry already answers the question. If a technique is reliably detectable in logs, a Sigma rule is cheaper to write, cheaper to run, and harder to evade than a content signature. Content changes on every build; behaviour changes when the technique changes.
Be honest about the evasion asymmetry. A content signature is trivially testable by an adversary who has it. Public rule sets are valuable and they are also a compliance checklist for anyone building a payload — they can verify non-detection before ever touching your network. That is not an argument against sharing rules; it is an argument against treating a public rule set as coverage.
Prevention is not the job. YARA is strongest in three places: sweeping an estate once you know what you are looking for, retro-hunting stored samples when new intelligence arrives, and classifying an artifact during triage. All three are response activities. A rule library maintained as though it were antivirus will be judged by a standard it was never designed to meet.
One note on tooling direction. VirusTotal’s YARA-X is a Rust rewrite of the engine intended as the long-term successor, with substantially better performance and stricter rule validation. Rule compatibility is high but not absolute, and the stricter parser rejects constructs the original engine accepted. If you maintain a large library, testing it against both engines now is cheaper than discovering the differences during a migration.
How do you build a rule library that survives contact with reality?
Individual rules are the easy part. What decays is the library — and a rule set nobody trusts is worse than no rule set, because it consumes scan time and produces alerts that get closed unread.
Three structural decisions determine whether a library stays useful past its first year:
Keep rules in version control with the same review bar as code. A rule is a production artifact that runs against every endpoint you own. It deserves a diff, a reviewer, and a history that explains why a condition was loosened in March. Storing rules in a shared folder is how libraries end up with four near-identical web shell rules and nobody willing to delete any of them.
Give every rule a retirement condition when you write it. An incident-scoped rule should expire when the incident closes. A rule tracking a specific campaign should be reviewed when that campaign stops being reported. Without an explicit end state, rules accumulate forever, and the scan gets slower every quarter until someone declares bankruptcy and disables the lot.
Test continuously against both corpora. The known-bad set proves the rules still match what they claim to; the known-good set proves they have not started matching your own software. The second corpus is the one teams skip, and it is the one that catches the expensive failure — a rule that begins firing on a newly deployed internal application and buries the queue on a Monday morning.
None of this is specific to YARA. It is the same lifecycle discipline that applies to Sigma rules, and running both libraries through one process is meaningfully cheaper than running two. The detections differ; the maintenance problem is identical, and it is the maintenance problem that determines whether either library is worth anything in eighteen months.
Common YARA mistakes
- Hash-equivalent rules. Break on the next recompile.
- No scope constraint. Slow scans and false positives on unrelated files.
- No clean-corpus testing. The rule fires on goodware in production.
- File-only thinking. Missing memory scanning loses fileless threats.
- Carrying
filesizeinto a memory rule. It has no meaning there, and the rule silently matches nothing. The scan reports success and finds an empty estate. - Ignoring the atom warnings. Short strings and unanchored regexes make a rule set slow enough that somebody eventually stops running it, which is the same outcome as deleting it.
- Building rules from a packed sample. The strings you extracted exist only on disk. Unpack first, or the memory rule will never match the running malware.
- No
metablock. A rule with no author, date, or reference cannot be retired, because nobody can establish what it was for or whether it still matters. - Holding triage rules to production standards. A broad incident-scoped rule with a high false positive rate is doing its job. Judging it as though it were deployed fleet-wide gets a useful rule deleted.
- Treating a public rule set as coverage. Anyone building a payload can test against the same rules you deployed, before they ever touch your network.
- Never testing regressions. Record a known matching hash per rule so a CI job can prove the rule still matches after somebody edits a shared string.
YARA for incident response checklist
- Extract durable traits (strings, structures) from a sample, not just its hash.
- Require a combination of conditions (
N of them). - Constrain by file size, magic bytes, or type.
- Name likely false positives and test against a clean goodware corpus.
- Scan files across endpoints, shares, and quarantines.
- Scan process memory for fileless and injected threats.
- Retro-hunt stored samples when a new rule is written.
- Version rules and track matches over time.
The takeaway
YARA rules for incident response turn one malware sample into a repeatable, fleet-wide sweep of files and memory — if you write them durably (traits, not hashes), constrain the scope, and tune against a clean corpus. It is the artifact-matching partner to Sigma’s behavior matching. Continue with writing Sigma rules that fire and process injection detection, or browse the full Detection Engineering pillar.
Training & tools referenced
Disclosure: Some links below are affiliate links. If you buy through them, darkpwn may earn a commission at no extra cost to you. We only recommend training and tools we actually use in our own lab, and affiliate links never influence editorial coverage.
- TryHackMeAuthorized labs to practice YARA, malware analysis, and incident responseSecurity TrainingStart training
Frequently asked questions
What is YARA used for in incident response?
YARA is a pattern-matching tool for identifying and classifying files and memory by content. In incident response you use it to sweep an estate for known-bad artifacts, hunt for a specific threat across many hosts, scan process memory for an implant, and triage suspicious files — turning an indicator into a repeatable scan.
How do you write a durable YARA rule?
Key on characteristics that survive a recompile or packer change — meaningful strings, code constructs, or structural traits — rather than a single hash or a byte sequence a rebuild would alter. Combine several conditions, constrain by file size or type, and name likely false positives so the rule is precise, not brittle.
Can YARA scan memory?
Yes. YARA can scan process memory as well as files, which is essential for detecting fileless malware and injected code that never touches disk. Memory scanning with a rule targeting an implant's in-memory strings or structures is a core IR technique.
What is the difference between YARA and Sigma?
YARA matches patterns in files and memory (the artifact itself); Sigma matches patterns in log events (the behavior). They complement each other — Sigma detects the activity in your telemetry, YARA identifies the malicious file or memory region during response and hunting.