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

GrumpyCats CLI

Command-line client for LitterBox. Same API surface as the web UI, scriptable from a shell.

python GrumpyCats/grumpycat.py [global flags] <command> [command flags]

The CLI is a thin wrapper: it parses args, builds a LitterBoxClient (see GrumpyCats Library), and renders the JSON response. Anything you do here you can also do programmatically.


Global flags

Flag Default Notes
--debug off Verbose request/response logging
--url http://127.0.0.1:1337 LitterBox server URL
--timeout 120 Per-request timeout (seconds)
--no-verify-ssl off Skip TLS verification
--proxy HTTP/HTTPS proxy URL

Intake

# Upload a file (and optionally kick off analysis on the same call)
grumpycat.py upload malware.exe
grumpycat.py upload malware.exe --analysis static dynamic
grumpycat.py upload payload.dll --analysis dynamic --args MyEntryPoint --args1 --args2

# Upload a kernel driver (and optionally HolyGrail-analyze it)
grumpycat.py upload-driver vuln.sys --holygrail

# Run dynamic analysis against a live process
grumpycat.py analyze-pid 1234 --wait

# Delete a sample (uploads + results + analysis folders)
grumpycat.py delete <md5>

--analysis accepts any subset of static dynamic. --args is forwarded to the dynamic runner. For a .dll payload the first token of --args is the exported entry point — Whiskers wraps the exec with rundll32.exe.


Results

# One specific result type
grumpycat.py results <md5> --type info       # file_info.json
grumpycat.py results <md5> --type static     # static_analysis_results.json
grumpycat.py results <md5> --type dynamic    # dynamic_analysis_results.json
grumpycat.py results <md5> --type holygrail  # byovd_results.json

# All saved results in parallel (faster than four sequential calls)
grumpycat.py results <md5> --comprehensive

For PIDs, pass the PID instead of the hash and use --type dynamic.


EDR

# List registered EDR profiles
grumpycat.py edr-profiles

# Live probe — Whiskers + backend reachability for every profile
grumpycat.py edr-status

# Dispatch a payload to a profile (fire-and-forget)
grumpycat.py edr-run <md5> --profile elastic
grumpycat.py edr-run <md5> --profile fibratus

# Dispatch and wait for Phase-2 to settle (or `--timeout` elapses)
grumpycat.py edr-run <md5> --profile fibratus --wait --timeout 180

# With XOR-on-the-wire (anti-AV-in-transit; Whiskers reverses on disk)
grumpycat.py edr-run <md5> --profile elastic --xor-key 42

# With command-line args forwarded to the payload
grumpycat.py edr-run <md5> --profile elastic --args --port 4444 --args --silent

# Read saved findings without re-dispatching
grumpycat.py edr-results <md5> --profile elastic
grumpycat.py edr-results <md5>                     # cross-profile index

# Test the Fibratus alert wire without running a payload — useful right
# after you've set up Fibratus on a new VM and want to confirm the
# alertsenders.eventlog -> Whiskers path is wired up before dispatch
grumpycat.py fibratus-alerts --profile fibratus \
    --from 2026-04-30T00:00:00Z \
    --until 2026-04-30T01:00:00Z

# Local scanner inventory (paths + presence)
grumpycat.py scanners

Doppelganger

# Snapshot the current host as the blender baseline
grumpycat.py doppelganger-scan --type blender

# Compare a payload against the blender host snapshot
grumpycat.py doppelganger-analyze <md5> --type blender

# Run fuzzy-hash similarity against the offensive-tools DB
grumpycat.py doppelganger-analyze <md5> --type fuzzy --threshold 85

# (Re)build the fuzzy-hash database from a folder of reference binaries
grumpycat.py doppelganger-db --folder C:\Tools\Offensive --extensions .exe .dll

Reports

# Render the HTML report and pipe it somewhere
grumpycat.py report <md5> > report.html

# Download the report (server returns Content-Disposition: attachment)
grumpycat.py report <md5> --download --output ./reports/

# Download AND open in the default browser
grumpycat.py report <md5> --download --browser

System

# Quick health probe + tool status
grumpycat.py status              # short
grumpycat.py status --full       # full inventory (includes scanner paths, EDR fleet)

# Just the boot-time health check
grumpycat.py health

# Cross-sample summary
grumpycat.py files

# Cleanup — DESTRUCTIVE
grumpycat.py cleanup --all                          # everything
grumpycat.py cleanup --uploads                      # only Uploads/
grumpycat.py cleanup --results --analysis           # results folders + PE-Sieve analysis

Exit codes

0 on success, 1 on any error (network, HTTP non-2xx, validation, etc.). Errors are written to stderr; JSON output goes to stdout (so grumpycat.py results ... | jq works as expected).


See also

📌 LitterBox · self-hosted payload analysis sandbox

Release


🚀 Getting Started

📊 Pipelines & Pages

🔬 Scanners · 4 modules

🛰️ EDR Integration
🔌 API & Clients
⚙️ Configuration & Dev

Clone this wiki locally