Earlier this summer at Black Hat USA, I gave a talk about what happens when you point Claude Code, a general-purpose coding harness, at malware. We call the resulting system Mortex.
We aren't malware analysts. That's the point. Getting there took more rebuilds than we expected, and one of the obstacles wasn't the malware at all.
From one result to a system
Attackers have to put something in the field, and that leaves a footprint. Take a sample apart and you can pull domains, IPs, execution behavior, and sometimes a trail into a wider campaign. One sample alone isn't attribution. Correlated context is what turns it into the bigger picture: variants, shared infrastructure, and the campaign behind them.
That correlation used to cost twice over. Malware analysis takes highly skilled labor, the kind of low-level OS knowledge and behavioral intuition that takes years to build. It also takes isolated, hardened lab infrastructure, because you're effectively detonating a bomb and the last thing you want is a sample escaping. Sandboxes already automated pieces of that workflow. They didn't eliminate the tooling, the maintenance, or the analyst judgment. Every additional sample still consumed both.
Then one result changed the question. Mallory CEO, Jonathan Cran, ran a quick spike, Claude against a real sample, and got back a coherent kill chain. That result proved Claude could do the work. Turning it into something we could trust on the next sample, and the one after that, was a separate problem.
So we made a bet: could one good result become a repeatable system? We called the experiment Mortex.
Version zero was deliberately thin. Claude Code became the harness, running on Cloud Run. A sample came in. Three personas (an orchestrator, an analyst, and a report writer) shared one mutable workspace. Skills wrapped the usual tools: triage, Ghidra, YARA, unpacking, report generation. Audit hooks fired on every tool call. Collection, interpretation, and authorship still lived in the same place.

Adaptivity isn't coordination
The report at the end was a verdict. It told us almost nothing about how the run actually happened.
So we built Hotwash, an after-action agent that reads the hook-generated event stream: dispatches, tool calls, failures, retries, and where the time went.
Hotwash re-reads that history to judge whether the report is good enough for a hunter, and whether the pipeline is healthy for operators. It doesn't change the underlying verdict.

The next wall wasn't the sample. It was the multi-agent system we'd built around it.
Hotwash surfaced the finding that forced a rebuild: two parallel extraction jobs had stepped on each other. One deleted a directory while the other was still writing to it, and the run only recovered after three failures and a full rerun. Recovery was the trap: shared state had no owner, and adaptivity wasn't coordination.

That collision drew a boundary we hadn't had before. In version zero, the agent owned both taking the sample apart and analyzing it, which is exactly how a coordination failure ended up corrupting the collection itself. The agent was also spending a finite run budget discovering tool compatibility and repeating mechanical work.
Now code alone collects. It identifies the artifact, routes packed, native PE or ELF, and managed inputs into bounded analyzers, and seals the results into an evidence database:
- DIE
- YARA
- capa
- Ghidra
- PE / .NET
The agent only ever interprets that sealed evidence afterward. It never receives sample bytes, and it never runs the analyzers. Mechanical work stays in code, deterministic and single-owner. The model's job is constrained synthesis on evidence it can't mutate.
Multiple specialist agents still need to work a case, so we added a blackboard: shared working memory with a single owner. Disposable analysts return typed proposals. An orchestrator alone validates and records them. References have to resolve, duplicates add no weight, and conflicts stay visible instead of being voted away. Known gaps drive the next pass. IOCs are derived from the board. The report and the verdict stay constrained synthesis, not a majority vote.
That's what the extraction collision was missing: shared memory without shared write authority. No analyst owns the whole answer, and no analyst writes the board.

On-disk isn't as-run
Coordination was fixed. The next wall to run through was visibility. Packers, VM protectors, staged loaders, and encrypted configs keep the real payload out of the static image. You detonate, or you never see it.
Detonation doesn't replace static analysis, and it's not a panacea. Static owns structure and on-disk facts. Detonation adds as-run behavior. Together they yield more than either lane alone. So we detonated. A cloud VM became a malware lab.
GCP became the control plane for detonation. A Cloud Run job launches a controller, which spins up a single, disposable Compute Engine VM from a pinned Windows image. Input and output move through an authenticated IAP and WinRM tunnel. The guest VM has no public IP and no general egress. We observe connection attempts. We don't allow completed C2.
Four sensors load at boot: our own kernel drivers.
- Process notify
- Filesystem minifilter
- Registry callback
- Observe-only WFP callout
Each copies events into a bounded kernel queue that a user-mode collector drains. Rows join on a stable process key, not a reused PID. The WFP callout never blocks or injects; it records connect attempts separately from established flows.
The four sensors join into a single ordered timeline instead of four separate logs: a process launches a child, that process attempts an outbound connection, a file gets written to a shared folder, a registry run key gets set for persistence. One run, one ordered story of what the sample actually did, joined back to whatever static analysis already found.
When execution finishes, the guest seals the case, the controller pulls it back through the same tunnel, verifies it outside the VM, and publishes it to Cloud Storage. Only a verified success triggers deletion of the VM and its disk. If the controller itself fails, we keep the machine around for diagnosis instead of tearing it down.

The case only pays off in Mallory
Most of this is only useful if a case can leave the lab.
We ran a sample through Mortex. On the dynamic lane it captured a DNS lookup to fimmora.surf and a TCP attempt to 165.227.123.79:6504. The report calls the sample malicious with medium confidence and stops there: no confirmed protocol, beacon, persistence, or exfil. The actionable indicators are the domain and the egress IP the sample attempted to reach.

That report lands in Mallory as a Mortex-sourced reference on fimmora.surf.
On that indicator, Mortex sits next to Palo Alto Networks Unit 42, already naming it a Remus Info-Stealer C2 on the same IP and port. Open the Unit 42 reference and the campaign is named.


Mortex produced indicators from what it observed. It couldn't attribute a family. Mallory could, by correlating those indicators against thousands of intel sources.
Make every case improve the next
A sealed case is still a single run. The next engineering work is to make every case improve the next: more believable Windows, deterministic Linux evidence, open-weight models evaluated against known cases, asynchronous gap-driven recursion, and a versioned corpus of sealed evidence so variant relationships can be joined exactly.
Historical reports stay immutable. We re-analyze; we don't rewrite the past.

This is the power of the graph. One indicator, and Mallory has the family, the industries they hit, the countries they operate in, and whether you're already in the blast radius.
See what Mallory already knows that's relevant to your environment
Start a 14-day free trial.
Start Free Trial