RMAgent Red-Team (drill)
A purple-team drill that stages living-off-the-land artifacts on your Windows estate (WS1/WS2), then runs the rmagent-windows skill to score what it detects — and Telegrams you the report. This is how you answer "does rmagent actually work?"
It is a DRILL, not a real attack. Every artifact is prefixed RMAgentDrill_, uses benign payloads (a network test to 1.1.1.1, an echo to a temp file), is non-persistent, and is fully reversible with clean. It requires --confirm and never runs against a box you do not administer. Misses that are witness_blind are holes, not so bugs. Drill cases live in ~/.rmagent/drill/. Payloads stay under the WinRM ~8191-char budget.
The attack this simulates (the Ada story, class 03 "Walk")
The drill stages the exact kind of movement rmagent is built to catch — identity-led, living-off-the-land, no new malware. Each artifact maps to a specific rmagent signal:
| Staged artifact |
Windows event |
rmagent signal it should fire |
| 2 failed Administrator logons |
4625 |
attest.admin_failed_60s, sketch.admin_failed |
New local admin RMAgentDrill_Test |
4720 + 4732 |
explain.identity_changes, sketch.new_local_admins |
New SYSTEM scheduled task RMAgentDrill_Task |
4698 |
explain.task_events, sketch.new_tasks |
New LocalSystem service RMAgentDrillSvc |
7045 |
explain.service_events, sketch.new_services |
| PowerShell spawns |
4688 (if Process Creation audited) |
explain.proc_spawns |
| SYSTEM outbound connection to 1.1.1.1:80 |
Sysmon EID3 |
|
| Run key RMAgentDrill_RunKey |
Registry state |
attackmap (T1547.001) |
| IFEO debugger RMAgentDrill.exe |
Registry state |
attackmap (T1546.010) |
Prerequisites
Jump host: macOS, Linux, or Windows. pywinrm connects to the Windows targets from any. On a non-macOS jump host, the secrets scrt master password is provided via SCRT_PASS env var or a ~/.scrt_pass file (macOS uses Keychain automatically). The winrm_pool.ps1 RunspacePool path needs PowerShell 7.
- The
rmagent-windows skill works (census passes on WS1/WS2). See its README.
- Telegram alerting configured — token
telegram-bot-token and chat telegram-chat-id in the secrets scrt store (already present), OR env RMAgent_TELEGRAM_TOKEN / RMAgent_TELEGRAM_CHAT.
- Windows credentials — env
RMAgent_<ID>_PASS, OR the scrt keys windows-server1-password / windows-server2-password (auto-loaded if env is missing).
- Audit subcategories on (so Windows writes the events to its diary). On each box, run:
auditpol /set /subcategory:"Process Creation" /success:enable # 4688 process spawns
auditpol /set /subcategory:"Other Object Access Events" /success:enable # 4698 scheduled tasks
auditpol /set /subcategory:"Security Group Management" /success:enable # 4732 group-add (new local admin) — NOT "Account Management" (that's 4720)
Without these, three of the six drill signals cannot be detected by any pull-based tool — Windows writes no event. On this estate they are already enabled.
- Sysmon NetworkConnect on (for the transient outbound-connection signal): Sysmon is already installed on WS1/WS2; enable its network-connection ring with a minimal config (
<NetworkConnect> to log all), applied via Sysmon64.exe -c <config>. Then the netedges question reads the Sysmon EID3 ring. Without it, system_outbound_conn shows 0 — a point-in-time edges snapshot misses sub-second connections. On this estate it is already enabled.
Run
export SKILL_DIR=~/.agents/skills/rmagent-redteam
cp ~/.agents/skills/rmagent-windows/assets/inventory.example.yaml ./estate.yaml
# Full loop: stage -> rmagent census+hunt -> score -> telegram -> clean
python3 "$SKILL_DIR/scripts/redteam.py" run --inventory ./estate.yaml --confirm
# Or step by step:
python3 "$SKILL_DIR/scripts/redteam.py" stage --inventory ./estate.yaml --confirm # stage artifacts
python3 "$SKILL_DIR/scripts/redteam.py" clean --inventory ./estate.yaml # remove them
--keep leaves artifacts staged after a run (clean later with clean).
What happens during a run
- Telegram: "drill started" message listing the artifacts it will stage.
- Stage
drill.ps1 on each box.
- Wait 8s for events to land in the logs.
- Run
rmagent-windows census + hunt (1h window) into a case folder.
- Score detected vs staged — compares what rmagent recorded to the 8 expected signals.
- Telegram: a detection report —
Detected (N/8) with each signal, plus any missed, plus the case name.
- Clean
clean.ps1 on each box (unless --keep).
- Telegram: "artifacts cleaned."
Output you owe the user
After a run, state plainly:
- What was staged (the 6 artifacts).
- What rmagent detected (N/6, with each signal and which rmagent field fired).
- What was missed and why (e.g., Process Auditing off → no 4688).
- The case path so the walk can be re-read.
- That artifacts were cleaned (or kept).
Non-negotiables
- Authorised estate only. WS1/WS2, or boxes the operator administers. Never a partner/NIBSS/production-critical box without explicit written consent.
--confirm required for stage and run. No silent staging.
- Reversible.
clean.ps1 removes every RMAgentDrill_* artifact. Idempotent. Run it after every drill unless you used --keep.
- Benign payloads only. A network test to
1.1.1.1:80 and an echo to a temp file. No exfiltration, no persistence, no destructive action.
- Telegram is the alert channel, not a data channel. Send detection summaries, never credentials, Event Logs, or case contents.
- Don't compete with EDR. Defender/CrowdStrike may alert on the drill too — that's good. Coordinate timing if your SOC is staffed.
Limits
proc_spawns (4688) needs Process Creation auditing on the target. If it shows 0, check auditpol /get /subcategory:"Process Creation".
system_outbound_conn needs the Sysmon NetworkConnect ring enabled (<NetworkConnect>). The point-in-time edges snapshot misses a sub-second connection that already closed; the Sysmon ring persists it. If it shows 0, confirm Sysmon's NetworkConnect config is on.
- The drill runs as Administrator over WinRM, so the staged "failed Administrator logon" events are real 4625s for the local Administrator account.
1---2name: rmagent-redteam3description: Purple-team DRILL for the rmagent-windows skill. Stages 8 reversible living-off-the-land (LOTL) artifacts on WS1/WS2 — failed Administrator logons, a new local admin, a SYSTEM scheduled task, a new LocalSystem service, PowerShell spawns, a SYSTEM outbound connection, a registry Run key (T1547.001), and an IFEO debugger hijack (T1546.010) — then runs rmagent census+hunt to score what it detects, and sends a Telegram alert with the detection report. Use to TEST rmagent effectiveness. This is a benign drill, not a real attack: every artifact is prefixed RMAgentDrill_ and is reversible with clean. Requires --confirm. Do NOT use against boxes you do not administer.4---56# RMAgent Red-Team (drill)78A **purple-team drill** that stages living-off-the-land artifacts on your Windows estate (WS1/WS2), then runs the `rmagent-windows` skill to score what it detects — and Telegrams you the report. This is how you answer "does rmagent actually work?"910It is a **DRILL, not a real attack.** Every artifact is prefixed `RMAgentDrill_`, uses benign payloads (a network test to `1.1.1.1`, an echo to a temp file), is non-persistent, and is fully reversible with `clean`. It requires `--confirm` and never runs against a box you do not administer. Misses that are `witness_blind` are **holes**, not so bugs. Drill cases live in `~/.rmagent/drill/`. Payloads stay under the WinRM ~8191-char budget.1112## The attack this simulates (the Ada story, class 03 "Walk")1314The drill stages the exact kind of movement rmagent is built to catch — **identity-led, living-off-the-land, no new malware.** Each artifact maps to a specific rmagent signal:1516| Staged artifact | Windows event | rmagent signal it should fire |17|---|---|---|18| 2 failed Administrator logons | 4625 | `attest.admin_failed_60s`, `sketch.admin_failed` |19| New local admin `RMAgentDrill_Test` | 4720 + 4732 | `explain.identity_changes`, `sketch.new_local_admins` |20| New SYSTEM scheduled task `RMAgentDrill_Task` | 4698 | `explain.task_events`, `sketch.new_tasks` |21| New LocalSystem service `RMAgentDrillSvc` | 7045 | `explain.service_events`, `sketch.new_services` |22| PowerShell spawns | 4688 (if Process Creation audited) | `explain.proc_spawns` |23| SYSTEM outbound connection to 1.1.1.1:80 | Sysmon EID3 |24| Run key RMAgentDrill_RunKey | Registry state | attackmap (T1547.001) |25| IFEO debugger RMAgentDrill.exe | Registry state | attackmap (T1546.010) | `netedges` (reads the Sysmon `Microsoft-Windows-Sysmon/Operational` ring — catches transient conns `edges` misses). Requires `<NetworkConnect onmatch="exclude">` |2627## Prerequisites2829> **Jump host: macOS, Linux, or Windows.** pywinrm connects to the Windows targets from any. On a non-macOS jump host, the `secrets` scrt master password is provided via `SCRT_PASS` env var or a `~/.scrt_pass` file (macOS uses Keychain automatically). The `winrm_pool.ps1` RunspacePool path needs PowerShell 7.30311. The `rmagent-windows` skill works (census passes on WS1/WS2). See its README.322. Telegram alerting configured — token `telegram-bot-token` and chat `telegram-chat-id` in the `secrets` scrt store (already present), OR env `RMAgent_TELEGRAM_TOKEN` / `RMAgent_TELEGRAM_CHAT`.333. Windows credentials — env `RMAgent_<ID>_PASS`, OR the scrt keys `windows-server1-password` / `windows-server2-password` (auto-loaded if env is missing).344. **Audit subcategories on** (so Windows writes the events to its diary). On each box, run:35 ```powershell36 auditpol /set /subcategory:"Process Creation" /success:enable # 4688 process spawns37 auditpol /set /subcategory:"Other Object Access Events" /success:enable # 4698 scheduled tasks38 auditpol /set /subcategory:"Security Group Management" /success:enable # 4732 group-add (new local admin) — NOT "Account Management" (that's 4720)39 ```40 Without these, three of the six drill signals cannot be detected by any pull-based tool — Windows writes no event. On this estate they are already enabled.415. **Sysmon NetworkConnect on** (for the transient outbound-connection signal): Sysmon is already installed on WS1/WS2; enable its network-connection ring with a minimal config (`<NetworkConnect onmatch="exclude">` to log all), applied via `Sysmon64.exe -c <config>`. Then the `netedges` question reads the Sysmon EID3 ring. Without it, `system_outbound_conn` shows 0 — a point-in-time `edges` snapshot misses sub-second connections. On this estate it is already enabled.4243## Run4445```bash46export SKILL_DIR=~/.agents/skills/rmagent-redteam47cp ~/.agents/skills/rmagent-windows/assets/inventory.example.yaml ./estate.yaml4849# Full loop: stage -> rmagent census+hunt -> score -> telegram -> clean50python3 "$SKILL_DIR/scripts/redteam.py" run --inventory ./estate.yaml --confirm5152# Or step by step:53python3 "$SKILL_DIR/scripts/redteam.py" stage --inventory ./estate.yaml --confirm # stage artifacts54python3 "$SKILL_DIR/scripts/redteam.py" clean --inventory ./estate.yaml # remove them55```5657`--keep` leaves artifacts staged after a `run` (clean later with `clean`).5859## What happens during a `run`60611. **Telegram**: "drill started" message listing the artifacts it will stage.622. **Stage** `drill.ps1` on each box.633. **Wait 8s** for events to land in the logs.644. **Run `rmagent-windows` census + hunt** (1h window) into a case folder.655. **Score** detected vs staged — compares what rmagent recorded to the 8 expected signals.666. **Telegram**: a detection report — `Detected (N/8)` with each signal, plus any missed, plus the case name.677. **Clean** `clean.ps1` on each box (unless `--keep`).688. **Telegram**: "artifacts cleaned."6970## Output you owe the user7172After a run, state plainly:731. **What was staged** (the 6 artifacts).742. **What rmagent detected** (N/6, with each signal and which rmagent field fired).753. **What was missed** and *why* (e.g., Process Auditing off → no 4688).764. **The case path** so the walk can be re-read.775. **That artifacts were cleaned** (or kept).7879## Non-negotiables8081- **Authorised estate only.** WS1/WS2, or boxes the operator administers. Never a partner/NIBSS/production-critical box without explicit written consent.82- **`--confirm` required** for `stage` and `run`. No silent staging.83- **Reversible.** `clean.ps1` removes every `RMAgentDrill_*` artifact. Idempotent. Run it after every drill unless you used `--keep`.84- **Benign payloads only.** A network test to `1.1.1.1:80` and an echo to a temp file. No exfiltration, no persistence, no destructive action.85- **Telegram is the alert channel, not a data channel.** Send detection summaries, never credentials, Event Logs, or case contents.86- **Don't compete with EDR.** Defender/CrowdStrike may alert on the drill too — that's good. Coordinate timing if your SOC is staffed.8788## Limits8990- `proc_spawns` (4688) needs Process Creation auditing on the target. If it shows 0, check `auditpol /get /subcategory:"Process Creation"`.91- `system_outbound_conn` needs the Sysmon NetworkConnect ring enabled (`<NetworkConnect onmatch="exclude">`). The point-in-time `edges` snapshot misses a sub-second connection that already closed; the Sysmon ring persists it. If it shows 0, confirm Sysmon's NetworkConnect config is on.92- The drill runs as Administrator over WinRM, so the staged "failed Administrator logon" events are real 4625s for the local Administrator account.