Skip to content
BlackSnufkin edited this page May 3, 2026 · 1 revision

Whiskers Agent

LitterBox's sensor agent β€” a single-binary HTTP execution runner. Runs on the Windows VM where you've installed an EDR (Elastic Defend, Defender, Fibratus, etc.) and accepts payloads from LitterBox over HTTP. Executes them, reports stdout/stderr/PID/exit code back.

LitterBox  ── HTTP ──►  Whiskers.exe  ── Process.Spawn ──►  payload
                              β”‚
                              └─ same VM has your EDR/detection engine watching everything
                                 (Elastic Defend / Fibratus / Defender / etc.)

What it does:

  • Single-occupancy gate (lock acquire/release) so two operators don't double-fire
  • Multipart payload upload with optional XOR-on-the-wire (anti-AV-in-transit)
  • Process spawn + kill + stdout/stderr capture
  • Self-reports hostname / OS version / agent version via /api/info
  • For Fibratus integrations: queries the Application event log on demand

What it does NOT do:

  • It does not author or interpret alerts. Alert sourcing is done by:
    • For kind: elastic profiles β€” LitterBox queries your Elastic stack directly. Whiskers stays a pure exec runner.
    • For kind: fibratus profiles β€” LitterBox calls Whiskers's /api/alerts/fibratus/since which wevtutil-queries the local Application event log for Provider=Fibratus records. Whiskers ships the raw <Data> JSON strings; LitterBox does the parsing.

Install

  1. Get the binary:

  2. Drop it anywhere on the VM (e.g. C:\Tools\Whiskers.exe). The folder you put it in becomes the agent home β€” payloads land in <that folder>\samples\ by default and the directory is created on first write.

  3. Allow inbound TCP 8080 in Windows Firewall:

    New-NetFirewallRule -DisplayName "Whiskers" `
                        -Direction Inbound -Protocol TCP -LocalPort 8080 `
                        -Action Allow
  4. Run it once to verify:

    .\Whiskers.exe --port 8080
    # 2026-04-29T13:30:12Z  INFO  whiskers ready version=0.1.0 listen=0.0.0.0:8080
  5. Optional: register an at-logon scheduled task so you don't relaunch every session:

    .\Whiskers.exe --install
    # creates an ONLOGON Windows scheduled task running as the invoking user (no UAC)

    Log out / back in to confirm. To remove: .\Whiskers.exe --uninstall.


CLI flags

Flag Default Notes
--port <PORT> 8080 TCP port to listen on
--bind <ADDR> 0.0.0.0 Bind address. 127.0.0.1 for loopback-only testing
--max-payload-mb <MB> 200 Multipart upload cap on /api/execute/exec. Mirrors LitterBox's 100 MB upload cap with envelope headroom
--samples-dir <PATH> <exe-dir>\samples Where payloads land when no per-request drop_path is sent. Auto-created on first write
--install β€” Register Whiskers as an ONLOGON Windows scheduled task (no UAC). Forwards non-default flags into the task command line. Exits without starting the server
--uninstall β€” Remove the previously installed scheduled task. Exits

Also accepts -h / --help and -V / --version.


Verify

From any machine that can reach the VM:

curl http://<edr-vm-ip>:8080/api/info
# {
#   "hostname": "DESKTOP-...",
#   "os_version": "Windows ...",
#   "agent_version": "0.1.0",
#   "telemetry_sources": ["fibratus"]    ← only when Fibratus is installed at the default path
# }

telemetry_sources is auto-populated based on what's present on the VM (currently just Fibratus presence at C:\Program Files\Fibratus\Bin\fibratus.exe). The orchestrator uses this to preflight before dispatching to a kind: fibratus profile.


Endpoints

