Replace monolithic CLI and web server with route-based Flask API. New routes: api_commands, api_build, api_can, api_monitor, api_ota, api_tunnel. Add honeypot security dashboard with real-time SSE, MITRE ATT&CK mapping, kill chain analysis. New TUI with commander/help modules. Add session management, tunnel proxy core, CAN bus data store. Docker support.
296 lines
12 KiB
Python
296 lines
12 KiB
Python
from utils.display import Display
|
|
|
|
|
|
# ESP32 Commands organized by module (matches Kconfig modules)
|
|
ESP_MODULES = {
|
|
"system": {
|
|
"description": "Core system commands",
|
|
"commands": {
|
|
"system_reboot": "Reboot the ESP32 device",
|
|
"system_mem": "Get memory info (heap, internal)",
|
|
"system_uptime": "Get device uptime",
|
|
}
|
|
},
|
|
"network": {
|
|
"description": "Network tools",
|
|
"commands": {
|
|
"ping": "Ping a host (ping <host>)",
|
|
"arp_scan": "ARP scan the local network",
|
|
"proxy_start": "Start TCP proxy (proxy_start <ip> <port>)",
|
|
"proxy_stop": "Stop TCP proxy",
|
|
"dos_tcp": "TCP flood (dos_tcp <ip> <port> <count>)",
|
|
}
|
|
},
|
|
"fakeap": {
|
|
"description": "Fake Access Point module",
|
|
"commands": {
|
|
"fakeap_start": "Start fake AP (fakeap_start <ssid> [open|wpa2] [pass])",
|
|
"fakeap_stop": "Stop fake AP",
|
|
"fakeap_status": "Show fake AP status",
|
|
"fakeap_clients": "List connected clients",
|
|
"fakeap_portal_start": "Start captive portal",
|
|
"fakeap_portal_stop": "Stop captive portal",
|
|
"fakeap_sniffer_on": "Enable packet sniffer",
|
|
"fakeap_sniffer_off": "Disable packet sniffer",
|
|
}
|
|
},
|
|
"recon": {
|
|
"description": "Reconnaissance module (Camera + MLAT)",
|
|
"commands": {
|
|
"cam_start": "Start camera streaming (cam_start <ip> <port>)",
|
|
"cam_stop": "Stop camera streaming",
|
|
"mlat config": "Set position (mlat config [gps|local] <c1> <c2>)",
|
|
"mlat mode": "Set scan mode (mlat mode <ble|wifi>)",
|
|
"mlat start": "Start MLAT scanning (mlat start <mac>)",
|
|
"mlat stop": "Stop MLAT scanning",
|
|
"mlat status": "Show MLAT status",
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class HelpManager:
|
|
def __init__(self, command_registry, dev_mode: bool = False):
|
|
self.commands = command_registry
|
|
self.dev_mode = dev_mode
|
|
|
|
def _out(self, text: str):
|
|
"""Output helper that works in both CLI and TUI mode."""
|
|
Display.system_message(text)
|
|
|
|
def show(self, args: list[str]):
|
|
if args:
|
|
self._show_command_help(args[0])
|
|
else:
|
|
self._show_global_help()
|
|
|
|
def show_modules(self):
|
|
"""Show ESP commands organized by module."""
|
|
self._out("=== ESP32 COMMANDS BY MODULE ===")
|
|
self._out("")
|
|
|
|
for module_name, module_info in ESP_MODULES.items():
|
|
self._out(f"[{module_name.upper()}] - {module_info['description']}")
|
|
for cmd_name, cmd_desc in module_info["commands"].items():
|
|
self._out(f" {cmd_name:<20} {cmd_desc}")
|
|
self._out("")
|
|
|
|
self._out("Use 'help <command>' for detailed help on a specific command.")
|
|
self._out("Send commands with: send <device_id|all> <command> [args...]")
|
|
|
|
def _show_global_help(self):
|
|
self._out("=== ESPILON C2 HELP ===")
|
|
self._out("")
|
|
self._out("C2 Commands:")
|
|
self._out(" help [command] Show help or help for a specific command")
|
|
self._out(" list List connected ESP devices")
|
|
self._out(" modules List ESP commands organized by module")
|
|
self._out(" send <target> <cmd> Send a command to ESP device(s)")
|
|
self._out(" group <action> Manage device groups (add, remove, list, show)")
|
|
self._out(" active_commands List currently running commands")
|
|
self._out(" clear Clear terminal screen")
|
|
self._out(" exit Exit C2")
|
|
self._out("")
|
|
self._out("Server Commands:")
|
|
self._out(" web start|stop|status Web dashboard server")
|
|
self._out(" camera start|stop|status Camera UDP receiver")
|
|
self._out("")
|
|
self._out("ESP Commands: (use 'modules' for detailed list)")
|
|
|
|
registered_cmds = self.commands.list()
|
|
if registered_cmds:
|
|
for name in registered_cmds:
|
|
handler = self.commands.get(name)
|
|
self._out(f" {name:<15} {handler.description}")
|
|
else:
|
|
self._out(" (no registered commands - use 'send' with any ESP command)")
|
|
|
|
if self.dev_mode:
|
|
self._out("")
|
|
self._out("DEV MODE: Send arbitrary text: send <target> <any text>")
|
|
|
|
def _show_command_help(self, command_name: str):
|
|
# CLI Commands
|
|
if command_name == "list":
|
|
self._out("Help for 'list' command:")
|
|
self._out(" Usage: list")
|
|
self._out(" Description: Displays all connected ESP devices with ID, IP, status,")
|
|
self._out(" connection duration, and last seen timestamp.")
|
|
|
|
elif command_name == "send":
|
|
self._out("Help for 'send' command:")
|
|
self._out(" Usage: send <device_id|all|group <name>> <command> [args...]")
|
|
self._out(" Description: Sends a command to one or more ESP devices.")
|
|
self._out(" Examples:")
|
|
self._out(" send ESP_ABC123 reboot")
|
|
self._out(" send all wifi status")
|
|
self._out(" send group scanners mlat start AA:BB:CC:DD:EE:FF")
|
|
|
|
elif command_name == "group":
|
|
self._out("Help for 'group' command:")
|
|
self._out(" Usage: group <action> [args...]")
|
|
self._out(" Actions:")
|
|
self._out(" add <name> <id1> [id2...] Add devices to a group")
|
|
self._out(" remove <name> <id1> [id2...] Remove devices from a group")
|
|
self._out(" list List all groups")
|
|
self._out(" show <name> Show group members")
|
|
|
|
elif command_name == "web":
|
|
self._out("Help for 'web' command:")
|
|
self._out(" Usage: web <start|stop|status>")
|
|
self._out(" Description: Control the web dashboard server.")
|
|
self._out(" Actions:")
|
|
self._out(" start Start the web server (dashboard, cameras, MLAT)")
|
|
self._out(" stop Stop the web server")
|
|
self._out(" status Show server status and MLAT engine info")
|
|
self._out(" Default URL: http://127.0.0.1:8000 (configurable via .env)")
|
|
|
|
elif command_name == "camera":
|
|
self._out("Help for 'camera' command:")
|
|
self._out(" Usage: camera <start|stop|status>")
|
|
self._out(" Description: Control the camera UDP receiver.")
|
|
self._out(" Actions:")
|
|
self._out(" start Start UDP receiver for camera frames")
|
|
self._out(" stop Stop UDP receiver")
|
|
self._out(" status Show receiver stats (packets, frames, errors)")
|
|
self._out(" Default port: 5000 (configurable via .env)")
|
|
|
|
elif command_name == "modules":
|
|
self._out("Help for 'modules' command:")
|
|
self._out(" Usage: modules")
|
|
self._out(" Description: List all ESP32 commands organized by module.")
|
|
self._out(" Modules: system, network, fakeap, recon")
|
|
|
|
elif command_name in ["clear", "exit", "active_commands"]:
|
|
self._out(f"Help for '{command_name}' command:")
|
|
self._out(f" Usage: {command_name}")
|
|
descs = {
|
|
"clear": "Clear the terminal screen",
|
|
"exit": "Exit the C2 application",
|
|
"active_commands": "Show all commands currently being executed"
|
|
}
|
|
self._out(f" Description: {descs.get(command_name, '')}")
|
|
|
|
# ESP Commands (by module or registered)
|
|
else:
|
|
# Check in modules first
|
|
for module_name, module_info in ESP_MODULES.items():
|
|
if command_name in module_info["commands"]:
|
|
self._out(f"ESP Command '{command_name}' [{module_name.upper()}]:")
|
|
self._out(f" Description: {module_info['commands'][command_name]}")
|
|
self._show_esp_command_detail(command_name)
|
|
return
|
|
|
|
# Check registered commands
|
|
handler = self.commands.get(command_name)
|
|
if handler:
|
|
self._out(f"ESP Command '{command_name}':")
|
|
self._out(f" Description: {handler.description}")
|
|
if hasattr(handler, 'usage'):
|
|
self._out(f" Usage: {handler.usage}")
|
|
else:
|
|
Display.error(f"No help available for '{command_name}'.")
|
|
|
|
def _show_esp_command_detail(self, cmd: str):
|
|
"""Show detailed help for specific ESP commands."""
|
|
details = {
|
|
# MLAT subcommands
|
|
"mlat config": [
|
|
" Usage: send <device> mlat config [gps|local] <coord1> <coord2>",
|
|
" GPS mode: mlat config gps <lat> <lon> - degrees",
|
|
" Local mode: mlat config local <x> <y> - meters",
|
|
" Examples:",
|
|
" send ESP1 mlat config gps 48.8566 2.3522",
|
|
" send ESP1 mlat config local 10.0 5.5",
|
|
],
|
|
"mlat mode": [
|
|
" Usage: send <device> mlat mode <ble|wifi>",
|
|
" Example: send ESP1 mlat mode ble",
|
|
],
|
|
"mlat start": [
|
|
" Usage: send <device> mlat start <mac>",
|
|
" Example: send ESP1 mlat start AA:BB:CC:DD:EE:FF",
|
|
],
|
|
"mlat stop": [
|
|
" Usage: send <device> mlat stop",
|
|
],
|
|
"mlat status": [
|
|
" Usage: send <device> mlat status",
|
|
],
|
|
"cam_start": [
|
|
" Usage: send <device> cam_start <ip> <port>",
|
|
" Description: Start camera streaming to C2 UDP receiver",
|
|
" Example: send ESP_CAM cam_start 192.168.1.100 12345",
|
|
],
|
|
"cam_stop": [
|
|
" Usage: send <device> cam_stop",
|
|
" Description: Stop camera streaming",
|
|
],
|
|
"fakeap_start": [
|
|
" Usage: send <device> fakeap_start <ssid> [open|wpa2] [password]",
|
|
" Examples:",
|
|
" send ESP1 fakeap_start FreeWiFi",
|
|
" send ESP1 fakeap_start SecureNet wpa2 mypassword",
|
|
],
|
|
"fakeap_stop": [
|
|
" Usage: send <device> fakeap_stop",
|
|
],
|
|
"fakeap_status": [
|
|
" Usage: send <device> fakeap_status",
|
|
" Shows: AP running, portal status, sniffer status, client count",
|
|
],
|
|
"fakeap_clients": [
|
|
" Usage: send <device> fakeap_clients",
|
|
" Lists all connected clients to the fake AP",
|
|
],
|
|
"fakeap_portal_start": [
|
|
" Usage: send <device> fakeap_portal_start",
|
|
" Description: Enable captive portal (requires fakeap running)",
|
|
],
|
|
"fakeap_portal_stop": [
|
|
" Usage: send <device> fakeap_portal_stop",
|
|
],
|
|
"fakeap_sniffer_on": [
|
|
" Usage: send <device> fakeap_sniffer_on",
|
|
" Description: Enable packet sniffing",
|
|
],
|
|
"fakeap_sniffer_off": [
|
|
" Usage: send <device> fakeap_sniffer_off",
|
|
],
|
|
"ping": [
|
|
" Usage: send <device> ping <host>",
|
|
" Example: send ESP1 ping 8.8.8.8",
|
|
],
|
|
"arp_scan": [
|
|
" Usage: send <device> arp_scan",
|
|
" Description: Scan local network for hosts",
|
|
],
|
|
"proxy_start": [
|
|
" Usage: send <device> proxy_start <ip> <port>",
|
|
" Example: send ESP1 proxy_start 192.168.1.100 8080",
|
|
],
|
|
"proxy_stop": [
|
|
" Usage: send <device> proxy_stop",
|
|
],
|
|
"dos_tcp": [
|
|
" Usage: send <device> dos_tcp <ip> <port> <count>",
|
|
" Example: send ESP1 dos_tcp 192.168.1.100 80 1000",
|
|
],
|
|
"system_reboot": [
|
|
" Usage: send <device> system_reboot",
|
|
" Description: Reboot the ESP32 device",
|
|
],
|
|
"system_mem": [
|
|
" Usage: send <device> system_mem",
|
|
" Shows: heap_free, heap_min, internal_free",
|
|
],
|
|
"system_uptime": [
|
|
" Usage: send <device> system_uptime",
|
|
" Shows: uptime in days/hours/minutes/seconds",
|
|
],
|
|
}
|
|
|
|
if cmd in details:
|
|
for line in details[cmd]:
|
|
self._out(line)
|