Malware Triage

SkillSecurity

Rapid assessment, classification, and prioritization of malware samples. Use when you need to perform initial malware assessment, classify a sample's type and family, determine analysis priority, identify quick indicators, or decide on next analysis steps.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Malware Triage skill

What this skill tells your AI

The instructions your AI receives, as published by gl0bal01/malware-analysis-claude-skills in malware-triage/SKILL.md and read by ahel’s review.

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_ROOT is 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. No chmod +x, no wine, 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 cat a strings dump. Save to a file, wc -l, then grep/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 saysAction
Mono/.Net assemblyRecord 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/textRecord hashes, hand back to orchestrator → specialized-file-analyzer
PE32 / PE32+ (not .NET)Continue below
data / unrecognizedContinue 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 output

Read every section of the output. What matters:

OutputInterpretation
.NET: YESStop, route to specialized-file-analyzer
Compile timestamp in the future / before 2000Forged; ignore for dating. Rich header linker info is harder to fake
Overall entropy > 7.0, or executable section > 6.8, or ! markersPacked/encrypted — see Packed Samples
Entry point outside .text/CODE, or in last sectionPacker stub or appended code
Import count < 10, or only LoadLibrary/GetProcAddress/VirtualAllocRuntime 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 presentAppended data: config, second-stage payload, or installer archive. Carve it: python3 -c "..." using the reported offset, then file the result
Signature presentVerify claimed signer; revoked/self-signed/mismatched = red flag. Unsigned is neutral
PDB pathProject/user names, build environment — high-value attribution string
Resources with high entropy or large sizeEmbedded payload. Note type/size; extract in deep analysis
TLS callbacksCode runs before entry point — anti-debug or early unpacking
Version info mimicking Microsoft/Adobe/etc. while unsignedMasquerading

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, paths

Then 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 -40

Note 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.

PackerIndicatorsUnpack on host?
UPXUPX0/UPX1 sections, UPX! in overlayYes: upx -d "$S" -o "$W/unpacked.exe"
Themida / WinLicense.themida, .winlicense sections, huge protected sectionNo — dynamic analysis
VMProtect.vmp0/.vmp1No — dynamic analysis
ASPack / MPRESS / Petite / Enigma / Upacknamed sections (.aspack, .MPRESS1, .petite, .enigma1, .Upack)Rarely — dynamic analysis
Custom / unknownhigh entropy, few imports, no known section namesNo — 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.

TypeTypical evidence
Trojan / RAT / Backdoorsocket or WinHTTP + command dispatch strings, screen/keyboard APIs, persistence
RansomwareCrypt* APIs, file enumeration, vssadmin delete shadows, ransom-note strings, wallet addresses
Infostealerbrowser profile paths (Login Data, cookies.sqlite), wallet dirs, CryptUnprotectData, exfil URL
Dropper / Loadersmall binary, high-entropy resource or overlay, URLDownloadToFile, WriteFile + CreateProcess, few other capabilities
Cryptominerpool URLs (stratum+tcp://), xmrig, high CPU-related config strings
WormSMB/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/powershell strings → LOLBin chain)?
  • Files: paths from strings; temp/AppData drops if GetTempPath/SHGetFolderPath imported.
  • Registry: Run keys, service creation, IFEO from strings/imports.
  • Network: protocol (WinHTTP/WinINet → HTTP(S); socket/connect → raw TCP; DnsQuery only → 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

PriorityWhen
ImmediateUnknown/undetected, incident-related, destructive capability, APT indicators, matches current threat intel
StandardKnown family variant, commodity malware with existing coverage
LowWell-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")
EOF

Also 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'
done

Produce a ranking table (sample, type, packed, detections, priority, one-line reason), then run the full workflow on Immediate samples first.

Output

  1. Print the triage report (template below, filled in — no placeholders left).
  2. Append to analysis_state.md in the user's working directory using the orchestrator's structure: hashes, type, priority, classification, threat level, triage findings, IOCs (defanged), next-phase recommendation.
  3. 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 patterns
  • references/triage_checklist.md — full checklist, decision tree, dynamic go/no-go criteria, tool reference
  • scripts/pe_info.py — PE header/section/import/resource/overlay/signature summary (needs pefile)
  • scripts/hash_calculator.py — MD5/SHA1/SHA256
  • ../scripts/ioc_extract.py — IOC extraction and defanging from any text

Signals

GitHub stars
46
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
malware-triage-gl0bal01
Source
github.com/gl0bal01/malware-analysis-claude-skills