Raven
An agentic malware-analysis platform where Claude drives sandboxed tools to reverse-engineer a real multi-stage RAT — statically, never executing it.
This is the full engineering dossier behind the project card. Internally the codebase is MalwareScope. It uses the Claude Agent SDK to give a model a set of sandboxed analysis tools, then walks a genuinely hostile sample — an obfuscated .NET infostealer/RAT — through deobfuscation, decryption, and decompilation to recover its complete kill chain. Every claim here is verified against the source, not the docs.
How to read this. The strongest and most honest framing of Raven is precise: it is a static reverse-engineering pipeline, not a dynamic detonation sandbox, and it is driven by a single Claude agent following a scripted plan, not a panel of debating agents. Section 12 is the hardening roadmap — the gap between the impressive demo and a general-purpose tool, tracked as findings.
What Raven is, in one screen
Raven accepts a suspicious file, copies it into an isolated Docker container, and gives Claude a small set of sandboxed tools to investigate it. The agent deobfuscates the sample, recovers encryption keys, decrypts the hidden payload, decompiles it, and extracts indicators of compromise — then a Snowflake-backed RAG chat lets an analyst interrogate the findings in plain language.
The one thing it proves
On its reference sample, the pipeline recovered all four stages of a real threat: an obfuscated 4 MB JScript dropper → hidden PowerShell with an AMSI bypass that disables Defender → an AES-256-CBC-encrypted payload → a reflectively-loaded .NET FTP infostealer/RAT. It pulled the AES key and IV, the C2 host and exfiltration credentials, and the full capability set (keylogging, clipboard capture, credential theft from 20+ applications) — entirely from static analysis, decompiling with ILSpy rather than running the malware.
The stack, precisely labeled
| Layer | Technology | What it does |
|---|---|---|
| Agent | Claude Agent SDK · Sonnet | Drives analysis via custom tools over a scripted 5-step plan. |
| Orchestrator | FastAPI · uvicorn | Upload, job tracking, event streaming, report, RAG chat. |
| Isolation | Docker (malware-sandbox) | Runs analysis commands against the sample away from the host. |
| RE tooling | pefile · ILSpy (ilspycmd) · restringer | PE parsing, .NET decompilation, JS deobfuscation. |
| RAG store | Snowflake Cortex / SQLite | Cortex similarity search when configured; SQLite keyword fallback. |
| Chat | Claude Sonnet (Anthropic SDK) | Answers grounded strictly in retrieved findings. |
| Frontend | Next.js 16 · React 19 | Analysis dashboard + streaming event log + chat panel. |
How the pieces fit together
The FastAPI orchestrator never analyzes anything itself. It copies the sample into the sandbox container, spawns the agent pipeline as a subprocess, and streams the agent's tool calls back to the browser as a live event log. The agent is the analyst; the tools are its hands.
%%{init: {'theme':'base','themeVariables':{'background':'#0c0c0e','primaryColor':'#151517','primaryTextColor':'#e6e6e6','primaryBorderColor':'#00ff41','lineColor':'#555','secondaryColor':'#111','tertiaryColor':'#0a0a0a','clusterBkg':'#0c0c0e','clusterBorder':'#262626','fontFamily':'JetBrains Mono, monospace','fontSize':'13px','textColor':'#c0c0c0'}}}%%
flowchart TB
subgraph CLIENT["Browser · Next.js 16"]
UI["Dashboard · streaming event log"]
CHAT["RAG chat panel"]
end
subgraph API["FastAPI orchestrator"]
UP["/analyze — upload + docker cp"]
ST["/status — stream events"]
RP["/report — structured findings"]
CH["/chat — RAG"]
end
subgraph AGENT["Agent pipeline (subprocess)"]
CL["Claude Sonnet
Claude Agent SDK"]
T1["sandbox
(docker exec)"]
T2["host_analyze
(host bash)"]
T3["extract_file
(docker cp out)"]
end
subgraph ISO["Isolation + tooling"]
BOX["Docker: malware-sandbox"]
HOST["Host: pefile · ILSpy"]
end
subgraph DATA["Findings + RAG"]
WS[("workspace/
findings · events")]
SNOW[("Snowflake Cortex
/ SQLite fallback")]
end
UI --> UP & ST & RP
CHAT --> CH
UP --> CL
CL --> T1 & T2 & T3
T1 --> BOX
T2 --> HOST
T3 --> BOX
CL --> WS
WS -->|"regex IOC parse"| RP
WS -->|"ingest"| SNOW
CH --> SNOW
CH -->|"grounded answer"| CL
ST -.->|"tool-call events"| UI
Fig. 1 — Component architecture. The agent's tools straddle two zones: sandbox and host (see §4).
The analysis run, step by step
The pipeline is a fixed sequence of prompts. Each step asks the agent to perform one concrete action with one tool, so the run is legible and every move shows up in the event stream.
%%{init: {'theme':'base','themeVariables':{'background':'#0c0c0e','primaryColor':'#151517','primaryTextColor':'#e6e6e6','primaryBorderColor':'#00ff41','lineColor':'#555','actorBkg':'#151517','actorBorder':'#00ff41','actorTextColor':'#e6e6e6','signalColor':'#666','signalTextColor':'#c0c0c0','noteBkgColor':'#111','noteTextColor':'#c0c0c0','noteBorderColor':'#333','fontFamily':'JetBrains Mono, monospace','fontSize':'12px'}}}%%
sequenceDiagram
participant U as Analyst
participant A as FastAPI
participant C as Claude (agent)
participant S as Sandbox (Docker)
participant H as Host tools
U->>A: POST /analyze (upload)
A->>S: docker cp sample
A->>C: run pipeline (subprocess)
C->>S: hash + read obfuscated JS
C->>C: strip noise, base64 + UTF-16LE decode → PowerShell
C->>C: recover AES key/IV, AES-256-CBC decrypt
C->>H: extract_file → decrypted .NET binary
C->>H: pefile + ILSpy decompile + grep IOCs
C->>A: write findings report
A->>A: regex-parse IOCs / MITRE / hashes
A-->>U: report + streamed events
U->>A: POST /chat (question)
A-->>U: Cortex/SQLite retrieval → Claude answer
Fig. 2 — The scripted agent run. Deobfuscation and decompilation only — the sample is never executed.
Design decisions & the trade-offs behind them
Agent-with-tools instead of a hardcoded analyzer
The core design bet is to give a capable model a few sharp tools rather than script every analysis branch. Three tools are exposed through an in-process MCP server: sandbox (run bash inside the Docker container), host_analyze (run bash on the host for pefile/ILSpy, which need .NET), and extract_file (copy an artifact out of the container). The agent decides how to use them; the pipeline just sequences the goals.
Why static, not dynamic
Raven never detonates the sample. It defeats obfuscation and decrypts the payload through analysis — stripping the JScript's noise delimiters, base64- and UTF-16LE-decoding the embedded PowerShell, recovering the AES key and IV from the script, decrypting the payload, then decompiling the resulting .NET assembly with ILSpy. Static recovery is slower to build but far safer and more complete here: it reads the malware's real logic instead of hoping it reveals itself at runtime. The reference report is explicit that all findings are static and the malware was never run.
Reporting: legible text, then structured extraction
The agent writes a full free-text findings report. The orchestrator then runs regular expressions over it to pull structured IOCs — IPs, domains, URLs, file paths, SHA-256/MD5 hashes, and MITRE technique IDs — and fills a report object. A few fields are fixed defaults rather than inferred (for example the type defaults to dropper). It is a pragmatic bridge from prose to structure, and §12 notes where it should become a typed schema the agent emits directly.
RAG chat over the findings
Completed findings are chunked and stored. When Snowflake is configured, retrieval uses Cortex similarity search; otherwise it falls back to a local SQLite keyword search, so the chat still works offline. Retrieved chunks become the context for a Claude Sonnet answer that is instructed to use only that context and cite specific IOCs and MITRE IDs.
The input is hostile by definition
Most tools threat-model their users. A malware analyzer must threat-model its input: every sample is actively trying to escape, mislead, or exploit whatever touches it. Two things make Raven's boundaries worth drawing carefully — the agent has host access, and the agent reasons over attacker-controlled content.
%%{init: {'theme':'base','themeVariables':{'background':'#0c0c0e','primaryColor':'#151517','primaryTextColor':'#e6e6e6','primaryBorderColor':'#00ff41','lineColor':'#555','clusterBkg':'#0c0c0e','clusterBorder':'#262626','fontFamily':'JetBrains Mono, monospace','fontSize':'12px','textColor':'#c0c0c0'}}}%%
flowchart LR
subgraph Z1["Zone: Untrusted sample"]
M["Uploaded file
(hostile)"]
end
subgraph Z2["Zone: Sandbox (Docker)"]
BOX["bash / python3
against the sample"]
end
subgraph Z3["Zone: Host"]
AG["Claude agent
bypassPermissions"]
HT["pefile · ILSpy
on decrypted payload"]
WS[("workspace/")]
end
subgraph Z4["Zone: Cloud"]
AN["Claude API"]
SN["Snowflake"]
end
M ==>|"docker cp"| BOX
BOX ==>|"TBâ‘ extract payload"| HT
AG ==>|"TBâ‘¡ host bash, no gate"| HT
BOX -.->|"TBâ‘¢ output steers agent"| AG
HT --> WS
AG --> AN
WS -->|"findings + IOCs"| SN
Fig. 3 — Containment boundaries. TB② and TB③ are the interesting ones for an agentic analyzer.
| Risk | Where it lives in Raven | Mitigation direction |
|---|---|---|
| Containment escape | The sample's execution-style operations run in Docker, but the decrypted .NET payload is extracted to the host and analyzed there (statically). The host tool runs host bash. | Keep all artifact handling in the container; treat the host as never touching the payload. |
| Agent host access | The agent runs with bypassPermissions and a host_analyze tool that executes arbitrary bash on the host — scoped to pefile/ILSpy by prompt, not by policy. | Constrain the host tool to an allowlisted binary set; run it in its own container; drop the bypass. |
| Prompt injection | The agent reasons over attacker-controlled output — deobfuscated strings, decompiled code — then issues tool calls. A crafted sample could try to steer those calls. | Isolate the reasoning from tool authority; require a human gate for host actions; sanitize tool output. |
| Data egress | Findings, IOCs, and hashes flow to Claude and Snowflake — sample intelligence leaves the host. | Acceptable for findings; keep raw sample bytes local and out of any prompt. |
| Distribution | A live malware sample is committed to the repository, which public hosts flag and which redistributes the sample. | Remove the binary; ship a hash and acquisition instructions instead. |
The senior-level question this invites: "Your agent reads attacker-controlled malware output and then runs host commands with permissions bypassed — what stops the sample from prompt-injecting its way into a host action?" The honest answer is right now, prompt scoping, and the real fix is architectural: separate the reasoning context from tool authority and gate anything that touches the host. Have that answer ready.
Running it — and what it assumes
# Backend (port 8001) + frontend (port 3000) pip install -r requirements.txt # fastapi, anthropic, claude-agent-sdk, ... # Set ANTHROPIC_API_KEY (+ optional Snowflake creds) in .env ./start.sh
The reference analysis also assumes external tooling on the machine: Docker with a running container named malware-sandbox, the .NET 8 runtime with ilspycmd for decompilation, and a pre-produced restringer deobfuscation of the sample. The RAG chat needs an Anthropic key; Snowflake is optional and degrades to SQLite.
Setup gap to name up front: the sandbox container is assumed to exist, but the repository ships no Dockerfile to build it. Reproducing a clean run means first defining and starting that container yourself — the first thing §12 fixes.
Where verification stands
Raven was validated the way reverse-engineering usually is: by ground-truth reproduction. Every recovered artifact — the AES key, the C2 credentials, the capability list — was confirmed against the decompiled source, and the report is careful to separate confirmed facts from inference (it flags the malware family as unconfirmed and notes why the .NET imphash is useless for attribution). That analytical discipline is the real test evidence.
The strategy to articulate
What it lacks is an automated harness. The honest plan is a small regression suite that runs the pipeline against a corpus of known samples and asserts on recovered IOCs and hashes; unit tests around the fragile parts (the report's regex extraction, the deobfuscation transforms); and a CI gate. Being able to name that pyramid — and to say the current evidence is manual reproduction, not automation — reads as more senior than claiming coverage that isn't there.
A four-minute live walkthrough
Run against the reference sample so the agent has a known target and the event stream is dense. Drive toward the reveal: a fully-recovered kill chain from a file nobody could read at the start.
- 0:00Show the raw sample: a 4 MB obfuscated JScript — unreadable. "This is what an analyst starts with. Watch the agent take it apart."
- 0:30Hit Analyze. Narrate the streaming event log as tool calls land —
sandbox, decode, decrypt — "every line is the agent's actual tool call, not a progress bar." - 1:30Point out the AES key and IV being recovered and the payload decrypting. "It found the key in the script and decrypted the hidden .NET binary — no execution."
- 2:15Show the ILSpy decompilation step and the grep that surfaces the C2 host, FTP credentials, and capability strings.
- 3:00Open the report: kill chain, both stage hashes, C2 infrastructure, MITRE techniques, capabilities. "All four stages, recovered statically."
- 3:30Chat: ask "what's the C2 and how does it exfiltrate?" Show the grounded answer citing the FTP host and credentials. Close on the honesty note — family unconfirmed, and why.
The line that lands: "It never ran the malware. Everything you just saw is deobfuscation and decompilation — the agent read the code, it didn't trust it to reveal itself." Volunteering that distinction is exactly the instinct a malware-analysis role screens for.
Ninety seconds, no jargon
Figuring out what a piece of malware actually does is slow, expert work — you're peeling back layers of deliberate obfuscation by hand. Raven puts an AI analyst on that job. You hand it a suspicious file, and it takes the thing apart and tells you exactly what it does.
What it does · 35sIt runs the file inside an isolated container and gives an AI model a set of analysis tools. The AI works through the layers — un-scrambling the code, finding the encryption key, unlocking the hidden payload, and reading the decompiled result — until it can report the whole attack: where it phones home, what it steals, how it hides. On the real sample I built it against, it recovered every stage.
Why it's mine to defend · 25sAnd it does all of that without ever running the malware — it reads the code instead of trusting it to behave, which is the safe way to do this. I built the agent tooling, the analysis pipeline, and the dashboard where you can watch it work in real time and then just ask it questions.
The close · 15sThe whole run streams live, so I can walk you from an unreadable file to a full threat report in about four minutes.
The technical explanation
Raven is an agentic malware-analysis pipeline. A FastAPI orchestrator takes an upload, copies it into a Docker container, and spawns a subprocess that runs a Claude agent built on the Claude Agent SDK. I give that agent three tools through an MCP server — run bash in the sandbox, run host tools like pefile and ILSpy, and copy files out of the container — and a fixed sequence of goals to work through.
The analysis · ~90sThe sample is a multi-stage threat: an obfuscated 4-megabyte JScript dropper that hides an AES-encrypted .NET infostealer. The agent strips the script's noise characters, base64- and UTF-16LE-decodes the embedded PowerShell, and recovers the AES key and IV from the script itself. It decrypts the payload, extracts the .NET binary, and decompiles it with ILSpy — and from the decompiled source it pulls the command-and-control host, the FTP exfiltration credentials, and the full capability set: keylogging, clipboard capture, credential theft from twenty-plus applications. The key point is that this is all static — it never executes the malware, it reads it.
Findings & chat · ~60sThe agent writes a findings report, and the orchestrator extracts structured indicators from it with regular expressions — hashes, IPs, domains, MITRE techniques. Those get chunked into a store, and an analyst can ask questions in a RAG chat: retrieval runs on Snowflake Cortex when it's configured and falls back to local keyword search otherwise, and Claude answers grounded only in the retrieved findings.
Honest edges · ~45sTwo things I'd flag myself. It's one agent following a scripted plan, not a panel of debating agents, and that plan is currently tuned to this specific sample — generalizing it is the real work ahead. And the agent runs with permissions bypassed and a host tool, so the trust boundary between the sample's content and the agent's authority is the thing I'd harden first.
The questions this project invites
Grouped by where the pressure comes from. The answers concede the real limitations on purpose — a malware-analysis panel rewards precision far more than a confident overstatement.
On the analysis
QDoes it detonate the sample?
No — and say so first. "It's static analysis. It deobfuscates the JScript, recovers the AES key from the script, decrypts the payload, and decompiles the .NET binary with ILSpy. The malware is never executed. Docker isolates the analysis operations, not a detonation. Static recovery is safer and, for a layered dropper like this, more complete — you read the real logic instead of hoping the runtime reveals it."
QIs it a multi-agent system?
Be precise. "It's a single Claude agent following a scripted five-step plan, using custom sandbox tools. There's no debate-and-consensus panel. I'd frame the roadmap toward specialized agents honestly, but I won't claim it does something it doesn't."
QWould it work on a sample it's never seen?
Concede the limit. "Not yet as a general tool — the current plan encodes assumptions about this sample's structure, down to specific offsets. It's a strong proof that an agent can drive this kind of recovery. Generalizing means replacing the scripted steps with capability-based prompts and a triage stage that detects the obfuscation scheme first."
On safety
QThe agent runs host bash with permissions bypassed. Defend that.
Own it. "That's the sharpest finding. The host tool exists because ILSpy and pefile need the host runtime, and I bypassed the permission gate for an unattended run. The right design separates the agent's reasoning from its tool authority, puts the host tools in their own container, and allowlists the binaries so the agent can't run arbitrary commands even if a sample tries to steer it."
QCould the malware prompt-inject the agent?
This is the real threat. "In principle yes — the agent reasons over attacker-controlled output like decompiled strings, then issues tool calls. Today the only defense is prompt scoping. The architectural fix is to treat all tool output as untrusted, gate host-touching actions behind a human, and never let sample content reach a context that has tool authority."
On the engineering
QHow is the structured report produced?
Don't oversell it. "The agent writes prose; the orchestrator extracts IOCs, hashes, and MITRE IDs from it with regular expressions, and a couple of fields are fixed defaults. It works, but it's brittle. The upgrade is to have the agent emit a typed JSON schema directly and validate it, instead of parsing text after the fact."
QWhat does the RAG chat actually run on?
Know both paths. "Snowflake Cortex similarity search when Snowflake is configured, and a local SQLite keyword search when it isn't — so the chat degrades gracefully offline. Either way Claude answers using only the retrieved findings and is told to cite specific IOCs and techniques."
The honest roadmap
Sample-specific pipeline
Tuned to one dropper's structure. Next: a triage stage that fingerprints obfuscation, then capability-based prompts instead of fixed steps.
Single scripted agent
Not a debating panel. Next: specialized roles (static, behavioral, critic) with a real adjudication step.
Agent host authority
Bypassed permissions + host bash. Next: containerize host tools, allowlist binaries, gate host actions.
Text-parsed reports
Regex over prose + fixed defaults. Next: a typed schema the agent emits and the orchestrator validates.
Undocumented sandbox
Container assumed, not shipped. Next: a Dockerfile and compose file for a reproducible sandbox.
No automated tests
Manual reproduction only. Next: a known-sample regression suite and CI.
Genuine strengths to lead with: a real, non-trivial reverse-engineering result — all four stages of a live .NET RAT recovered statically, including AES key recovery and full C2/credential extraction; a genuine use of the Claude Agent SDK with custom sandboxed tools and a live event stream; graceful RAG degradation from Snowflake Cortex to local search; and analytical honesty in the output itself, separating confirmed facts from inference.
Known limitations, tracked as findings
Documented like any other assessment — each limitation logged as a severity-tagged finding with a fix. This is the path from an award-winning demo toward a general, hardened analyzer.
- Detail
- The pipeline never executes the sample (deobfuscation + ILSpy decompilation), and it is a single Claude agent following a scripted plan, not multiple agents reaching consensus.
- Fix
- Describe it precisely: an agentic static reverse-engineering pipeline. Both properties are strengths when stated honestly.
- Detail
- Steps encode assumptions about the reference dropper (obfuscation scheme, offsets). An arbitrary upload would not follow the same path.
- Fix
- Add an obfuscation-fingerprinting triage stage; replace fixed steps with capability-based prompts.
- Detail
- The agent runs with
bypassPermissionsand ahost_analyzetool that executes arbitrary host bash; the decrypted payload is handled on the host. The agent also reasons over attacker-controlled output — a prompt-injection surface. - Fix
- Containerize host tooling, allowlist binaries, separate reasoning context from tool authority, and gate host actions.
- Detail
- The code assumes a running
malware-sandboxcontainer, but the repo ships nothing to build it. - Fix
- Add a Dockerfile + compose so a clean run is one command.
- Detail
- IOCs come from regex over the agent's text; some fields are fixed defaults. A separate rich chunker expects a schema the pipeline never emits.
- Fix
- Have the agent emit a typed JSON report and validate it; retire the unused schema path.
- Detail
- Analysis uses pefile, ILSpy, and grep; there is no YARA in the pipeline, and the report's YARA/Sigma fields are never populated.
- Fix
- Either add real YARA rule generation, or drop it from the described stack.
- Detail
- A live malware sample is committed to the public repo, and the API allows all origins.
- Fix
- Replace the binary with a hash + fetch instructions; restrict CORS to the frontend origin.
Sequenced: F1 is a framing fix worth one honest sentence. F2 and F3 are the substantive engineering — generalize the pipeline and re-architect the agent's trust boundary. F4–F7 are the reproducibility and hygiene work that take a hackathon result toward a tool other analysts could safely run.