
Yara Memory Hunting
- 1 installs
- 10 repo stars
- Updated August 3, 2026
- dreadnode/capabilities
Run YARA rules against memory images to locate malware and C2 frameworks, scoping by PID or whole image and controlling false positives.
About
Scans memory images with YARA to find known malware, C2 frameworks, and custom IoCs, then pivots hits into structured findings. A developer or analyst uses it during memory forensics and malware triage.
- Scoping table for single-PID vs whole-image scans
- Rule patterns for config blocks, API resolution, and named pipes
Yara Memory Hunting by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,835 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dreadnode/capabilities --skill yara-memory-huntingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 10 |
| Last updated | August 3, 2026 |
| Repository | dreadnode/capabilities ↗ |
What it does
Run YARA rules against memory images to locate malware and C2 frameworks, scoping by PID or whole image and controlling false positives.
Files
YARA Memory Hunting
Maps to MITRE ATT&CK T1059 (Command and Scripting Interpreter) and T1027 (Obfuscated Files or Information) when classifying samples. For rule sources see Elastic protections-artifacts, YARA-Forge, and vendor reports.
When to Use
- You have IoCs (strings, byte patterns, config layouts) and want to confirm / scope
- Triage surfaced a suspect process and you want to classify the family
- Sweeping an image for commodity C2 frameworks (Cobalt Strike, Sliver, Brute Ratel, Metasploit, etc.)
Scoping Decisions First
| Goal | Scope | Rule style |
|---|---|---|
| "Is this process X?" | Single PID via pid=N | Specific, tight strings |
| "Where in the image does X live?" | Whole image | Broader, paired-condition rules |
| "Is there anything bad here at all?" | Whole image | Curated commodity-framework pack |
Whole-image scans are slow and noisy. Use them when you don't yet have a suspect, then narrow to PIDs.
Workflow
1. Pick the rule set
For commodity C2 and known malware, start with community-maintained packs:
- Elastic Protections Artifacts (
protections-artifacts/yara/rules/) - YARA-Forge aggregate
- Vendor-published rules attached to report writeups (Mandiant, Volexity, CrowdStrike blogs)
For custom IoCs derived from triage, write the rule inline — don't manage a file for a one-shot.
2. Run the scan
volatility_yara_scan(image, rules_file="/path/to/rules.yar", pid=None)or
volatility_yara_scan(image, rules_inline="""
rule MyCustom { strings: $a = "CONFIG:" condition: $a }
""", pid=1234)Exactly one of rules_file / rules_inline. The pid filter dramatically speeds up scans when you have a suspect.
3. Interpret hits
Each hit gives you: rule name, PID, process, virtual address, matching string(s). Triage each:
- High specificity rule (tight strings, multi-condition) — trust the verdict, move to analysis
- Generic rule (single common string) — corroborate before acting
- Hit on a `csrss`, `services`, `svchost` — elevated priority; system processes don't normally contain arbitrary strings
- Hit on a user-mode browser / IDE / chat app — often benign (strings in page cache, clipboard, logs)
4. Pivot
For each confirmed hit:
volatility_malfind --pid Nto see if the hit sits inside an injected regionvolatility_dll_list --pid Nto see what module the offset maps into (if any)volatility_dump_process --pid N --mode vadand carve around the hit offset for offline triage- Derive new IoCs (neighboring strings, config blobs, mutex names) and re-scan
Rule Patterns That Work Well Against Memory
Config-block pattern (Cobalt Strike / Sliver style)
rule CS_Beacon_Config {
strings:
$magic = { 2E 2E 2E 2E ?? ?? 2E 2E 2E 2E } // XOR-key surrounded config
$sleep = "Beacon_mask" ascii wide
$post = "post-ex" ascii wide
condition:
2 of them
}Decoded-in-memory string pattern
Decrypted strings appear in memory even if encrypted on disk. Target what only shows up after unpacking:
rule FamilyX_Runtime_Strings {
strings:
$cmd1 = "!@#run_payload@#!" ascii wide
$cmd2 = "!@#beacon_check@#!" ascii wide
$err = "FamX: failed to allocate" ascii wide
condition:
any of them
}API-resolution pattern
Malware that dynamically resolves APIs leaves the names in memory:
rule Injector_API_Resolution {
strings:
$a1 = "NtAllocateVirtualMemory"
$a2 = "NtWriteVirtualMemory"
$a3 = "NtCreateThreadEx"
$a4 = "RtlAdjustPrivilege"
condition:
3 of them
}Benign software rarely stores these as plaintext strings (they're in import tables, not data).
Mutex / named-pipe pattern
rule Beacon_NamedPipe {
strings:
$p1 = "\\\\.\\pipe\\msagent_" ascii wide
$p2 = "\\\\.\\pipe\\postex_" ascii wide
$p3 = "\\\\.\\pipe\\status_" ascii wide
condition:
any of them
}False-Positive Control
- Never rely on single-string rules unless the string is a hash / GUID / long unique phrase
- Pair "would appear in malware" strings with "would not appear in benign software" strings
- Scope by process type: system processes (
lsass,services,svchost) have a tiny legitimate string set; hits there are almost always real - Every hit in a browser, email client, or IDE needs corroboration — those processes scrape the internet into memory and will match almost anything
Timeouts and Budgets
Whole-image YARA is slow. The MCP defaults to 600s; raise timeout for larger images or heavy rule packs. When iterating rules, scope to pid=N first to get fast feedback, then widen.
Common Pitfalls
- Rules with only wide strings miss ASCII-compiled binaries; use
ascii wideliberally - Very long strings may not match if the memory range they land in is paged out — prefer shorter signatures with stronger condition logic
- Vol3 yarascan wants a compiled or source `.yar` file, not a compiled
.yarc— pass source