diff --git a/.cursor/skills/reaper-red-team-operator/SKILL.md b/.cursor/skills/reaper-red-team-operator/SKILL.md index f6a4856..117b83a 100644 --- a/.cursor/skills/reaper-red-team-operator/SKILL.md +++ b/.cursor/skills/reaper-red-team-operator/SKILL.md @@ -2,9 +2,9 @@ name: reaper-red-team-operator description: >- Red team operator workflows for ReaperC2: reconnaissance, enumeration, - exploitation planning, beacon commands, MITRE ATT&CK mapping, and engagement - scoping. Use when working in the ReaperC2 repo, admin panel, Scythe beacons, - or when the user asks for operator tradecraft tied to this C2. + exploitation planning, beacon commands, Scythe SOCKS pivots, MITRE ATT&CK + mapping, and engagement scoping. Use when working in the ReaperC2 repo, admin + panel, Scythe beacons, or when the user asks for operator tradecraft tied to this C2. --- # ReaperC2 red team operator @@ -13,14 +13,16 @@ Read and follow: 1. **[SKILLS.md](../../../SKILLS.md)** — ReaperC2 platform map, beacon workflow, authorization. 2. **[red_team_operator_skills.md](red_team_operator_skills.md)** — tradecraft reference (recon, enumeration, cloud, reporting). -3. **[mitre_attck_skills.md](mitre_attck_skills.md)** — MITRE ATT&CK Enterprise matrix reference (tactics, techniques, sub-techniques). -4. **[purple-team-operator.md](purple-team-operator.md)** — optional: translate red-team findings into detection rules, hardening, and coverage analysis (purple-team handoff). +3. **[scythe_proxy_skills.md](scythe_proxy_skills.md)** — exact Generate beacon fields for a Scythe SOCKS pivot (upstream listener, child `-proxy`). +4. **[mitre_attck_skills.md](mitre_attck_skills.md)** — MITRE ATT&CK Enterprise matrix reference (tactics, techniques, sub-techniques). +5. **[purple-team-operator.md](purple-team-operator.md)** — optional: translate red-team findings into detection rules, hardening, and coverage analysis (purple-team handoff). **Operator AI** (`/ai`) merges these from disk when present (`REAPERC2_ROOT`, usually `/root` in Docker). Any other `*_skills.md` in this folder is picked up automatically. Override everything with `REAPER_AI_SKILLS_FILE` for a single custom file. ## Quick triggers - **Beacons / Scythe / embedded** → see SKILLS.md “Beacon and command workflow” and `docs/operator-guide-beacons.md` +- **Proxy / pivot / SOCKS** → `scythe_proxy_skills.md` (Operator AI loads this file automatically) - **Queue commands** → `docs/operator-guide-commands.md`; suggest exact strings for `whoami`, `download`, uploads - **MITRE / Navigator** → `docs/operator-guide-notes.md` - **Engagement scope** → `docs/operator-guide-engagements.md` diff --git a/.cursor/skills/reaper-red-team-operator/scythe_proxy_skills.md b/.cursor/skills/reaper-red-team-operator/scythe_proxy_skills.md new file mode 100644 index 0000000..5405198 --- /dev/null +++ b/.cursor/skills/reaper-red-team-operator/scythe_proxy_skills.md @@ -0,0 +1,95 @@ +# Scythe proxy (SOCKS pivot) + +Use this whenever the operator asks how to pivot, set a proxy, chain beacons, or phone home through an already-landed host. Give the exact **Generate beacon** field values. Do not tell them to edit a running binary or to rebuild a saved profile to change these flags. + +A pivot is two beacons. The upstream beacon phones home directly and listens as a SOCKS5 proxy. Each downstream beacon still targets the public C2 URL; `-proxy` only changes the TCP dial. + +`-socks5-listen`, `-socks5-port`, and `-proxy` are compiled into **Scythe.embedded**. **Saved profiles → Scythe.embedded** rebuilds the options already stored on that profile. To turn a listener on, or to point a child at a different address, generate a new beacon and download again. + +## What the server actually does + +- **Parent beacon ClientId** draws the Topology edge. It does not add `-proxy`. +- **Pivot proxy** (`host:port`) is copied into Scythe `-proxy` only when a parent is set and Scythe Http **Proxy** is empty. After save, both **Pivot proxy** and **Scythe HTTP proxy** show that same `host:port`. +- If Scythe Http **Proxy** is filled in, that value wins and **Pivot proxy** is ignored for the dial. +- `BEACON_PIVOT_PROXY` on the server is a fallback only when a new beacon has a parent and both proxy fields are empty. The k3s deployment does not set it. Put the address on the form. +- **SOCKS5 listener** must be checked. The port box alone does nothing. The form still stores port **9050** when the box is unchecked; the binary omits `-socks5-listen` unless the box was checked. +- The listener binds all interfaces (`:9050`) and accepts SOCKS5 with no username or password. +- **Beacon C2 base URL** stays the public beacon origin on every hop (ingress or port 8080). It is not the admin UI on 8443, and it is not the pivot address. +- HTTP client timeout (`-timeout`, these profiles use `15s`) is not the phone-home interval (these profiles use 120 seconds). + +## 1. Upstream beacon (the proxy) + +Generate this first. It must check in before any child is built. Match this shape (the engagement profile **Initial Access - pivot**): + +| Field | Value | +|-------|--------| +| Display label | Name the landing host, for example `Initial Access - pivot` | +| Parent beacon ClientId | Empty | +| Pivot proxy | Empty | +| Beacon C2 base URL | Public beacon origin, for example `https://metrics.harvestrangelabs.com` | +| Expected phone-home interval | Operator cadence (120 on the saved profile) | +| HTTP method | `GET` | +| HTTP client timeout | `15s` unless the operator needs a different client timeout | +| Extra headers | Optional. A browser User-Agent is fine and does not affect the proxy | +| Extra directories | Empty (the server always adds `/heartbeat/,/heartbeat`) | +| Proxy | Empty | +| SOCKS5 listener | **Checked** | +| SOCKS5 listen port | **9050** unless this host already uses that port | +| Skip TLS verify | Off | +| GOOS / GOARCH | The landing host (`linux` / `amd64` on the saved profile) | + +Download **Scythe.embedded**. The example line ends with `-socks5-listen -socks5-port 9050` and has no `-proxy`. + +Start it with `TERM_HARVEST=9` in the same shell. Without that variable the process prints random hex and exits, and it never listens. + +Confirm it is green on **Topology**. The address children will use is the upstream host’s IP **as the child can route to it**, plus `9050`. That is not the public C2 hostname. Use `127.0.0.1` only when the child runs on the same machine. + +## 2. Downstream beacon (through the proxy) + +The upstream client must already exist in this engagement. Match this shape (the engagement profile **pivot-through-proxy**): + +| Field | Value | +|-------|--------| +| Display label | Name the hop, for example `pivot-through-proxy` | +| Parent beacon ClientId | Upstream beacon’s ClientId | +| Pivot proxy | `:9050` reachable from the child. The saved child uses the upstream host on the child’s network, port **9050** | +| Beacon C2 base URL | Same public origin as the upstream beacon | +| HTTP method | `GET` | +| HTTP client timeout | `15s` | +| Extra headers | Empty unless the operator wants them | +| Proxy | **Empty.** Do not type the address here; **Pivot proxy** is what the server copies into `-proxy` | +| SOCKS5 listener | **Unchecked**, unless this host should accept a further hop | +| SOCKS5 listen port | Leave the default. It is not compiled in while the box is unchecked | +| Skip TLS verify | Off | +| GOOS / GOARCH | The child host | + +Download a new embedded binary. The example line includes `-proxy :9050` and does not include `-socks5-listen`. + +The child still requests `https:///heartbeat/`. Scythe opens SOCKS5 to the pivot address, then asks that proxy to connect to the C2 host. + +Start it with `TERM_HARVEST=9`. + +## 3. Further hops + +Repeat step 2. Each new beacon’s parent is the beacon one hop closer to C2. Its **Pivot proxy** is that parent’s SOCKS address (`:9050`). Check **SOCKS5 listener** only on a beacon that should accept the next hop. + +## How to tell a profile is wrong + +Read **Saved profiles → View credentials** before telling the operator to run a binary. + +| Saved state | What to say | +|-------------|-------------| +| Label looks like an initial beacon, **SOCKS5 listener** is false | It is not a proxy. The earlier pattern **Initial Access no pivot** was built this way. Generate a new upstream with the box checked. | +| Child has a parent but **Pivot proxy** is empty and the example has no `-proxy` | It dials C2 directly. Generate again with **Pivot proxy** set. Topology can still draw the edge. | +| Child **Proxy** was typed and does not match the upstream listen port | That typed value is what got compiled. Generate again; leave **Proxy** empty and set **Pivot proxy** to `:9050`. | +| Operator wants to “just rebuild” Scythe.embedded on an old profile | Rebuild keeps the saved flags. Generate a new beacon. | + +## Launch + +```bash +export TERM_HARVEST=9 && ./Scythe-embedded--linux-amd64.bin +``` + +```powershell +$env:TERM_HARVEST='9'; .\Scythe-embedded--windows-amd64.exe +``` diff --git a/SKILLS.md b/SKILLS.md index 1fa5162..d3bbf97 100644 --- a/SKILLS.md +++ b/SKILLS.md @@ -64,7 +64,7 @@ Embedded Scythe requires **`TERM_HARVEST=9`** in the environment before launch. - Tie recommendations to observed facts (e.g. domain user → credential access techniques, local admin → privilege escalation). - For lateral movement, check **Topology** for existing beacons and pivot (`ParentClientId`, pivot proxy). -- Initial proxy: upstream beacon has **SOCKS5 listener** checked (UI default port 9050), no parent, and empty Proxy. It listens on all interfaces with no SOCKS auth. Each child sets **Parent beacon ClientId** to that UUID and **Pivot proxy** to `:` reachable from the child. The child’s C2 base URL stays the public listener; `-proxy` only changes the dial. Parent alone does not add `-proxy`. These flags are compiled into Scythe.embedded, so a profile rebuild does not turn a listener on after the fact. +- For a Scythe SOCKS pivot, follow **scythe_proxy_skills.md** field for field. Upstream: no parent, **SOCKS5 listener** checked, port 9050, empty Proxy. Child: parent ClientId of that beacon, **Pivot proxy** `:9050`, Scythe Http **Proxy** left empty, listener unchecked. Parent alone does not add `-proxy`. Flags are compiled into Scythe.embedded. - Prefer living-off-the-land and engagement-appropriate tooling; note OPSEC (logging, EDR, DLP). ### Reporting diff --git a/pkg/ai/SKILLS.md b/pkg/ai/SKILLS.md index 330ac18..6956766 100644 --- a/pkg/ai/SKILLS.md +++ b/pkg/ai/SKILLS.md @@ -64,7 +64,7 @@ Embedded Scythe requires **`TERM_HARVEST=9`** in the environment before launch. - Tie recommendations to observed facts (e.g. domain user → credential access techniques, local admin → privilege escalation). - For lateral movement, check **Topology** for existing beacons and pivot (`ParentClientId`, pivot proxy). -- Initial proxy: upstream beacon has **SOCKS5 listener** checked (UI default port 9050), no parent, and empty Proxy. It listens on all interfaces with no SOCKS auth. Each child sets **Parent beacon ClientId** to that UUID and **Pivot proxy** to `:` reachable from the child. The child’s C2 base URL stays the public listener; `-proxy` only changes the dial. Parent alone does not add `-proxy`. These flags are compiled into Scythe.embedded, so a profile rebuild does not turn a listener on after the fact. +- For a Scythe SOCKS pivot, follow **scythe_proxy_skills.md** field for field. Upstream: no parent, **SOCKS5 listener** checked, port 9050, empty Proxy. Child: parent ClientId of that beacon, **Pivot proxy** `:9050`, Scythe Http **Proxy** left empty, listener unchecked. Parent alone does not add `-proxy`. Flags are compiled into Scythe.embedded. - Prefer living-off-the-land and engagement-appropriate tooling; note OPSEC (logging, EDR, DLP). ### Reporting