# exploits/

The Tier-3 exploit driver — fires a Metasploit module against a
vulnerable target VM, watches for the resulting session, and stamps the
session-open transition into the episode's `events.jsonl` so the
labeler can mark `armed → infecting` honestly.

## Layout

```
exploits/
  msfrpc.py           tiny msgpack-over-HTTPS client for msfrpcd
  driver.py           MSFExploitDriver — plugged in as EpisodeRunner.on_phase
  modules.py          ModuleConfig + TOML loader
  modules/
    vsftpd_234_backdoor.toml   first canned module (Metasploitable2)
    ...
```

## Module configs

Each `modules/*.toml` describes one Metasploit module — its path, the
options to set, and the payload to use. The driver reads these files
to drive `module.execute` over msfrpc.

```toml
description = "..."
[module]
type = "exploit"                      # exploit | auxiliary | post
path = "unix/ftp/vsftpd_234_backdoor"

[module.options]
RHOSTS = "{{ target_ip }}"            # placeholder substituted at runtime
RPORT = 21

[payload]
path = "cmd/unix/interact"
[payload.options]                     # optional
# LHOST = "{{ target_ip }}"

[session]
type = "shell"
```

The only placeholder supported today is `{{ target_ip }}`. Add more in
`exploits/modules.py::ModuleConfig.render_options` when needed.

## Running

```sh
# 1. Start msfrpcd locally:
msfrpcd -P <password> -U msf -a 127.0.0.1 -p 55553

# 2. Drop a vulnerable target image at vm/images/<name>.qcow2 (e.g.
#    Metasploitable2 — see docs/sources.md for sha256).

# 3. Drive an episode:
MSFRPC_PASSWORD=<password> uv run python tools/run_tier3_demo.py \
    --module vsftpd_234_backdoor \
    --target-port 21 \
    --data-root data
```

The episode's `events.jsonl` will contain:

```
driver_setup        — module + target snapshotted before fire
exploit_fire        — module.execute issued
session_open        — new session id observed in session.list
session_landing_probe — first command response (id) recorded
sample_executed     — workload kicked off inside the session
session_dormant     — workload killed
session_killed      — session.stop at episode end
```

These pair with the standard phase labels in `labels.jsonl` so a
downstream loader can reconcile "what the orchestrator scheduled"
against "what actually happened on the wire".

## Adding a module

1. Drop a TOML at `exploits/modules/<name>.toml` per the schema above.
2. Pick a payload that works without a callback channel until the
   `br-malware` bridge is in (see `vm/launch_target.sh` — SLIRP +
   `restrict=on` blocks reverse-tcp by design). `cmd/unix/interact`
   and other "session on the same socket" payloads are safe.
3. Drive a quick check: `uv run python tools/run_tier3_demo.py --module <name>`.
4. The new module is automatically picked up by `tools/run_tier3_demo.py`
   via `--module <name>`; no driver code changes needed.

We do **not** author exploits or modify upstream Metasploit code. The
driver is a pure adapter from the project's phase machine to msfrpc.
