Three-tier malware triage pipeline running across the home lab: an OpenCTI ingest layer, a fast static-analysis tier (50 samples / 30 min), a CAPEv2 sandbox tier for dynamic detonation, and a deep agentic tier where a local LLM (kimi-k2.6 via Ollama Cloud) drives Ghidra, radare2, and OpenCTI through 88 MCP tools. Outputs land in a markdown wiki, Discord, and as OpenCTI Notes — on cron, overnight, autonomously.
This project came out of the Kinsing infection writeup. The week our team spent dismembering a 5.9 MB Go binary, a Claude agent with Ghidra did in about two hours. Same coverage, same MITRE ATT&CK mapping, a few details I had missed. I could not stop thinking about it. This stack is what happened when I stopped just thinking about it: take that capability, turn it into infrastructure, put it on a cron, and let it work overnight.
The thesis is straightforward: a single LLM agent with the right toolbelt can do the boring eighty percent of reverse engineering at a quality bar I would accept from a human analyst. What I want from that arrangement is not an analyst replacement — it is a tireless first pass that turns the queue of "samples I will never get to" into a queue of "samples I have actual context on before I sit down." New samples arrive via OpenCTI connectors. A fast static-analysis tier triages volume. A CAPEv2 sandbox detonates select samples. The deep tier runs one sample every three hours through a local LLM agent (kimi-k2.6 via Ollama Cloud) wired up to 88 MCP tools spanning Ghidra, radare2, OpenCTI, CAPE, and the local malware corpus. The agent decides which tools to call in what order — I do not script it.
Infrastructure: three Proxmox 9 hosts (Lab1, Lab1BU, packetpursuit) plus a Mini Dell holding the malware corpus and wiki over NFS. OpenCTI runs on a dedicated VM (32 GB RAM, 200 GB disk after I bumped both during the connector backlog incident on day one). pp-hermes is an Ubuntu LXC on Lab1BU running NousResearch's Hermes-CLI agent. pp-cape is a separate VM on Lab1BU running CAPEv2 with a Linux Ubuntu 22 golden guest. The triage cron lives on pp-hermes; logs go to /var/log/triage; reports land in /srv/malware-corpus/wiki on SOC over NFS. The wiki is intentionally Karpathy-style — plain markdown files in a directory tree, no database, no application server.
First real find: asgardprotector, a 1.87 MB IExpress SFX dropper with an embedded Microsoft CAB containing AutoIt3.exe and a compiled A3X script (Terminals.a3x). Six minutes of agent time produced a report with file metadata pulled via exiftool and pefile, the embedded CAB confirmed via binwalk at offset 0x688BC, payload identification as the AutoIt-compiled-script-dropper pattern, an empty signature directory observation (the original wextract.exe is Microsoft-signed; this copy was repacked), and a wikilink graph connecting the sample to a sibling using the same build pattern. Every claim in the report carries a footnote pointing at the exact tool output that produced it. That last detail is what convinced me to ship the architecture.
What does not work yet: the Win11 CAPE guest. I defined a Windows 11 LTSC EVAL domain on pp-cape but the install never started — the OVMF firmware build that ships with Ubuntu 22.04 cannot walk Microsoft's El Torito boot catalog on the Win11 ISO. Three recovery paths documented (upgrade OVMF, extract the ESP as a separate FAT32 disk, VNC-driven manual install). For now PE samples skip dynamic detonation and proceed to the agent tier with static enrichment only. The pipeline is built to handle missing guests gracefully — better to ship the platform and add the guest than to block on it.
> Architecture_
INGEST
OpenCTI
STIX normalization + queue, polled by the pipeline every 30 min. Connectors throttled to prevent the 41k-deep backlog that ate the VM on day one.
MalwareBazaarURLhausRSSVM 200 · 32 GB
50 samples / 30 min
TIER 1 — STATIC
triage-fast.sh
Pure unix battery, no LLM, no network. Classifier scores each sample and assigns a tier. Sub-minute per sample.
filepefilebinwalkrabin2yarastringsSFX config extractor
tier = deep
TIER 2 — SANDBOX
CAPEv2 dynamic detonation
pp-cape VM 120, Ubuntu 22 guest live, Win11 guest in build. PCAP + process tree + dropped files routed back into the per-sample wiki dir.
process treePCAPdropped filescape-mcp
enqueued for deep dive
TIER 3 — AGENT
Hermes + kimi-k2.6 via Ollama Cloud
pp-hermes LXC 110. 88 MCP tools across five servers. One sample every three hours, throttled by design.
pyghidra-mcpradare2-mcpopencti-mcpcape-mcpfilesystem-mcp
writes report + entities
PUBLISH
Wiki · Discord · OpenCTI Note · Blog
Karpathy-style markdown corpus on SOC NFS. Discord summary as Titus. Note written back to the source artifact. ThreatWatch generator publishes to this site.
raw/analysesby-familytechniquesDiscord webhookOpenCTI Note
Sample lifecycle. A new artifact lands in OpenCTI via a connector. The fast tier picks it up on the next 30-minute cron, runs the static battery, scores it, and writes a per-sample directory into the wiki under raw/analyses/<sha256>/. If the sample is a Linux ELF, the sandbox tier detonates it in CAPE and appends the dynamic artifacts. The deep tier picks one sample from the queue every three hours, runs Hermes against it, and the agent produces a report.md, links it into the family page under by-family/<family>/, writes a Discord summary as Titus, and posts an OpenCTI Note back to the artifact that started it all. Everything is idempotent, everything is logged, and everything is replayable.
> pipeline-status.sh_
=== Pipeline lock ===
not running
=== Recent log (last cycle) ===
2026-05-27T03:30:01 START triage-pipeline (max_wall=25m, max_samples=50)
2026-05-27T03:30:14 queue=2 artifacts pending triage
2026-05-27T03:30:14 [1/2] sha=8f28849296f4 START
2026-05-27T03:30:23 tier=deep
2026-05-27T03:30:27 opencti-note=885b1433-f411-494c-82c4-a66788f720fe
2026-05-27T03:30:27 enqueued for deep dive
2026-05-27T03:30:27 [2/2] sha=fc944b5465a4 START
2026-05-27T03:30:34 tier=deep
2026-05-27T03:30:41 opencti-note=97aa720d-1e1e-48f5-895a-751bc2e24cde
2026-05-27T03:30:41 DONE processed=2 errors=0 elapsed=0m
=== Tier counts (all-time) ===
deep 516
skip 55
TOTAL 571
=== Top 10 families ===
coinminer 21 acrstealer 16 connectwise 9
silverfox 8 hippamsascom 8 lummastealer 7
> sample wiki entry_
asgardprotector: d59dc2f2 — IExpress SFX dropper embedding AutoIt3 + compiled A3X script
family: asgardprotector
type: analysis
confidence: medium
2026-05-27
Executive Summary
Microsoft Cabinet self-extractor ([[iexpress-sfx-dropper]]) repurposed as a silent dropper. Extracts AutoIt3.exe and a compiled .a3x script (Terminals.a3x) to a temp directory, then launches the script via the AutoIt interpreter — an [[autoit-compiled-script-dropper]] pattern. No CAPE detonation available; payload behavior is opaque statically. A sibling sample (d364a2f6, StatingConnectors.exe) uses the same build pattern with Dayton.a3x. The outer SFX carries a fabricated PE timestamp (2085).
What It Is
- File:
SomaliaCruises.exe, PE32+ x86-64, 1.87 MB.
- Build: MSVC 14.30 (VS 2022), linker version 14.30, compiled timestamp
2085:08:19 (fabricated).
- Signature: Unsigned — the certificate directory is empty. The original
wextract.exe is Microsoft-signed, but this copy has been modified/repacked.
- PDB:
wextract.pdb, GUID 94098867-5fc9-b268-c53c-be826110dd1e.
- Embedded archive: Microsoft Cabinet at offset
0x688BC (428,220), 1,484,468 bytes, containing 2 files.
Every claim is footnoted to the tool output that produced it. The wiki has 4 family pages, 7 deep analyses, and 122 OpenCTI Notes as of writing — counters above update live as the agent works.
Read the full writeup: the blog post Building an Autonomous Malware Triage Stack covers the architecture in depth, including the OpenCTI connector throttling story, the SFX config extractor as an example of agent-driven tool-building, the OVMF wall blocking the Win11 sandbox guest, and the practical lessons from running the stack for two weeks.