Files
reverse-skills-max/vendor-new/malware-analysis-claude-skills/tests/run.sh

146 lines
6.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# End-to-end test harness for the malware-analysis skills package.
#
# Proves the host-side tooling works on realistic fixtures: the Python
# scripts every skill depends on, plus the detection rules the skills
# ship as examples. No malware is involved — fixtures are synthetic
# (tests/make_pe.py builds a benign PE that only calls ExitProcess).
#
# Usage: bash tests/run.sh
# Exit 0 = all required checks pass. Optional tool checks (pefile, yara,
# sigma, olevba) are skipped with a note when the tool is absent, so the
# harness runs on a bare box and does more when deps are installed.
set -u
cd "$(dirname "$0")/.."
ROOT=$(pwd)
PY=python3
[ -x .venv/bin/python ] && PY=.venv/bin/python
mkdir -p tests/out
pass=0; fail=0; skip=0
ok() { echo " ok $1"; pass=$((pass+1)); }
bad() { echo " FAIL $1"; fail=$((fail+1)); }
skipm(){ echo " skip $1"; skip=$((skip+1)); }
have() { command -v "$1" >/dev/null 2>&1; }
pyhas(){ $PY -c "import $1" >/dev/null 2>&1; }
# assert: <label> <needle> <<< "$output"
assert(){ if grep -qF -- "$2" <<<"$3"; then ok "$1"; else bad "$1 (missing: $2)"; fi; }
refute(){ if grep -qF -- "$2" <<<"$3"; then bad "$1 (unexpected: $2)"; else ok "$1"; fi; }
echo "== 1. script self-tests"
for s in scripts/ioc_extract.py malware-dynamic-analysis/scripts/procmon_summary.py malware-dynamic-analysis/scripts/sysmon_summary.py; do
if $PY "$s" --self-test >/dev/null 2>&1; then ok "$s"; else bad "$s"; fi
done
echo "== 2. PE triage (pe_info.py on synthetic PE)"
$PY tests/make_pe.py tests/out/invoice_2024.exe >/dev/null
[ -f tests/out/invoice_2024.exe ] && ok "PE fixture built" || bad "PE fixture build"
if pyhas pefile; then
o=$($PY malware-triage/scripts/pe_info.py tests/out/invoice_2024.exe)
assert "detects .NET=no" ".NET: no" "$o"
assert "categorizes injection" "injection: CreateRemoteThread" "$o"
assert "categorizes network" "network: InternetOpenA" "$o"
assert "categorizes persistence" "persistence: RegCreateKeyExA" "$o"
assert "stable imphash" "dfcaebd44ff7676285215e9d856415f3" "$o"
assert "finds overlay" "Overlay size: 530 bytes" "$o"
# deterministic hash
h=$($PY malware-triage/scripts/hash_calculator.py tests/out/invoice_2024.exe | grep -i sha256)
assert "hash_calculator SHA256" "af747150f9afc0937a6b62755f9bd84cfb88726370f6007ac03f8f7504d38c4d" "$h"
else
skipm "pe_info.py (pip install pefile)"
fi
echo "== 3. Procmon evidence parsing"
o=$($PY malware-dynamic-analysis/scripts/procmon_summary.py tests/fixtures/evidence/procmon.csv --process invoice_2024.exe)
assert "process tree nests cmd" " cmd.exe (PID 5102)" "$o"
assert "grandchild named" "PING.EXE (PID 5140)" "$o"
assert "dropped file" "svc.exe" "$o"
assert "persistence flagged" "PERSISTENCE" "$o"
assert "self-deletion" "Files deleted (1)" "$o"
refute "no unrelated process" "chrome.exe:2100" "$o"
echo "== 4. Sysmon evidence parsing"
o=$($PY malware-dynamic-analysis/scripts/sysmon_summary.py tests/fixtures/evidence/sysmon.json --process invoice_2024.exe,svc.exe)
assert "injection remote thread" "-> C:\\Windows\\explorer.exe" "$o"
assert "high-rights access" "0x1F0FFF" "$o"
assert "run key persistence" "PERSISTENCE" "$o"
assert "beacon detected" "BEACON-LIKE" "$o"
assert "named pipe IOC" "\\testfixture" "$o"
assert "unsigned dll load" "hlp.dll signed=false" "$o"
echo "== 5. IOC extraction + defang"
o=$(cat tests/fixtures/evidence/*.txt tests/fixtures/evidence/procmon.csv | $PY scripts/ioc_extract.py)
assert "C2 IP defanged" "203[.]0[.]113[.]5" "$o"
assert "C2 domain defanged" "update-cdn[.]example[.]test" "$o"
refute "no live C2 dot" "203.0.113.5" "$o"
o2=$(echo "hxxps://update-cdn[.]example[.]test/gate[.]php" | $PY scripts/ioc_extract.py --refang)
assert "refang restores URL" "update-cdn.example.test" "$o2"
echo "== 6. Script deobfuscation (host-side decoders from the skill)"
o=$($PY - tests/fixtures/scripts/malicious.ps1 <<'EOF'
import base64, re, sys
src = open(sys.argv[1], encoding="utf-8", errors="replace").read()
for m in re.finditer(r"[A-Za-z0-9+/]{40,}={0,2}", src):
raw = base64.b64decode(m.group(0) + "=" * (-len(m.group(0)) % 4))
for enc in ("utf-16le", "utf-8"):
try:
print(raw.decode(enc)); break
except UnicodeDecodeError:
continue
EOF
)
assert "PowerShell base64 decoded" "DownloadString" "$o"
o=$($PY - tests/fixtures/scripts/malicious.vbs <<'EOF'
import re, sys
c = open(sys.argv[1], encoding="utf-8", errors="replace").read()
c = re.sub(r"Chr[Ww]?\((\d+)\)", lambda m: '"' + chr(int(m.group(1))) + '"', c)
c = re.sub(r'"\s*&\s*"', "", c)
c = re.sub(r'StrReverse\("([^"]*)"\)', lambda m: '"' + m.group(1)[::-1] + '"', c)
for m in re.finditer(r'Replace\("([^"]*)",\s*"([^"]*)",\s*"([^"]*)"\)', c):
c = c.replace(m.group(0), '"' + m.group(1).replace(m.group(2), m.group(3)) + '"')
print(c)
EOF
)
assert "VBS Chr() resolved" '"cmd"' "$o"
assert "VBS StrReverse resolved" "calc.exe" "$o"
echo "== 7. Detection rules validate (optional)"
if have sigma || [ -x .venv/bin/sigma ]; then
SIGMA=sigma; [ -x .venv/bin/sigma ] && SIGMA=.venv/bin/sigma
n=0
rm -f tests/out/sigma_*.yml
$PY tests/extract_rules.py detection-engineer/SKILL.md tests/out/sigma_
for f in tests/out/sigma_*.yml; do
[ -f "$f" ] || continue
if $SIGMA check "$f" >/dev/null 2>&1; then ok "sigma check $(basename "$f")"; else bad "sigma check $(basename "$f")"; fi
n=$((n+1))
done
[ "$n" -gt 0 ] || skipm "no sigma rules extracted"
else
skipm "sigma check (pip install sigma-cli)"
fi
echo "== 8. YARA rule tests against PE fixture (optional)"
if { have yara || pyhas yara; } && [ -f tests/fixtures/yara/fixture.yar ]; then
if pyhas yara; then
o=$($PY - tests/fixtures/yara/fixture.yar tests/out/invoice_2024.exe tests/extract_rules.py <<'EOF'
import yara, sys
r = yara.compile(sys.argv[1])
print("MATCH" if r.match(sys.argv[2]) else "NOMATCH", "sample")
print("MATCH" if r.match(sys.argv[3]) else "NOMATCH", "clean")
EOF
)
assert "YARA matches sample" "MATCH sample" "$o"
assert "YARA clean no-match" "NOMATCH clean" "$o"
elif have yara; then
yara -w tests/fixtures/yara/fixture.yar tests/out/invoice_2024.exe | grep -q fixture && ok "yara matches sample" || bad "yara sample"
fi
else
skipm "yara (pip install yara-python)"
fi
echo
echo "== summary: $pass passed, $fail failed, $skip skipped"
[ "$fail" -eq 0 ]