Method Path Purpose
GET /api/info {hostname, os_version, agent_version, telemetry_sources}
POST /api/lock/acquire Single-occupancy gate. 200 if free, 409 if held
POST /api/lock/release 200, idempotent
GET /api/lock/status {in_use: bool}
POST /api/execute/exec Multipart: file + drop_path + executable_args + xor_key. Returns {status, pid} immediately; the spawn runs detached. .dll payloads spawn via rundll32.exe <path>,<entry> [args...] β€” entry is the first token of executable_args
POST /api/execute/kill Terminate the most recent run if alive
GET /api/logs/execution {pid, status, stdout, stderr, exit_code, started_at, finished_at, is_running}. Stdout/stderr capped at 256 KB by the LitterBox-side AgentClient
GET /api/logs/agent Plain-text agent-debug log (last 1000 lines)
DELETE /api/logs/agent Clear the agent log buffer
GET /api/alerts/fibratus/since Query params from=<ISO8601>&until=<ISO8601>. Returns {supported: bool, events: [{time_created, event_id, data}]} β€” data is the raw JSON <Data> from each Provider=Fibratus event-log record. supported: false when Fibratus isn't installed

Single-occupancy by design β€” a new /api/execute/exec while a previous run is still live will kill the previous one before starting the new one. The lock is what the orchestrator (LitterBox) holds across the whole exec β†’ poll β†’ release window. Lock auto-expires after 30 minutes, so a crashed orchestrator can't strand the agent.


Security model

  • No authentication. Designed to run on a private VM only LitterBox should reach. Don't expose port 8080 to the internet.
  • Default sample drop: <exe-dir>\samples\, auto-created on first write, auto-cleaned per run. Override per-VM with --samples-dir or per-dispatch via the profile YAML's drop_path.
  • Privilege: payloads run as the user the Whiskers process is running as. --install registers the task as ONLOGON running as the invoking user β€” payloads run unelevated unless you launched the install from an elevated shell.
  • XOR-on-the-wire: when LitterBox dispatches with xor_key set, the agent reverses the XOR while writing to disk. Avoids cleartext payload sitting in HTTP buffers / OS network stacks where Defender's network inspection might flag it pre-write. The 64 KiB chunked-write keeps cleartext to a bounded in-memory window.

Troubleshooting

Bind error: address already in use Another process holds port 8080. Pick a different --port or stop the conflicting service.

Curl times out from another machine Windows Firewall is blocking. Verify with Get-NetFirewallRule -DisplayName "Whiskers".

Lock stuck "in_use" Wait 30 min for auto-expiry, or POST /api/lock/release from any client (release is unauthenticated β€” single-VM trust model).

/api/execute/exec returns 500 with Failed to spawn The EDR on the VM probably blocked the dropper or the spawn. Check the EDR's quarantine log; this is exactly the signal to capture.

/api/execute/exec returns 200 with {"status":"virus", ...} Whiskers detected an AV intercept on file write or spawn (Windows errno 225 / 995 / 1234). The orchestrator surfaces this as summary.blocked_by_av: true in the saved findings.

/api/logs/execution shows empty stdout The spawned process may not have flushed before exit, or it wrote to a separate console (GUI app). Best-effort capture for GUI / detached payloads.

/api/alerts/fibratus/since returns supported: false The agent didn't find C:\Program Files\Fibratus\Bin\fibratus.exe. Confirm Fibratus is installed at the default path; non-standard install paths aren't currently auto-detected.

/api/alerts/fibratus/since returns prose data strings instead of JSON Fibratus is in the default format: pretty mode. Edit %PROGRAMFILES%\Fibratus\Config\fibratus.yml to set alertsenders.eventlog.format: json and restart the Fibratus service. See Fibratus Setup.


See also

πŸ“Œ LitterBox Β· self-hosted payload analysis sandbox

Release


πŸš€ Getting Started

πŸ“Š Pipelines & Pages

πŸ”¬ Scanners Β· 4 modules

πŸ›°οΈ EDR Integration
πŸ”Œ API & Clients
βš™οΈ Configuration & Dev

Releases Β· CHANGELOG Β· Issues Β· README

Clone this wiki locally