Chumikov/CTFd-Skill

GitHub: Chumikov/CTFd-Skill

为 opencode 智能体打造的 CTFd 平台交互技能,提供挑战管理、flag 提交、持久化工作区等完整的玩家端 API 功能。

Stars: 0 | Forks: 0

# CTFd Skill 一个用于 [opencode](https://opencode.ai) 的技能 (skill),允许智能体通过统一的 REST 接口 (`/api/v1`) 与任何基于 **[CTFd](https://ctfd.io)** 引擎的 CTF 平台 API 进行交互。它可以帮助参与 CTF:任务列表、阅读说明、下载文件、提交 flag、解锁提示、查看排名和公告。 该技能面向**玩家** (player):涵盖普通账户可执行的操作,不包含管理员端点。 ## 功能 - 列出并详细查看挑战(分类、分数、解答次数、“我是否已解答”) - **提交 flag**,处理所有响应变体 (`correct` / `incorrect` / `already_solved` / `partial` / `ratelimited` / …) - 遇到 `429` 时自动 backoff(CTFd 的防暴力破解机制)——客户端会自动从响应中读取等待的秒数并执行一次重试 - 通过已签名的 URL 下载附件 - 为每个任务提供**持久化工作区** (`~/Downloads/ctf////`) —— 文件、脚本和日志在重启后依然保留(而不是 `/tmp`) - **解题进度日志** `NOTES.md` —— 自动追加带有日期的记录(假设/尝试/结果) - **提示智能体优先使用 `hexstrike_*` MCP 工具**处理 offsec 任务(在上下文压缩后依然保留) - 解锁提示和官方解答(考虑扣减分数) - 排名、前 N 名、个人资料、团队资料 - 轮询组织者公告 (`since_id`) - 管理个人的 API token(创建 / 列出 / 撤销) - 通过 **API token** 进行授权(推荐)或使用账号/密码登录 - 适用于**任何** CTFd 实例 —— 不绑定特定的平台 ## 环境要求 - [opencode](https://opencode.ai) ≥ 2.x - Python 3.8+ - [`requests`](https://pypi.org/project/requests/) — `pip install requests` ## 安装说明 在 opencode 中,该技能的名称为 `ctfd-api`。本地目标目录**必须**命名为 `ctfd-api`(与 `SKILL.md` 中的 `name` 字段保持一致)。 ### 方法 1 — 全局安装(推荐) 该技能将对当前用户的所有项目可用。 ``` git clone https://github.com/Chumikov/CTFd-Skill ~/.config/opencode/skills/ctfd-api ``` ### 方法 2 — 在特定项目中安装 将该技能放置在与其相关的 CTF 仓库旁边。 ``` git clone https://github.com/Chumikov/CTFd-Skill .opencode/skills/ctfd-api ``` ### 方法 3 — 通过 `opencode.jsonc` 如果该技能位于非标准目录下,请显式指定路径: ``` { "$schema": "https://opencode.ai/config.json", "skills": { "paths": ["/абсолютный/путь/к/ctfd-api"] } } ``` ### 方法 4 — 手动安装(不使用 git) 下载 [仓库压缩包](https://github.com/Chumikov/CTFd-Skill/archive/refs/heads/main.zip), 并将其解压到 `~/.config/opencode/skills/ctfd-api/`。 ### 验证 安装完成后,运行 opencode —— `ctfd-api` 技能将出现在可用列表中。智能体会根据请求自动加载它(例如,当您输入“在任务 42 中提交 flag”时)。 ## 配置 该技能需要两个值:实例的 host 和 API token。建议将它们放入环境变量中: ``` export CTFD_HOST="https://ctf.example.com" export CTFD_TOKEN="ctfd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` token 在 Web 界面中创建:**Settings → Access Tokens → Generate** (该值仅显示一次)。或者,也可以通过客户端自动生成(见下文)。 ## 使用方法 ### 通过 opencode 智能体 只需使用自然语言要求即可,例如: - “显示 ctf.bug-makers.ru 上的任务列表” - “打开任务 42 并下载它的文件” - “在任务 42 中提交 flag `BugCTF{demo}`” 智能体会自动加载该技能并调用相应的方法。 ### 直接从 Python 中使用 ``` import sys sys.path.insert(0, "scripts") from ctfd_client import CTfdClient c = CTfdClient.from_env() # читает CTFD_HOST / CTFD_TOKEN print(c.list_challenges()) # список задач detail = c.get_challenge(42) # условие, файлы, хинты ws = c.init_challenge_workspace(detail) # персистентный воркспейс (НЕ /tmp) for f in detail["files"]: c.download_file(f) # → ws/attachments/ (dest_dir=None по умолчанию) c.log_attempt(42, "Начало решения", "hypothesis") # запись в ws/NOTES.md # ... 解决方案 (对于 offsec — 优先使用 hexstrike_* 工具,参见 SKILL.md §7a) ... verdict = c.attempt(42, "BugCTF{example}") # {"status": "correct", ...} c.log_attempt(42, "BugCTF{example}", "solved") ``` 密码授权(如果没有 token): ``` c = CTfdClient.from_userpass("https://ctf.example.com", "username", "password") ``` ### 通过 CLI ``` python scripts/ctfd_client.py challenges --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py challenge 42 --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py submit 42 'BugCTF{...}' --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py me --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py scoreboard --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py top 10 --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py hint 7 --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py unlock-hint 7 --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py notifications --since-id 5 --host "$CTFD_HOST" --token "$CTFD_TOKEN" python scripts/ctfd_client.py gen-token --description "automation" --expiration 2026-12-31 python scripts/ctfd_client.py tokens python scripts/ctfd_client.py revoke-token 3 ``` 完整的端到端演示场景(默认仅读取): ``` python examples/solve_flow.py python examples/solve_flow.py --show-id 42 python examples/solve_flow.py --submit-id 42 --flag 'BugCTF{...}' ``` ## 持久化工作区 为了让任务文件、解题脚本和解答日志**不会在重启后丢失** (曾经有整个 CTF 周末的成果存放在 `/tmp` 中,结果被重启清空了),该技能会在 `~/Downloads/ctf/` 下为每个任务创建持久化结构: ``` ~/Downloads/ctf//// ├── challenge.yaml # метаданные CTFd (id, name, host, solved) ├── description.md # условие задачи ├── attachments/ # скачанные файлы (автоматически через download_file) ├── scripts/ # самописные solve-скрипты/эксплойты — запускать отсюда └── NOTES.md # журнал хода решения (append через log_attempt) ``` - `` 从实例的 host 中提取(`nhnc.ic3dt3a.org` → `nhnc-2026`); 可通过环境变量 `CTFD_EVENT` 覆盖。 - `init_challenge_workspace(detail)` 会创建脚手架 + `description.md` + `NOTES.md` 标题。 - `download_file(f)` 如果不带 `dest_dir` 参数,文件会被放入 `attachments/`。 - `log_attempt(challenge_id, entry, status)` 会向 `NOTES.md` 追加带有日期的记录 (`status`:`hypothesis` / `tried` / `solved` / `failed`)。 临时的草稿文件(一次性的 `curl` 测试、解压的二进制文件等)依然会存放在 `/tmp` 中。自定义脚本则存放在工作区的 `scripts/` 目录下。 ## 安全性 - **不要滥用 `submit`**。 CTFd 具有防暴力破解机制(每个账户+任务组合每分钟约允许 10 次错误提交,超过后触发 `429 ratelimited`)以及针对单个挑战的 `max_attempts` 和 `lockout` 模式 —— 胡乱盲猜可能会**永久**锁定您的任务。客户端能正确处理 `429`,但多余的错误尝试仍然会被记录在历史中。 - token 意味着对您账户的完全访问权限。请勿将其提交到代码仓库或泄露到聊天室中。 - `unlock-hint` 会从您个人或团队的账户中扣除真实的分数。 ## 项目结构 ``` CTFd-Skill/ ├── SKILL.md # тело навыка для opencode ├── scripts/ │ └── ctfd_client.py # Python-клиент + CLI ├── examples/ │ └── solve_flow.py # демо: список → скачать → флаг ├── README.md # этот файл ├── LICENSE # MIT └── .gitignore ``` ## 兼容性 支持 CTFd 3.x,REST API v1。客户端逻辑是根据 CTFd 的源码 (`master`) 推导出来的,不调用任何第三方的非官方端点。 ## 许可证 [MIT](LICENSE)。
标签:API客户端, CTF辅助, Python, 无后门, 网络调试, 自动化, 逆向工具