---
name: draw-topology
description: >
  把网络资产、内网横向和攻击路径画到 draw 拓扑画布上。
  当用户提到画拓扑、横向移动、攻击链、分区资产、APT 图、或打开这个站点时使用。
---

# draw — 拓扑绘图 Skill

你正在操作 **draw**：浏览器里的网络安全攻击拓扑工具。画布文档是 JSON。站点作者信息在应用运行时解码。你不要假装已经改了用户屏幕上的图——必须按下面任一方式交付。

交付 URL 一律使用**当前页面 origin**，不要写死其它域名。

## 发现（访问网站时）

先 GET 这些路径（都是纯文本 / JSON）：

| 路径 | 内容 |
|---|---|
| `/llms.txt` | 入口 |
| `/SKILL.md` | 本文件 |
| `/agent-protocol.json` | JSON Schema |
| `/mcp` | 静态站无服务端，请忽略 POST |
| `/for-agents` | 人读说明 |

站点 `<head>` 里有 `rel=describedby` 指向 `/llms.txt`。

## 交付方式（按优先级）

1. **打开 URL（推荐）**  
   生成计划后让用户打开：
   `{当前 origin}/?plan={base64url(JSON)}`  
   要覆盖成一张新图时加 `&replace=1`。  
   省略 replace 则**追加**到当前画布（适合在校园网上叠横向）。
2. **MCP** `tools/call` → `encode_open_url` 直接得到上面的 URL。
3. **导入**  
   用户打开应用内「导入」，选择 Agent / 画布 JSON。
4. **不要**输出 SVG/Mermaid 代替协议 JSON。

`plan` 参数是 **UTF-8 JSON 的 base64url**（`+`→`-`，`/`→`_`，去掉 `=`）。

## AgentPlan JSON

```json
{
  "title": "办公网横向到域控",
  "summary": "一句话",
  "actions": []
}
```

### add_node
```json
{ "op": "add_node", "id": "ws1", "type": "desktop", "label": "办公机", "col": 0, "row": 0, "meta": { "os": "Windows 10", "ip": "10.0.8.12" } }
```

- `id` 稳定、简短、唯一。
- `type` 必须来自下面的类型表。
- `col` / `row` 是网格坐标（整数）。列 = 阶段，行 = 平行路径。相邻节点至少隔 1。
- `label` 中文，≤24 字。

### add_edge
```json
{ "op": "add_edge", "from": "ws1", "to": "dc1", "label": "WMI", "style": "dashed", "color": "#D94F4F" }
```

- `from` / `to` 用节点 `id`，或画布上已有节点的唯一中文名。
- 已攻陷 / 横向：`style: "dashed"`, `color: "#D94F4F"`。
- 正常业务：`style: "solid"`，不要 `color`。
- `label` 写手法族或协议：WMI、RDP、PtH、Kerberoast、SMB、HTTPS。不要写 exploit / POC。

### add_zone
```json
{ "op": "add_zone", "id": "z_id", "label": "身份区", "color": "#3D6B8A", "c0": 2, "r0": 0, "c1": 3, "r1": 1 }
```

`c0,r0` 到 `c1,r1` 是包含该区内节点的网格包围盒。

### note
```json
{ "op": "note", "text": "给操作员的说明" }
```

限额：单次最多 24 个新节点、32 条新边、6 个新区。

## 节点类型

**网络** `internet` 互联网/云 · `router` 路由器 · `switch` 交换机 · `wifi-ap` 无线 AP  
**安全** `firewall` 防火墙 · `waf` WAF · `proxy` 代理 · `load-balancer` 负载均衡 · `vpn` VPN  
**基础设施** `identity` 身份/AD · `email-gw` 邮件网关 · `saas` SaaS · `server` 服务器 · `database` 数据库 · `storage` 存储 · `desktop` 台式机 · `laptop` 笔记本 · `mobile` 移动设备 · `iot` 物联网  
**威胁** `threat-actor` 威胁行为体 · `malware` 恶意软件 · `c2-server` C2 · `phishing` 钓鱼 · `botnet` 僵尸网络 · `insider` 内部人员

## 内网横向怎么画

列（从左到右）：

0 入口/钓鱼/VPN → 1 工作站/跳板 → 2 身份（AD/SSO）→ 3 服务器/数据库 → 4 目标或外传

同一阶段多台机器用不同 `row`。不要把所有节点排成一条横线。

已有校园网分区图时：复用已有节点 id/名称连边，只添加缺失的跳点和红色虚线。

## 例子

用户：「钓鱼进办公机，WMI 打到域控，再访问业务库」

```json
{
  "title": "钓鱼到域控",
  "summary": "办公机经 WMI 横向到 AD，再访问业务库",
  "actions": [
    { "op": "add_zone", "id": "z_lat", "label": "横向路径", "color": "#D94F4F", "c0": 0, "r0": 0, "c1": 3, "r1": 0 },
    { "op": "add_node", "id": "phish", "type": "phishing", "label": "钓鱼邮件", "col": 0, "row": 0 },
    { "op": "add_node", "id": "ws", "type": "desktop", "label": "办公主机", "col": 1, "row": 0, "meta": { "os": "Windows 10" } },
    { "op": "add_node", "id": "dc", "type": "identity", "label": "域控", "col": 2, "row": 0, "meta": { "kind": "Active Directory" } },
    { "op": "add_node", "id": "db", "type": "database", "label": "业务库", "col": 3, "row": 0, "meta": { "engine": "MySQL" } },
    { "op": "add_edge", "from": "phish", "to": "ws", "label": "附件", "style": "dashed", "color": "#D94F4F" },
    { "op": "add_edge", "from": "ws", "to": "dc", "label": "WMI", "style": "dashed", "color": "#D94F4F" },
    { "op": "add_edge", "from": "dc", "to": "db", "label": "票据", "style": "dashed", "color": "#D94F4F" }
  ]
}
```

## MCP 工具

`POST /mcp` JSON-RPC 2.0：

- `initialize`
- `tools/list`
- `tools/call`  
  - `get_skill`  
  - `list_node_types`  
  - `validate_plan` 参数 `{ plan }`  
  - `encode_open_url` 参数 `{ plan, replace?: boolean }` → `{ path, hint }`

## 禁止

- 不写利用步骤、载荷、命令行。
- 不编造未公开漏洞。
- 不用 Mermaid/ASCII 冒充已上画布。
- 不把全部节点挤在 row=0 一条线上。
