Files
tabledevil 7ad1cc8465 Pin ubuntu:22.04, work around upstream rot, smoke test
APT-Hunter is unmaintained and breaks on modern dependency versions.
Workarounds:
- Pin ubuntu:22.04 (Python 3.10) — base for venv install.
- Pin netaddr<1.0 — 1.x removed IPAddress.is_private().
- Add flatten_json (missing from upstream requirements.txt).
- Patch EvtxDetection.py via sed: strip ' UTC' suffix from timestamps
  before parse() since dateutil rejects 'Z UTC' (Microsoft EVTX bug).

start.sh: pre-mkdir the nested output/ dir APT-Hunter expects.
test_smoke.sh: glob the actually-produced /output/apthunter_<ts>/output/
nested layout. Default SUBSET=DeepBlueCLI documented; YamatoSecurity is a
working alternative and avoids the few corpora that hit other parser bugs.

Validated end-to-end on amd64 Linux: 5/5 PASS on YamatoSecurity (16 EVTX),
1753 detections, 24K xlsx + 84K TimeSketch CSV produced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:20:19 +02:00

63 lines
2.0 KiB
Bash
Executable File

#!/bin/bash
# Smoke test for APT-Hunter: fetch sample EVTX, run, check outputs.
#
# Available SUBSET values (under test-data/sample-evtx/):
# DeepBlueCLI 21 files, ~1min
# YamatoSecurity 16 files, ~30s
# EVTX-ATTACK-SAMPLES 278 files, ~10min
# EVTX-to-MITRE-Attack 284 files, ~10min
# "" 599 files, ~20min
#
# Env vars: TAG=ls-apthunter:test SUBSET=DeepBlueCLI KEEP_DATA=1
set -u
TAG="${TAG:-ls-apthunter:test}"
SUBSET="${SUBSET:-DeepBlueCLI}"
KEEP_DATA="${KEEP_DATA:-0}"
cd "$(dirname "$0")"
ROOT="$(pwd)"
DATA="$ROOT/test-data/sample-evtx"
OUT="$(mktemp -d)"
trap 'rm -rf "$OUT"; [ "$KEEP_DATA" = 0 ] && rm -rf "$ROOT/test-data"' EXIT
pass=0; fail=0
ok() { echo "PASS $1"; pass=$((pass+1)); }
bad() { echo "FAIL $1"; fail=$((fail+1)); }
if docker image inspect "$TAG" >/dev/null 2>&1; then
ok "image $TAG present"
else
bad "image $TAG not present"; exit 1
fi
if [ ! -d "$DATA" ]; then
echo "Fetching sample EVTX..."
./fetch-test-data.sh >/dev/null
fi
SCAN="$DATA/$SUBSET"; [ -z "$SUBSET" ] && SCAN="$DATA"
n=$(find "$SCAN" -name "*.evtx" | wc -l | tr -d ' ')
[ "$n" -gt 0 ] && ok "found $n EVTX in ${SUBSET:-<all>}" || { bad "no EVTX"; exit 1; }
echo "Running scan..."
if docker run --rm --network=none -v "$SCAN:/data:ro" -v "$OUT:/output" "$TAG" >"$OUT/.run.log" 2>&1; then
ok "container exited cleanly"
else
bad "container non-zero"; tail -20 "$OUT/.run.log"
fi
# APT-Hunter writes /output/apthunter_<ts>/output/apthunter_<ts>_{Report.xlsx,TimeSketch.csv,...}
xlsx=$(ls "$OUT"/apthunter_*/output/apthunter_*_Report.xlsx 2>/dev/null | head -1)
ts=$(ls "$OUT"/apthunter_*/output/apthunter_*_TimeSketch.csv 2>/dev/null | head -1)
[ -s "$xlsx" ] && ok "Excel report exists ($(du -h "$xlsx" | cut -f1))" || bad "xlsx missing"
[ -s "$ts" ] && ok "TimeSketch CSV exists ($(du -h "$ts" | cut -f1))" || bad "csv missing"
if [ -s "$ts" ]; then
detections=$(($(wc -l < "$ts") - 1))
echo
echo "Detections: $detections"
fi
echo
echo "Summary: $pass pass, $fail fail"
[ "$fail" -eq 0 ]