CTFx 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ctfx-0.2.2/.github/workflows/python-publish.yml +62 -0
- ctfx-0.2.2/.gitignore +54 -0
- ctfx-0.2.2/Makefile +65 -0
- ctfx-0.2.2/PKG-INFO +273 -0
- ctfx-0.2.2/README.md +250 -0
- ctfx-0.2.2/ctfx/__init__.py +3 -0
- ctfx-0.2.2/ctfx/cli.py +81 -0
- ctfx-0.2.2/ctfx/commands/__init__.py +1 -0
- ctfx-0.2.2/ctfx/commands/ai.py +228 -0
- ctfx-0.2.2/ctfx/commands/awd.py +214 -0
- ctfx-0.2.2/ctfx/commands/challenge.py +211 -0
- ctfx-0.2.2/ctfx/commands/competition.py +227 -0
- ctfx-0.2.2/ctfx/commands/config.py +109 -0
- ctfx-0.2.2/ctfx/commands/interactive.py +32 -0
- ctfx-0.2.2/ctfx/commands/platform.py +383 -0
- ctfx-0.2.2/ctfx/commands/serve.py +48 -0
- ctfx-0.2.2/ctfx/commands/setup.py +125 -0
- ctfx-0.2.2/ctfx/commands/terminal.py +168 -0
- ctfx-0.2.2/ctfx/commands/token.py +55 -0
- ctfx-0.2.2/ctfx/commands/webui.py +41 -0
- ctfx-0.2.2/ctfx/exceptions.py +17 -0
- ctfx-0.2.2/ctfx/managers/__init__.py +1 -0
- ctfx-0.2.2/ctfx/managers/awd.py +106 -0
- ctfx-0.2.2/ctfx/managers/config.py +248 -0
- ctfx-0.2.2/ctfx/managers/platform/__init__.py +1 -0
- ctfx-0.2.2/ctfx/managers/platform/base.py +23 -0
- ctfx-0.2.2/ctfx/managers/platform/ctfd.py +68 -0
- ctfx-0.2.2/ctfx/managers/scaffold.py +88 -0
- ctfx-0.2.2/ctfx/managers/workspace.py +310 -0
- ctfx-0.2.2/ctfx/server/__init__.py +1 -0
- ctfx-0.2.2/ctfx/server/api.py +714 -0
- ctfx-0.2.2/ctfx/server/app.py +164 -0
- ctfx-0.2.2/ctfx/server/auth.py +174 -0
- ctfx-0.2.2/ctfx/server/mcp.py +7 -0
- ctfx-0.2.2/ctfx/server/mcp_server.py +258 -0
- ctfx-0.2.2/ctfx/utils/__init__.py +1 -0
- ctfx-0.2.2/ctfx/utils/process.py +56 -0
- ctfx-0.2.2/frontend/index.html +13 -0
- ctfx-0.2.2/frontend/package.json +33 -0
- ctfx-0.2.2/frontend/src/App.tsx +36 -0
- ctfx-0.2.2/frontend/src/components/Layout.tsx +222 -0
- ctfx-0.2.2/frontend/src/index.css +84 -0
- ctfx-0.2.2/frontend/src/lib/api.ts +336 -0
- ctfx-0.2.2/frontend/src/lib/compContext.tsx +52 -0
- ctfx-0.2.2/frontend/src/lib/utils.ts +5 -0
- ctfx-0.2.2/frontend/src/main.tsx +18 -0
- ctfx-0.2.2/frontend/src/pages/ChallengePage.tsx +446 -0
- ctfx-0.2.2/frontend/src/pages/CompetitionProfile.tsx +315 -0
- ctfx-0.2.2/frontend/src/pages/Competitions.tsx +247 -0
- ctfx-0.2.2/frontend/src/pages/Dashboard.tsx +249 -0
- ctfx-0.2.2/frontend/src/pages/FlagsPage.tsx +124 -0
- ctfx-0.2.2/frontend/src/pages/Settings.tsx +209 -0
- ctfx-0.2.2/frontend/src/pages/SubmitPage.tsx +166 -0
- ctfx-0.2.2/frontend/src/pages/awd/AWDExploits.tsx +72 -0
- ctfx-0.2.2/frontend/src/pages/awd/AWDHostMap.tsx +76 -0
- ctfx-0.2.2/frontend/src/pages/awd/AWDOverview.tsx +66 -0
- ctfx-0.2.2/frontend/src/pages/awd/AWDPatches.tsx +82 -0
- ctfx-0.2.2/frontend/tsconfig.app.json +22 -0
- ctfx-0.2.2/frontend/tsconfig.app.tsbuildinfo +1 -0
- ctfx-0.2.2/frontend/tsconfig.json +7 -0
- ctfx-0.2.2/frontend/tsconfig.node.json +10 -0
- ctfx-0.2.2/frontend/tsconfig.node.tsbuildinfo +1 -0
- ctfx-0.2.2/frontend/vite.config.d.ts +2 -0
- ctfx-0.2.2/frontend/vite.config.js +16 -0
- ctfx-0.2.2/frontend/vite.config.ts +17 -0
- ctfx-0.2.2/pyproject.toml +46 -0
- ctfx-0.2.2/tests/__init__.py +1 -0
- ctfx-0.2.2/tests/conftest.py +62 -0
- ctfx-0.2.2/tests/test_api.py +259 -0
- ctfx-0.2.2/tests/test_auth.py +91 -0
- ctfx-0.2.2/tests/test_config.py +68 -0
- ctfx-0.2.2/tests/test_process.py +20 -0
- ctfx-0.2.2/tests/test_scaffold.py +56 -0
- ctfx-0.2.2/tests/test_workspace.py +140 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Upload Python Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
release-build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: "20"
|
|
20
|
+
|
|
21
|
+
- name: Build frontend
|
|
22
|
+
run: |
|
|
23
|
+
cd frontend
|
|
24
|
+
npm install
|
|
25
|
+
npm install @rollup/rollup-linux-x64-gnu lightningcss-linux-x64-gnu --no-save
|
|
26
|
+
npm run build
|
|
27
|
+
|
|
28
|
+
- uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.11"
|
|
31
|
+
|
|
32
|
+
- name: Build release distributions
|
|
33
|
+
run: |
|
|
34
|
+
python -m pip install --upgrade build
|
|
35
|
+
python -m build
|
|
36
|
+
|
|
37
|
+
- name: Upload distributions
|
|
38
|
+
uses: actions/upload-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: release-dists
|
|
41
|
+
path: dist/
|
|
42
|
+
|
|
43
|
+
pypi-publish:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
needs: release-build
|
|
46
|
+
permissions:
|
|
47
|
+
id-token: write
|
|
48
|
+
environment:
|
|
49
|
+
name: pypi
|
|
50
|
+
url: https://pypi.org/project/ctfx/
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- name: Retrieve release distributions
|
|
54
|
+
uses: actions/download-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: release-dists
|
|
57
|
+
path: dist/
|
|
58
|
+
|
|
59
|
+
- name: Publish release distributions to PyPI
|
|
60
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
61
|
+
with:
|
|
62
|
+
packages-dir: dist/
|
ctfx-0.2.2/.gitignore
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
prompt.md
|
|
2
|
+
progress.md
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
**/_pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*.pyo
|
|
9
|
+
*.pyd
|
|
10
|
+
*.egg-info/
|
|
11
|
+
*.egg
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
.eggs/
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
.env
|
|
19
|
+
*.env
|
|
20
|
+
|
|
21
|
+
**/package-lock.json
|
|
22
|
+
|
|
23
|
+
# uv
|
|
24
|
+
.python-version
|
|
25
|
+
uv.lock
|
|
26
|
+
|
|
27
|
+
# Node / React frontend
|
|
28
|
+
frontend/node_modules/
|
|
29
|
+
frontend/dist/
|
|
30
|
+
frontend/.vite/
|
|
31
|
+
ctfx/server/static/
|
|
32
|
+
|
|
33
|
+
# Distribution
|
|
34
|
+
*.whl
|
|
35
|
+
*.tar.gz
|
|
36
|
+
|
|
37
|
+
# Editor
|
|
38
|
+
.vscode/
|
|
39
|
+
.idea/
|
|
40
|
+
*.swp
|
|
41
|
+
*.swo
|
|
42
|
+
|
|
43
|
+
# OS
|
|
44
|
+
.DS_Store
|
|
45
|
+
Thumbs.db
|
|
46
|
+
|
|
47
|
+
# Test / coverage
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
.coverage
|
|
50
|
+
htmlcov/
|
|
51
|
+
.tox/
|
|
52
|
+
|
|
53
|
+
.claude/
|
|
54
|
+
.pytest*
|
ctfx-0.2.2/Makefile
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
.PHONY: install dev test build clean lint frontend
|
|
2
|
+
|
|
3
|
+
PYTHON ?= python
|
|
4
|
+
PYTEST_FLAGS ?= -v
|
|
5
|
+
PROTOBUF_ENV = PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
|
|
6
|
+
|
|
7
|
+
# ── Install ──────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
install:
|
|
10
|
+
$(PYTHON) -m pip install -e .
|
|
11
|
+
|
|
12
|
+
install-llm:
|
|
13
|
+
$(PYTHON) -m pip install -e ".[llm]"
|
|
14
|
+
|
|
15
|
+
dev:
|
|
16
|
+
$(PYTHON) -m pip install -e ".[llm]"
|
|
17
|
+
$(PYTHON) -m pip install pytest pytest-asyncio httpx ruff
|
|
18
|
+
|
|
19
|
+
# ── Tests ─────────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
test:
|
|
22
|
+
$(PROTOBUF_ENV) $(PYTHON) -m pytest $(PYTEST_FLAGS) tests/
|
|
23
|
+
|
|
24
|
+
test-quick:
|
|
25
|
+
$(PROTOBUF_ENV) $(PYTHON) -m pytest -x -q tests/
|
|
26
|
+
|
|
27
|
+
test-cov:
|
|
28
|
+
$(PROTOBUF_ENV) $(PYTHON) -m pytest $(PYTEST_FLAGS) --tb=short tests/
|
|
29
|
+
|
|
30
|
+
# ── Lint ──────────────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
lint:
|
|
33
|
+
$(PYTHON) -m ruff check ctfx/ tests/
|
|
34
|
+
|
|
35
|
+
lint-fix:
|
|
36
|
+
$(PYTHON) -m ruff check --fix ctfx/ tests/
|
|
37
|
+
|
|
38
|
+
# ── Frontend ──────────────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
frontend:
|
|
41
|
+
cd frontend && npm install && npm run build
|
|
42
|
+
|
|
43
|
+
frontend-dev:
|
|
44
|
+
cd frontend && npm run dev
|
|
45
|
+
|
|
46
|
+
# ── Clean ─────────────────────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
clean:
|
|
49
|
+
rm -rf dist/ build/ *.egg-info .pytest_cache __pycache__
|
|
50
|
+
find ctfx -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true
|
|
51
|
+
find tests -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true
|
|
52
|
+
|
|
53
|
+
# ── Build wheel ───────────────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
build: frontend
|
|
56
|
+
$(PYTHON) -m pip install --upgrade build
|
|
57
|
+
$(PYTHON) -m build
|
|
58
|
+
|
|
59
|
+
# ── Quick dev loop ────────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
run-server:
|
|
62
|
+
ctfx serve
|
|
63
|
+
|
|
64
|
+
webui:
|
|
65
|
+
ctfx webui
|
ctfx-0.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: CTFx
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Local-first CTF workspace manager and assistant CLI
|
|
5
|
+
Author: Li Yan
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: click>=8.1
|
|
9
|
+
Requires-Dist: fastapi>=0.110
|
|
10
|
+
Requires-Dist: httpx>=0.27
|
|
11
|
+
Requires-Dist: itsdangerous>=2.1
|
|
12
|
+
Requires-Dist: mcp>=1.0
|
|
13
|
+
Requires-Dist: paramiko>=3.0
|
|
14
|
+
Requires-Dist: prompt-toolkit>=3.0
|
|
15
|
+
Requires-Dist: pydantic>=2.0
|
|
16
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
17
|
+
Requires-Dist: requests>=2.31
|
|
18
|
+
Requires-Dist: rich>=13.0
|
|
19
|
+
Requires-Dist: uvicorn[standard]>=0.29
|
|
20
|
+
Provides-Extra: llm
|
|
21
|
+
Requires-Dist: anthropic>=0.40; extra == 'llm'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# CTFx
|
|
25
|
+
|
|
26
|
+
A local-first CTF workspace manager and assistant CLI for Jeopardy and AWD competitions.
|
|
27
|
+
|
|
28
|
+
## Background
|
|
29
|
+
|
|
30
|
+
CTFx started from a bunch of PowerShell scripts I wrote for CTF competitions back in HKCERT 2024.
|
|
31
|
+
|
|
32
|
+
Later, in the HKCERT 2025 Final, I made a Python-based CTF Assistant for AWD matches. It worked pretty well, got some positive feedback, and helped our team achieve a solid result.
|
|
33
|
+
|
|
34
|
+
After that, I decided to turn those ideas and experiences into CTFx, hoping it can give CTF players a bit of extra help in the AI era.
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
- **Competition management** — create, list, and switch between CTF workspaces
|
|
39
|
+
- **Challenge scaffolding** — auto-generate category-specific solve templates (`pwn`, `crypto`, `forensics`, `rev`, `misc`)
|
|
40
|
+
- **Platform integration** — fetch challenges and submit flags via CTFd API using either team token or platform cookies
|
|
41
|
+
- **Terminal integration** — open shells, WSL, editors, and file explorers at challenge paths
|
|
42
|
+
- **AI context** — generate `prompt.md` with competition context plus CLI/MCP usage notes for LLM-assisted solving
|
|
43
|
+
- **WebUI** — React dashboard with challenge add/delete, editable challenge detail, flags table, and writeup editor
|
|
44
|
+
- **REST API + MCP** — machine-readable interface for Claude Desktop / Cursor integration
|
|
45
|
+
- **AWD mode** — SSH/SCP helpers, exploit runner, patch tracker, host map
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
Requires Python 3.11+.
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pip install ctfx
|
|
53
|
+
# or with uv (recommended)
|
|
54
|
+
uv tool install CTFx
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Install Guide
|
|
58
|
+
|
|
59
|
+
Install from PyPI:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
pip install ctfx
|
|
63
|
+
ctfx --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Upgrade to the latest release:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
pip install -U ctfx
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Install from a local checkout during development:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
git clone https://github.com/liyanqwq/CTFx
|
|
76
|
+
cd CTFx
|
|
77
|
+
pip install -e .
|
|
78
|
+
ctfx --help
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quick Start
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
# First run — initializes ~/.config/ctfx/config.json
|
|
85
|
+
ctfx setup
|
|
86
|
+
|
|
87
|
+
# Create a competition workspace
|
|
88
|
+
ctfx comp init --name HKCERT_CTF --year 2025 --mode jeopardy --platform ctfd
|
|
89
|
+
|
|
90
|
+
# Switch to it
|
|
91
|
+
ctfx use HKCERT_CTF_2025
|
|
92
|
+
|
|
93
|
+
# Add a challenge
|
|
94
|
+
ctfx add baby_pwn pwn
|
|
95
|
+
|
|
96
|
+
# Open in editor
|
|
97
|
+
ctfx code pwn/baby_pwn
|
|
98
|
+
|
|
99
|
+
# Open a terminal at the solve directory
|
|
100
|
+
ctfx cli pwn/baby_pwn/solve
|
|
101
|
+
|
|
102
|
+
# Start the WebUI + API + MCP server
|
|
103
|
+
ctfx serve
|
|
104
|
+
|
|
105
|
+
# Open WebUI in browser (auto-login)
|
|
106
|
+
ctfx webui
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Typical Flag Workflow
|
|
110
|
+
|
|
111
|
+
`CTFx` now separates local flag recording from remote submission:
|
|
112
|
+
|
|
113
|
+
1. Save a discovered flag locally in the WebUI or via API. This moves the challenge to `hoard`.
|
|
114
|
+
2. Review hoarded flags in the `Flags` page.
|
|
115
|
+
3. Submit the flag to the remote platform when ready.
|
|
116
|
+
4. A successful remote submission promotes the challenge to `solved`.
|
|
117
|
+
|
|
118
|
+
## Notes
|
|
119
|
+
|
|
120
|
+
- Paths passed to `ctfx cli`, `ctfx code`, `ctfx explorer`, API routes, and MCP tools are restricted to the active competition workspace. Escaping with `..` is rejected.
|
|
121
|
+
- Challenge categories, challenge names, and AWD service names are treated as path components and must not contain `/` or `\\`.
|
|
122
|
+
- If `terminal.python_cmd` contains spaces, quote the executable path normally. Example on Windows: `"C:\Program Files\Python313\python.exe" -u`
|
|
123
|
+
- `ctfx webui` generates a one-time login URL for the local WebUI. API and MCP still use the root token unless you are already authenticated in the browser.
|
|
124
|
+
- For platform-backed competitions, set either `team_token` or `team_cookies` in the competition profile before attempting remote submission.
|
|
125
|
+
- Challenge status flow is `fetched -> seen -> working -> hoard -> solved`.
|
|
126
|
+
|
|
127
|
+
## CLI Reference
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
ctfx comp list [query] List competitions
|
|
131
|
+
ctfx comp use <name> Set active competition
|
|
132
|
+
ctfx comp init Create new competition workspace
|
|
133
|
+
ctfx comp info Show active competition metadata
|
|
134
|
+
|
|
135
|
+
ctfx chal list [query] [--cat] [--status] List challenges
|
|
136
|
+
ctfx chal add <name> [cat] Add and scaffold a challenge
|
|
137
|
+
ctfx chal rm <name> Remove a challenge
|
|
138
|
+
ctfx chal info <name> Show challenge detail
|
|
139
|
+
ctfx chal status <name> <status> Update challenge status
|
|
140
|
+
|
|
141
|
+
ctfx cli [path] Open terminal at path
|
|
142
|
+
ctfx wsl [path] [-- cmd] Open WSL shell or run command
|
|
143
|
+
ctfx e [path] Open file explorer
|
|
144
|
+
ctfx code [path] Open editor
|
|
145
|
+
ctfx py [file] Run Python in configured environment
|
|
146
|
+
|
|
147
|
+
ctfx fetch [--cat] [--chal] Fetch challenges from platform
|
|
148
|
+
ctfx submit <flag> [--chal] Submit flag to platform
|
|
149
|
+
ctfx import <url> LLM-assisted challenge import
|
|
150
|
+
|
|
151
|
+
ctfx ai [--print] Generate AI context prompt.md with CLI/MCP notes
|
|
152
|
+
ctfx mcp [--out PATH] Generate MCP client config
|
|
153
|
+
|
|
154
|
+
ctfx webui / ctfx web / ctfx ui Open WebUI in browser
|
|
155
|
+
ctfx token update Rotate root token
|
|
156
|
+
|
|
157
|
+
ctfx config show Display current configuration
|
|
158
|
+
ctfx config list Alias for config show
|
|
159
|
+
ctfx config set <key> <value> Set a config value (dot-notation)
|
|
160
|
+
|
|
161
|
+
ctfx serve [--port] [--host] Start WebUI + API + MCP server
|
|
162
|
+
ctfx setup Interactive configuration wizard
|
|
163
|
+
ctfx i Interactive REPL
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Aliases
|
|
167
|
+
| Short | Full |
|
|
168
|
+
|---|---|
|
|
169
|
+
| `ctfx use <comp>` | `ctfx comp use <comp>` |
|
|
170
|
+
| `ctfx init` | `ctfx comp init` |
|
|
171
|
+
| `ctfx add <chal> [cat]` | `ctfx chal add <chal> [cat]` |
|
|
172
|
+
| `ctfx e [path]` | `ctfx explorer [path]` |
|
|
173
|
+
| `ctfx i` | `ctfx interactive` |
|
|
174
|
+
|
|
175
|
+
## Configuration
|
|
176
|
+
|
|
177
|
+
Global config lives at `~/.config/ctfx/config.json`. Run `ctfx setup` to configure interactively, or use `ctfx config set` for individual keys.
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
ctfx config show # view all settings
|
|
181
|
+
ctfx config set serve.port 9000
|
|
182
|
+
ctfx config set terminal.editor_cmd cursor
|
|
183
|
+
ctfx config set terminal.wsl_distro ubuntu
|
|
184
|
+
ctfx config set basedir ~/ctf
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Settable keys: `basedir`, `active_competition`, `serve.host`, `serve.port`, `terminal.cli_cmd`, `terminal.editor_cmd`, `terminal.wsl_distro`, `terminal.python_cmd`, `terminal.explorer_cmd`, `terminal.file_manager_cmd`, `auth.one_time_login_ttl_sec`, `auth.session_ttl_sec`, `auth.webui_cookie_name`
|
|
188
|
+
|
|
189
|
+
Key fields:
|
|
190
|
+
- `basedir` — root directory for all competition workspaces (default: `~/ctf`)
|
|
191
|
+
- `root_token` — auth secret for REST API, MCP, and WebUI; rotate with `ctfx token update` (not settable via `config set`)
|
|
192
|
+
- `serve.port` — default server port (default: `8694`)
|
|
193
|
+
- `terminal.*` — shell, editor, WSL distro, Python command
|
|
194
|
+
|
|
195
|
+
Example Windows Python configuration with spaces in the executable path:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
ctfx config set terminal.python_cmd "\"C:\Program Files\Python313\python.exe\" -u"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Server & Authentication
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
ctfx serve # starts on 127.0.0.1:8694 by default
|
|
205
|
+
ctfx webui # opens browser with auto one-time login
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
API and MCP endpoints require `Authorization: Bearer <root_token>`.
|
|
209
|
+
|
|
210
|
+
The WebUI authenticates through a one-time login URL and then uses a secure session cookie for subsequent browser requests.
|
|
211
|
+
|
|
212
|
+
Changing the active competition through the CLI or API also updates the in-process MCP server state, so MCP tools follow the currently selected competition.
|
|
213
|
+
|
|
214
|
+
MCP client config for Claude Desktop / Cursor:
|
|
215
|
+
```sh
|
|
216
|
+
ctfx mcp --out mcp.json
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The generated MCP URL uses `/mcp/` with a trailing slash.
|
|
220
|
+
|
|
221
|
+
## Workspace Structure
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
~/ctf/
|
|
225
|
+
└── HKCERT_CTF_2025/
|
|
226
|
+
├── ctf.json
|
|
227
|
+
├── prompt.md
|
|
228
|
+
└── pwn/
|
|
229
|
+
└── baby_pwn/
|
|
230
|
+
├── src/
|
|
231
|
+
├── solve/
|
|
232
|
+
│ └── exploit.py
|
|
233
|
+
├── wp.md
|
|
234
|
+
└── chal.md
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## AWD Mode
|
|
238
|
+
|
|
239
|
+
Set `"mode": "awd"` in `ctf.json` to enable AWD commands:
|
|
240
|
+
|
|
241
|
+
```sh
|
|
242
|
+
ctfx awd ssh <service> [--team NAME] SSH into service host
|
|
243
|
+
ctfx awd scp <service> <src> <dst> SCP file transfer
|
|
244
|
+
ctfx awd cmd <service> -- <command> Run remote command
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Security note:
|
|
248
|
+
- AWD SSH now relies on known host keys. Add the target host to your SSH known hosts first, otherwise the connection will be rejected instead of being auto-trusted.
|
|
249
|
+
|
|
250
|
+
## Platform Support
|
|
251
|
+
|
|
252
|
+
| Platform | Fetch | Submit |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| CTFd | yes | yes |
|
|
255
|
+
| rCTF | planned | planned |
|
|
256
|
+
| Manual | via `ctfx add` | no |
|
|
257
|
+
|
|
258
|
+
## Development
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
git clone https://github.com/liyanqwq/CTFx
|
|
262
|
+
cd CTFx
|
|
263
|
+
pip install -e .
|
|
264
|
+
ctfx --help
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Frontend (React + Vite):
|
|
268
|
+
```sh
|
|
269
|
+
cd frontend
|
|
270
|
+
npm install
|
|
271
|
+
npm run dev # dev server
|
|
272
|
+
npm run build # outputs to ctfx/server/static/
|
|
273
|
+
```
|
ctfx-0.2.2/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# CTFx
|
|
2
|
+
|
|
3
|
+
A local-first CTF workspace manager and assistant CLI for Jeopardy and AWD competitions.
|
|
4
|
+
|
|
5
|
+
## Background
|
|
6
|
+
|
|
7
|
+
CTFx started from a bunch of PowerShell scripts I wrote for CTF competitions back in HKCERT 2024.
|
|
8
|
+
|
|
9
|
+
Later, in the HKCERT 2025 Final, I made a Python-based CTF Assistant for AWD matches. It worked pretty well, got some positive feedback, and helped our team achieve a solid result.
|
|
10
|
+
|
|
11
|
+
After that, I decided to turn those ideas and experiences into CTFx, hoping it can give CTF players a bit of extra help in the AI era.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Competition management** — create, list, and switch between CTF workspaces
|
|
16
|
+
- **Challenge scaffolding** — auto-generate category-specific solve templates (`pwn`, `crypto`, `forensics`, `rev`, `misc`)
|
|
17
|
+
- **Platform integration** — fetch challenges and submit flags via CTFd API using either team token or platform cookies
|
|
18
|
+
- **Terminal integration** — open shells, WSL, editors, and file explorers at challenge paths
|
|
19
|
+
- **AI context** — generate `prompt.md` with competition context plus CLI/MCP usage notes for LLM-assisted solving
|
|
20
|
+
- **WebUI** — React dashboard with challenge add/delete, editable challenge detail, flags table, and writeup editor
|
|
21
|
+
- **REST API + MCP** — machine-readable interface for Claude Desktop / Cursor integration
|
|
22
|
+
- **AWD mode** — SSH/SCP helpers, exploit runner, patch tracker, host map
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
Requires Python 3.11+.
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pip install ctfx
|
|
30
|
+
# or with uv (recommended)
|
|
31
|
+
uv tool install CTFx
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Install Guide
|
|
35
|
+
|
|
36
|
+
Install from PyPI:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
pip install ctfx
|
|
40
|
+
ctfx --help
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Upgrade to the latest release:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
pip install -U ctfx
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Install from a local checkout during development:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
git clone https://github.com/liyanqwq/CTFx
|
|
53
|
+
cd CTFx
|
|
54
|
+
pip install -e .
|
|
55
|
+
ctfx --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
# First run — initializes ~/.config/ctfx/config.json
|
|
62
|
+
ctfx setup
|
|
63
|
+
|
|
64
|
+
# Create a competition workspace
|
|
65
|
+
ctfx comp init --name HKCERT_CTF --year 2025 --mode jeopardy --platform ctfd
|
|
66
|
+
|
|
67
|
+
# Switch to it
|
|
68
|
+
ctfx use HKCERT_CTF_2025
|
|
69
|
+
|
|
70
|
+
# Add a challenge
|
|
71
|
+
ctfx add baby_pwn pwn
|
|
72
|
+
|
|
73
|
+
# Open in editor
|
|
74
|
+
ctfx code pwn/baby_pwn
|
|
75
|
+
|
|
76
|
+
# Open a terminal at the solve directory
|
|
77
|
+
ctfx cli pwn/baby_pwn/solve
|
|
78
|
+
|
|
79
|
+
# Start the WebUI + API + MCP server
|
|
80
|
+
ctfx serve
|
|
81
|
+
|
|
82
|
+
# Open WebUI in browser (auto-login)
|
|
83
|
+
ctfx webui
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Typical Flag Workflow
|
|
87
|
+
|
|
88
|
+
`CTFx` now separates local flag recording from remote submission:
|
|
89
|
+
|
|
90
|
+
1. Save a discovered flag locally in the WebUI or via API. This moves the challenge to `hoard`.
|
|
91
|
+
2. Review hoarded flags in the `Flags` page.
|
|
92
|
+
3. Submit the flag to the remote platform when ready.
|
|
93
|
+
4. A successful remote submission promotes the challenge to `solved`.
|
|
94
|
+
|
|
95
|
+
## Notes
|
|
96
|
+
|
|
97
|
+
- Paths passed to `ctfx cli`, `ctfx code`, `ctfx explorer`, API routes, and MCP tools are restricted to the active competition workspace. Escaping with `..` is rejected.
|
|
98
|
+
- Challenge categories, challenge names, and AWD service names are treated as path components and must not contain `/` or `\\`.
|
|
99
|
+
- If `terminal.python_cmd` contains spaces, quote the executable path normally. Example on Windows: `"C:\Program Files\Python313\python.exe" -u`
|
|
100
|
+
- `ctfx webui` generates a one-time login URL for the local WebUI. API and MCP still use the root token unless you are already authenticated in the browser.
|
|
101
|
+
- For platform-backed competitions, set either `team_token` or `team_cookies` in the competition profile before attempting remote submission.
|
|
102
|
+
- Challenge status flow is `fetched -> seen -> working -> hoard -> solved`.
|
|
103
|
+
|
|
104
|
+
## CLI Reference
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
ctfx comp list [query] List competitions
|
|
108
|
+
ctfx comp use <name> Set active competition
|
|
109
|
+
ctfx comp init Create new competition workspace
|
|
110
|
+
ctfx comp info Show active competition metadata
|
|
111
|
+
|
|
112
|
+
ctfx chal list [query] [--cat] [--status] List challenges
|
|
113
|
+
ctfx chal add <name> [cat] Add and scaffold a challenge
|
|
114
|
+
ctfx chal rm <name> Remove a challenge
|
|
115
|
+
ctfx chal info <name> Show challenge detail
|
|
116
|
+
ctfx chal status <name> <status> Update challenge status
|
|
117
|
+
|
|
118
|
+
ctfx cli [path] Open terminal at path
|
|
119
|
+
ctfx wsl [path] [-- cmd] Open WSL shell or run command
|
|
120
|
+
ctfx e [path] Open file explorer
|
|
121
|
+
ctfx code [path] Open editor
|
|
122
|
+
ctfx py [file] Run Python in configured environment
|
|
123
|
+
|
|
124
|
+
ctfx fetch [--cat] [--chal] Fetch challenges from platform
|
|
125
|
+
ctfx submit <flag> [--chal] Submit flag to platform
|
|
126
|
+
ctfx import <url> LLM-assisted challenge import
|
|
127
|
+
|
|
128
|
+
ctfx ai [--print] Generate AI context prompt.md with CLI/MCP notes
|
|
129
|
+
ctfx mcp [--out PATH] Generate MCP client config
|
|
130
|
+
|
|
131
|
+
ctfx webui / ctfx web / ctfx ui Open WebUI in browser
|
|
132
|
+
ctfx token update Rotate root token
|
|
133
|
+
|
|
134
|
+
ctfx config show Display current configuration
|
|
135
|
+
ctfx config list Alias for config show
|
|
136
|
+
ctfx config set <key> <value> Set a config value (dot-notation)
|
|
137
|
+
|
|
138
|
+
ctfx serve [--port] [--host] Start WebUI + API + MCP server
|
|
139
|
+
ctfx setup Interactive configuration wizard
|
|
140
|
+
ctfx i Interactive REPL
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Aliases
|
|
144
|
+
| Short | Full |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `ctfx use <comp>` | `ctfx comp use <comp>` |
|
|
147
|
+
| `ctfx init` | `ctfx comp init` |
|
|
148
|
+
| `ctfx add <chal> [cat]` | `ctfx chal add <chal> [cat]` |
|
|
149
|
+
| `ctfx e [path]` | `ctfx explorer [path]` |
|
|
150
|
+
| `ctfx i` | `ctfx interactive` |
|
|
151
|
+
|
|
152
|
+
## Configuration
|
|
153
|
+
|
|
154
|
+
Global config lives at `~/.config/ctfx/config.json`. Run `ctfx setup` to configure interactively, or use `ctfx config set` for individual keys.
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
ctfx config show # view all settings
|
|
158
|
+
ctfx config set serve.port 9000
|
|
159
|
+
ctfx config set terminal.editor_cmd cursor
|
|
160
|
+
ctfx config set terminal.wsl_distro ubuntu
|
|
161
|
+
ctfx config set basedir ~/ctf
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Settable keys: `basedir`, `active_competition`, `serve.host`, `serve.port`, `terminal.cli_cmd`, `terminal.editor_cmd`, `terminal.wsl_distro`, `terminal.python_cmd`, `terminal.explorer_cmd`, `terminal.file_manager_cmd`, `auth.one_time_login_ttl_sec`, `auth.session_ttl_sec`, `auth.webui_cookie_name`
|
|
165
|
+
|
|
166
|
+
Key fields:
|
|
167
|
+
- `basedir` — root directory for all competition workspaces (default: `~/ctf`)
|
|
168
|
+
- `root_token` — auth secret for REST API, MCP, and WebUI; rotate with `ctfx token update` (not settable via `config set`)
|
|
169
|
+
- `serve.port` — default server port (default: `8694`)
|
|
170
|
+
- `terminal.*` — shell, editor, WSL distro, Python command
|
|
171
|
+
|
|
172
|
+
Example Windows Python configuration with spaces in the executable path:
|
|
173
|
+
|
|
174
|
+
```sh
|
|
175
|
+
ctfx config set terminal.python_cmd "\"C:\Program Files\Python313\python.exe\" -u"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Server & Authentication
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
ctfx serve # starts on 127.0.0.1:8694 by default
|
|
182
|
+
ctfx webui # opens browser with auto one-time login
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
API and MCP endpoints require `Authorization: Bearer <root_token>`.
|
|
186
|
+
|
|
187
|
+
The WebUI authenticates through a one-time login URL and then uses a secure session cookie for subsequent browser requests.
|
|
188
|
+
|
|
189
|
+
Changing the active competition through the CLI or API also updates the in-process MCP server state, so MCP tools follow the currently selected competition.
|
|
190
|
+
|
|
191
|
+
MCP client config for Claude Desktop / Cursor:
|
|
192
|
+
```sh
|
|
193
|
+
ctfx mcp --out mcp.json
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The generated MCP URL uses `/mcp/` with a trailing slash.
|
|
197
|
+
|
|
198
|
+
## Workspace Structure
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
~/ctf/
|
|
202
|
+
└── HKCERT_CTF_2025/
|
|
203
|
+
├── ctf.json
|
|
204
|
+
├── prompt.md
|
|
205
|
+
└── pwn/
|
|
206
|
+
└── baby_pwn/
|
|
207
|
+
├── src/
|
|
208
|
+
├── solve/
|
|
209
|
+
│ └── exploit.py
|
|
210
|
+
├── wp.md
|
|
211
|
+
└── chal.md
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## AWD Mode
|
|
215
|
+
|
|
216
|
+
Set `"mode": "awd"` in `ctf.json` to enable AWD commands:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
ctfx awd ssh <service> [--team NAME] SSH into service host
|
|
220
|
+
ctfx awd scp <service> <src> <dst> SCP file transfer
|
|
221
|
+
ctfx awd cmd <service> -- <command> Run remote command
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Security note:
|
|
225
|
+
- AWD SSH now relies on known host keys. Add the target host to your SSH known hosts first, otherwise the connection will be rejected instead of being auto-trusted.
|
|
226
|
+
|
|
227
|
+
## Platform Support
|
|
228
|
+
|
|
229
|
+
| Platform | Fetch | Submit |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| CTFd | yes | yes |
|
|
232
|
+
| rCTF | planned | planned |
|
|
233
|
+
| Manual | via `ctfx add` | no |
|
|
234
|
+
|
|
235
|
+
## Development
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
git clone https://github.com/liyanqwq/CTFx
|
|
239
|
+
cd CTFx
|
|
240
|
+
pip install -e .
|
|
241
|
+
ctfx --help
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Frontend (React + Vite):
|
|
245
|
+
```sh
|
|
246
|
+
cd frontend
|
|
247
|
+
npm install
|
|
248
|
+
npm run dev # dev server
|
|
249
|
+
npm run build # outputs to ctfx/server/static/
|
|
250
|
+
```
|