malware-triage
Skill46 starsChanged 2 months agoMITView on GitHub
Rapid static assessment, classification, and prioritization of malware samples. Use for the first look at any unknown file — hashes, file type, packing, imports, strings, initial IOCs, threat level, and the decision on which deep-analysis phase comes next. Claude runs the static tooling on the host itself; the sample is never executed.
- Installs packages
4 other projects use a version of this.
Adopted by
Most recently taken up by
- briiirussell/cybersecurity-skillstheir own version, first seen Nov 1, 2026
- dandye/adk_runbookstheir own version, first seen Nov 1, 2026
- TaiMaBenJi/taima-skillsword for word, first seen Oct 11, 2026
- ftrout/secops-claude-skillstheir own version, first seen Sep 18, 2026
Other versions4 projects use a version of this.
Word for word · 1
- TaiMaBenJi/taima-skills★ 1100% same
Edited · 0
None found.
Wrote their own version · 3
- briiirussell/cybersecurity-skills★ 489same name
- dandye/adk_runbooks★ 88same name
- ftrout/secops-claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository6 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- detection-engineerSkill
- malware-dynamic-analysisSkill
- malware-report-writerSkill
- malware-analysisSkill
- specialized-file-analyzerSkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 3 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 14
Never execute the sample: Only static tools touch it: file, strings, pe_info.py, upx -d, 7z l, hashing.
- Distinctive: line 17
Tool check first: Run once per session; note what is missing and degrade rather than stop:
- Very specific: line 22
Big outputs: never cat a strings dump. Save to a file, wc -l, then grep/head.
- Distinctive: line 56
Read every section of the output.
- Very specific: line 111
If UPX unpacking succeeds: hash the unpacked file, re-run Steps 3-4 on it, record both hashes (packed = delivery artifact, unpacked = what …
- Distinctive: line 138
Registry: Run keys, service creation, IFEO from strings/imports.
- Very specific: line 220
Before handing back: all three hashes.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Malware Triage
First phase for every sample. You run static tools on the host, interpret the output, classify the sample, and decide the next phase. Target: 5-15 minutes per sample.
Execution Model
- You run the commands. You have Bash. Execute every command in this skill yourself and interpret the output. Do not ask the user to run tools or paste results unless a tool is missing and cannot be installed.
- Locate skill files. Scripts and reference files ship in this skill's directory. Set
R="${CLAUDE_PLUGIN_ROOT:-<dir containing this SKILL.md>}"once (when installed as a plugin$CLAUDE_PLUGIN_ROOTis set; otherwise it is this skill folder). Your working directory is the user's analysis workspace, so prefix every script path below with$R, e.g.python3 "$R"/scripts/ioc_extract.py. - Never execute the sample. Only static tools touch it:
file,strings,pe_info.py,upx -d,7z l, hashing. Nochmod +x, nowine, no./sample. - Never upload the sample to any service without explicit consent. Hash lookups are fine; file uploads are not.
- Script paths are relative to this skill directory. From the repo/skill root:
malware-triage/scripts/pe_info.py,malware-triage/scripts/hash_calculator.py,scripts/ioc_extract.py. Resolve them from wherever this SKILL.md lives. - Tool check first. Run once per session; note what is missing and degrade rather than stop:
command -v file strings upx 7z yara; python3 -c "import pefile" 2>&1 | tail -1 # pefile missing -> pip install pefile (needed by pe_info.py) - Big outputs: never
cata strings dump. Save to a file,wc -l, thengrep/head. - Ask the user only for: the sample path, context (where it came from, incident ID, anything already known), and reputation results if no MCP server is available.
Workflow
Step 1 — Identify and hash
S=/path/to/sample
file "$S"; ls -l "$S"
python3 malware-triage/scripts/hash_calculator.py "$S"Record MD5/SHA1/SHA256, size, file output. Then route on the file output:
file says | Action |
Mono/.Net assembly | Record hashes, hand back to orchestrator → specialized-file-analyzer (check this before PE) |
Microsoft Office, PDF document, ELF, MS Windows shortcut, Zip/RAR/7-zip, ISO 9660, Microsoft Disk Image, HTML document, script/text | Record hashes, hand back to orchestrator → specialized-file-analyzer |
PE32 / PE32+ (not .NET) | Continue below |
data / unrecognized | Continue at Unknown Files |
Step 2 — Reputation
- MCP available (VirusTotal, Threat Intel / MalwareBazaar): look up the SHA256. Record detection ratio, family labels, first-seen date, tags. Look up any imphash and section hashes too.
- No MCP: give the user the SHA256 and ask them to check VirusTotal / MalwareBazaar while you continue. Do not block on it. Zero detections on a fresh hash means nothing; 0 detections on an old hash is informative.
- Reputation is a hint, not the verdict. Static findings override AV labels.
Step 3 — PE static summary
python3 malware-triage/scripts/pe_info.py "$S" # add --json for structured outputRead every section of the output. What matters:
| Output | Interpretation |
.NET: YES | Stop, route to specialized-file-analyzer |
| Compile timestamp in the future / before 2000 | Forged; ignore for dating. Rich header linker info is harder to fake |
Overall entropy > 7.0, or executable section > 6.8, or ! markers | Packed/encrypted — see Packed Samples |
Entry point outside .text/CODE, or in last section | Packer stub or appended code |
Import count < 10, or only LoadLibrary/GetProcAddress/VirtualAlloc | Runtime API resolution — packed or deliberately hiding imports |
| Suspicious import categories (injection, keylogging, network, anti-debug, crypto, persistence) | Map each to a capability; cross-check with references/indicators.md |
| Overlay present | Appended data: config, second-stage payload, or installer archive. Carve it: python3 -c "..." using the reported offset, then file the result |
| Signature present | Verify claimed signer; revoked/self-signed/mismatched = red flag. Unsigned is neutral |
| PDB path | Project/user names, build environment — high-value attribution string |
| Resources with high entropy or large size | Embedded payload. Note type/size; extract in deep analysis |
| TLS callbacks | Code runs before entry point — anti-debug or early unpacking |
| Version info mimicking Microsoft/Adobe/etc. while unsigned | Masquerading |
Step 4 — Strings and IOCs
W=triage_$(basename "$S") # work dir
mkdir -p "$W"
strings -a -n 6 "$S" > "$W/strings_ascii.txt"
strings -a -n 6 -e l "$S" > "$W/strings_wide.txt" # UTF-16LE, essential for Windows binaries
wc -l "$W"/strings_*.txt
python3 scripts/ioc_extract.py "$W"/strings_*.txt # defanged IPs, domains, URLs, emails, hashes, reg keys, pathsThen targeted greps (adjust after reading the ioc_extract output):
grep -ihE 'HKEY_|HKLM|HKCU|CurrentVersion\\Run|schtasks|sc create|netsh|vssadmin|bcdedit|wmic' "$W"/strings_*.txt | sort -u | head -40
grep -ihE 'user-agent|mozilla/|POST |GET |Content-Type|\.php|\.onion|/gate|/panel' "$W"/strings_*.txt | sort -u | head -40
grep -ihE 'mutex|Global\\|Local\\|\\pipe\\' "$W"/strings_*.txt | sort -u | head -20
grep -ihE 'IsDebuggerPresent|VMware|VBox|vbox|QEMU|Xen|sandbox|SbieDll|wireshark|procmon|ollydbg|x64dbg' "$W"/strings_*.txt | sort -u
grep -ihE 'bitcoin|monero|\.onion|decrypt|ransom|your files|README' "$W"/strings_*.txt | sort -u | head -20
grep -ihE '\.exe|\.dll|\.bat|\.ps1|\.vbs|\.tmp' "$W"/strings_*.txt | grep -viE 'kernel32|ntdll|user32|advapi32|msvcr|api-ms-win' | sort -u | head -40Note what is absent too: a binary with network imports but no URL/IP strings is decrypting its config at runtime.
Suspicious-API and string categories: references/indicators.md.
Packed Samples
Triggered by Step 3 entropy/import findings.
| Packer | Indicators | Unpack on host? |
| UPX | UPX0/UPX1 sections, UPX! in overlay | Yes: upx -d "$S" -o "$W/unpacked.exe" |
| Themida / WinLicense | .themida, .winlicense sections, huge protected section | No — dynamic analysis |
| VMProtect | .vmp0/.vmp1 | No — dynamic analysis |
| ASPack / MPRESS / Petite / Enigma / Upack | named sections (.aspack, .MPRESS1, .petite, .enigma1, .Upack) | Rarely — dynamic analysis |
| Custom / unknown | high entropy, few imports, no known section names | No — dynamic analysis |
If UPX unpacking succeeds: hash the unpacked file, re-run Steps 3-4 on it, record both hashes (packed = delivery artifact, unpacked = what matches families). If upx -d fails, the UPX header was tampered; treat as custom.
Set sophistication: known packer → at least Moderate; commercial protector → Advanced; custom packer → Advanced/APT. Add "requires dynamic analysis to reveal imports/strings" to next steps.
Step 5 — Classify
Combine imports, strings, reputation, and context. Consult references/indicators.md for the patterns.
| Type | Typical evidence |
| Trojan / RAT / Backdoor | socket or WinHTTP + command dispatch strings, screen/keyboard APIs, persistence |
| Ransomware | Crypt* APIs, file enumeration, vssadmin delete shadows, ransom-note strings, wallet addresses |
| Infostealer | browser profile paths (Login Data, cookies.sqlite), wallet dirs, CryptUnprotectData, exfil URL |
| Dropper / Loader | small binary, high-entropy resource or overlay, URLDownloadToFile, WriteFile + CreateProcess, few other capabilities |
| Cryptominer | pool URLs (stratum+tcp://), xmrig, high CPU-related config strings |
| Worm | SMB/RPC APIs, network share enumeration, removable-drive checks |
Threat level: Critical (destructive, ransomware, APT) / High (data theft, full compromise) / Medium (limited capability, targeted) / Low (adware, PUP, commodity). Sophistication: Simple / Moderate / Advanced / APT-level, driven by protection, evasion, and custom code. Verdict: Malicious / Suspicious / Benign. Benign requires positive evidence (valid signature from a plausible vendor, expected imports for its stated purpose, reputation clean over time), not just absence of red flags.
Step 6 — Predict behavior
Turn static evidence into a watch list for the dynamic phase. Each prediction names the evidence:
- Process: child processes or injection expected? Which targets (
CreateRemoteThread+OpenProcess→ injection;CreateProcess+cmd/powershellstrings → LOLBin chain)? - Files: paths from strings; temp/AppData drops if
GetTempPath/SHGetFolderPathimported. - Registry: Run keys, service creation, IFEO from strings/imports.
- Network: protocol (WinHTTP/WinINet → HTTP(S);
socket/connect→ raw TCP;DnsQueryonly → DNS tunnelling/DGA), hard-coded C2 vs runtime-decrypted, likely beacon. - Persistence: mechanism and location.
- Evasion: anti-VM/anti-debug strings → plan for bypass (
malware-dynamic-analysis/references/anti_analysis_bypass.md).
These predictions become the Procmon/Sysmon filters and the observation plan for malware-dynamic-analysis.
Step 7 — Priority and next phase
| Priority | When |
| Immediate | Unknown/undetected, incident-related, destructive capability, APT indicators, matches current threat intel |
| Standard | Known family variant, commodity malware with existing coverage |
| Low | Well-documented sample, adware/PUP, old, likely false positive |
Next phase: malware-dynamic-analysis for PE files that are packed, have runtime-resolved config, or need behavioral confirmation; detection-engineer + malware-report-writer directly when the sample is a known variant and static IOCs suffice; Benign closes the sample.
Unknown Files
file returned data or something unhelpful:
xxd "$S" | head -20 # magic bytes, structure
strings -a -n 8 "$S" | head -50
python3 - "$S" <<'EOF' # single-byte XOR brute force for a hidden PE
import sys; b=open(sys.argv[1],'rb').read()
for k in range(1,256):
d=bytes(x^k for x in b[:4096])
if d[:2]==b'MZ' or b'This program cannot' in d: print(f"XOR key 0x{k:02x} reveals PE header")
EOFAlso check: base64 blob ([A-Za-z0-9+/]{100,}), gzip/zlib magic (1f 8b, 78 9c), reversed PE (ZM at end), shellcode (starts with fc e8 / e8 00 00 00 00 / 55 8b ec). Decode what you find, file the result, and re-route.
Batch Triage
For N samples, do a quick pass on all before deep-diving any:
for f in samples/*; do
echo "== $f"; file "$f"; sha256sum "$f"
python3 malware-triage/scripts/pe_info.py "$f" 2>/dev/null | grep -E '^\.NET:|packed|imported functions'
doneProduce a ranking table (sample, type, packed, detections, priority, one-line reason), then run the full workflow on Immediate samples first.
Output
- Print the triage report (template below, filled in — no placeholders left).
- Append to
analysis_state.mdin the user's working directory using the orchestrator's structure: hashes, type, priority, classification, threat level, triage findings, IOCs (defanged), next-phase recommendation. - Recommend the next phase with reasoning, then wait for the user.
## Triage Report — [filename]
**Hashes:** MD5 … / SHA1 … / SHA256 … **Size:** … bytes **Type:** … **Packed:** No | Yes (packer)
**Reputation:** VT x/y, family label(s), first seen … | not checked
### Static Findings
- Compile time / linker / signature / PDB
- Sections + entropy (flag anomalies)
- Suspicious imports by category → capability
- Notable strings: URLs, IPs, paths, registry, mutex, UA, commands
- Resources / overlay / TLS callbacks
### Classification
**Verdict:** Malicious | Suspicious | Benign **Type:** … **Threat:** Critical | High | Medium | Low **Sophistication:** …
**Capabilities:** …
### Predicted Behavior
Process / Files / Registry / Network / Persistence / Evasion — each with the evidence behind it
### Initial IOCs (defanged)
File: hashes, imphash, dropped names · Network: … · Host: registry, paths, mutex
### Recommendation
**Priority:** … **Next phase:** … **Why:** …Quality Gate
Before handing back: all three hashes; file type; packing status with evidence; imports categorized; strings run in both ASCII and UTF-16; IOCs extracted and defanged; classification with reasoning; predictions tied to evidence; state file updated.
References
references/indicators.md— suspicious API imports, string patterns, behavioral indicators, packer signatures, classification patternsreferences/triage_checklist.md— full checklist, decision tree, dynamic go/no-go criteria, tool referencescripts/pe_info.py— PE header/section/import/resource/overlay/signature summary (needspefile)scripts/hash_calculator.py— MD5/SHA1/SHA256../scripts/ioc_extract.py— IOC extraction and defanging from any text
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

