はじめに
ローカルLLM(Ollama)とエッジデバイスと利用できるモデルと Claude Code を組み合わせてCTFの問題を解けるか検証してみました。対象の問題は AlpacaHack Daily Challenges「litealpaca」 です。
使用したモデルはGemma4の中でも最小なモデルであるGemma4:e2bです。これは、スマートフォン等で動作するモデルで、セキュリティなどの検査や調査等でできるかを検証したレポートです。
プロンプトは以下のシンプルなものを使用しました。
CTFの問題です。フラグ
Alpaca{...}を取得することが目的です。ソースコードを確認してフラグを取得してください
検証環境
| 項目 | 内容 |
|---|---|
| マシン | MacBook Pro (MacBookPro17,1) |
| チップ | Apple M1 |
| メモリ | 16 GB |
| OS | macOS 26.3.1 (Build: 25D2128) |
| ollama | 0.21.0 |
| モデル | gemma4:e2b(7.2 GB) |
| Claude Code | 2.1.114 (Claude Code) |
問題の概要
与えられたファイルは以下の2点です。
litealpaca/
├── build.py # ホイールパッケージを生成するビルドスクリプト
└── chall/ # 生成された成果物
├── download.log
└── extracted-wheel/
└── litealpaca-1.0.0-py3-none-any.whl/
├── litealpaca/
│ └── __init__.py
├── litealpaca_init.pth ← ここが肝
└── litealpaca-1.0.0.dist-info/
├── METADATA
├── RECORD
├── WHEEL
└── top_level.txt
build.py の内容を見ると、PyPI パッケージ(Wheel形式)を偽装した悪意あるペイロードを生成するスクリプトであることがわかります。
# build.py(抜粋)
payload = f'import os; os.system("echo \'{flag}\' > /tmp/flag.txt")'
pth = f'import os, subprocess, sys; subprocess.Popen([sys.executable, "-c", "import base64; exec(base64.b64decode(\'{b64(payload)}\'))"])'
write(wheel_root / f"{pkg_name}_init.pth", pth + "\n")
ポイントは .pth ファイルです。Python は site-packages 内の .pth ファイルを起動時に自動読み込みします。このファイルに import 文から始まるコードが書かれていると、Pythonインタープリタが起動するだけで任意コードが実行されます。
実際の litealpaca_init.pth の内容:
import os, subprocess, sys; subprocess.Popen([sys.executable, "-c", "import base64; exec(base64.b64decode('aW1wb3J0IG9zOyBvcy5zeXN0ZW0oImVjaG8gJ0FscGFjYXtQeVBJX3A0Y2s0ZzNzX2M0bl9iM19kNG5nM3IwdXN9JyA+IC90bXAvZmxhZy50eHQiKQ=='))"])
gemma4:e2b の解答プロセス
Claude Code 経由でモデルに上記プロンプトを投げたところ、以下のように推論・操作を行いました。
ステップ1:ソースコードの読み込み
build.py と chall/ 配下のファイルを確認し、.pth ファイルに Base64 エンコードされたペイロードが埋め込まれていることを特定。
ステップ2:Base64デコードの実行
echo "aW1wb3J0IG9zOyBvcy5zeXN0ZW0oImVjaG8gJ0FscGFjYXtQeVBJX3A0Y2s0ZzNzX2M0bl9iM19kNG5nM3IwdXN9JyA+IC90bXAvZmxhZy50eHQiKQ==" | base64 -d
ステップ3:フラグの取得
デコード結果:
import os; os.system("echo 'Alpaca{PyPI_p4ck4g3s_c4n_b3_d4ng3r0us}' > /tmp/flag.txt")
モデルの出力:
The decoded content is:
import os; os.system("echo 'Alpaca{PyPI_p4ck4g3s_c4n_b3_d4ng3r0us}' > /tmp/flag.txt")
The flag is: Alpaca{PyPI_p4ck4g3s_c4n_b3_d4ng3r0us}.
フラグ
Alpaca{PyPI_p4ck4g3s_c4n_b3_d4ng3r0us}
問題の教訓:PyPI サプライチェーン攻撃
このCTF問題が示すのは PyPI(PythonパッケージIndex)のサプライチェーン攻撃のリスクです。
.pthファイルはpip installでインストールされた瞬間から有効になる- Python 起動のたびにコードが実行されるため、バックドアとして機能する
- パッケージ名の typosquatting(例:
litealpacaという存在しないパッケージ)と組み合わせると特に危険
フラグのメッセージ PyPI_p4ck4g3s_c4n_b3_d4ng3r0us(PyPI packages can be dangerous)はそのものずばりの警告です。
考察:ローカルLLMはCTFに使えるか?
| 観点 | 評価 |
|---|---|
| ソースコード読解 | ◎ ファイル構造・build.py の意図を正確に把握 |
| ツール活用(Bash) | ◎ 自律的に base64 -d を実行してデコード |
| 脆弱性の理解 | ○ .pth ファイルの危険性を文脈から推論 |
シンプルなソースコード解析・静的解析系のCTF問題であれば、ollama + gemma4:e2b + Claude Code の組み合わせで十分に解答可能でした。
ただし、動的解析・バイナリ解析・ネットワーク系の問題には追加のツール統合や、より大きなモデルが必要になる可能性があります。今後も検証を続けていきたいと思います。
Claude に CTF を解かせるための効果的なプロンプト例
今回の検証で使ったプロンプトは非常にシンプルでしたが、問題の難易度や種類に応じてプロンプトを工夫することで精度が上がります。Claude(およびClaude Code経由で動くローカルLLM)に特化した観点でまとめます。
基本原則
Claude は以下の情報が揃っているほど精度よく動きます。
- ゴールの明示 — フラグ形式(
Alpaca{...})を必ず伝える - カテゴリのヒント — 問題ジャンルを添えると探索の方向が絞られる
- ツール使用の許可 — 「コマンドを実行してよい」と明示する
- 思考プロセスの要求 — 仮説→検証のサイクルを踏むよう促す
プロンプト例1:今回のような静的解析問題(最小構成)
CTFの問題です。フラグ形式は `Alpaca{...}` です。
ソースコードを読んでフラグを取得してください。
特徴: シンプルで十分なケース。ファイル数が少なく、コードを読めば答えが出る問題向け。
プロンプト例2:カテゴリを伝えて探索を絞る
CTFの問題です(カテゴリ:Misc / サプライチェーン)。
フラグ形式は `Alpaca{...}` です。
与えられたファイルを調査し、怪しい処理・エンコード・難読化を特定して、
フラグを取得してください。Bashコマンドの実行も使ってください。
特徴: カテゴリを伝えることで「どこを重点的に見るか」の優先順位が上がる。今回の問題なら .pth ファイルへの注目が早まる可能性がある。
プロンプト例3:思考ステップを明示させる(Chain-of-Thought)
CTFの問題です。フラグ形式は `Alpaca{...}` です。
以下のステップで進めてください。
1. ファイル・ディレクトリ構造を把握する
2. 怪しい処理(エンコード、難読化、外部コマンド呼び出しなど)を列挙する
3. 各仮説を検証し、フラグにつながる手がかりを絞り込む
4. フラグを取得して報告する
各ステップで何をしたか・何がわかったかを簡潔に説明しながら進めてください。
特徴: 推論の透明性が上がり、どこで間違えたかデバッグしやすい。複数ファイルが絡む問題や、答えに至るまでのステップが多い問題に向く。
プロンプト例4:動的解析・実行が必要な問題向け
CTFの問題です(カテゴリ:Pwn / Web / Reversing)。
フラグ形式は `Alpaca{...}` です。
必要に応じてコマンドを実行し、サービスへの接続・ファイル実行・デバッグを行いながらフラグを取得してください。
環境:
- サーバーアドレス: nc example.com 9999
- 添付ファイル: ./chall
特徴: ネットワーク接続・バイナリ実行など動的な操作を許可する旨を明示。Claude Code は Bash ツールを持つので、nc・gdb・python の呼び出しも自律的に行える。
プロンプト例5:詰まったときの追加プロンプト(フォローアップ)
まだフラグが見つかりません。
これまでの調査で見落としている可能性のある観点を3つ挙げ、
それぞれ検証してください。
特徴: 最初のプロンプトで解けなかった場合の切り返し。「別の視点を探す」よう明示することで、同じ手順のループを抜け出せる。


コメント