こんにちは!
社内技術横断支援組織「Backbeat」の山田のてっちゃんです!
picoCTF 2026 に、今回も LLM を使って挑戦してきました。
結果は 70問中69問正答。かなり戦えた一方で、最後の1問 Paper-2 に 7日近く張り付いて敗北 し、しっかり悔しい思いもしました。。。
今回は序盤に Sonnet 4.6 の多重並列、中盤以降は Opus 4.6 の単騎運用 に切り替えたところ、かなりパフォーマンス差を感じました。
ただし、最後まで残った超高難度問題では、「強い思考法を与える」だけでは届かない壁 も見えました。
まだまだ改善点はありますが、どのように運用し、どこで詰まり、何を直したかをご紹介します。
AIエージェントの長時間タスク運用に転用できそうなTips もあると思うので、ぜひ読んでいってください!
本記事は「Paper-2 の解法」ではなく、picoCTF を LLM / AIエージェントで走らせたときの運用設計・限界・改善 にフォーカスします。
Paper-2の解法発想そのものを LLM にどう獲得させるかは、次回記事で扱う予定です。
この記事でわかること
- picoCTF 2026 での Sonnet 4.6 多重並列 と Opus 4.6 単騎 の運用方針
- 長時間タスクで AI エージェントが陥った 未検証仮説の固定化 と、その抑止策のアイディア
- Solve.log 運用 と Solver / Analyzer 分離 で、行動改善を狙った設計
作ったもの(方針と制約)
今回やりたかったのは、シンプルにいうと 「LLM は CTF でどこまで戦えるのか」 の継続観測です。
前回大会から引き続き取り組んでおり、もはや自分の中では LLM × CTF がライフワーク化しつつある テーマです。
前回大会では、CLAUDE.md に 問題ジャンルごとの具体的な解法方針 を「例えば」という形で入れていました。
すると、それがヒントになるどころか、その方針に固執して探索の幅が狭まる ケースが目立ちました。
そこで今回は、前回の反省を踏まえて次のように設計しました。
- 方針1:具体的な解法手順は入れない
- 方針2:代わりに 強いCTFプレイヤーの思考方法 だけを注入する
- 方針3:モデルの素の探索力をできるだけ観察する
つまり、「このジャンルならこう解け」とは教えず、
「どう考えるべきか」だけ渡して、どこまで行けるか を見にいった形です。
ただし大会期間は 10日間、問題数は 70問。
しかも平日進行だったので、常時べったり張り付く運用はできませんでした。
そのため、序盤はスループット重視で並列、中盤以降は精度重視で単騎、という切り替えを行いました。
小話ですが、出先から状況を見るために Claude Code の Remote Control も試しました。
Research Preview として 2026年2月ごろから案内されている機能で、ローカルで動いている Claude Code のセッションをスマホやブラウザから引き継げる、というものです1。 (引用は第三者記事なのでご参考まで)
自分の環境では Windows ノートPC上の VirtualBox 上で Kali Linux を動かし、その中で Claude Code を稼働 させていました。VirtualBox の NIC をデフォルトの NAT のままにしていたときは Remote Control の確立に失敗し、ブリッジにすると確立自体は通ったのですが、最終的にはスマホアプリ側で接続エラーになってしまい、実戦投入には至りませんでした。
ノートPCの画面オフやロック状態が影響した可能性もあり、ここは今後の再検証ポイントです。
最終的な構成イメージ
ctf-agent-run/
├── CLAUDE.md # 思考法のみを記述。具体的な解法方針は入れない
├── prompts/
│ ├── main-agent.md # メインエージェント用プロンプト
│ ├── solver.md # 問題分析・検証担当
│ └── analyzer.md # 次アクション決定担当
├── logs/
│ └── Solve.log # 検証済み事実のみを蓄積
├── work/
│ ├── challenge-files/ # 配布ファイル、Dockerfile、補助スクリプトなど
│ └── scratch/ # 仮説検証用の作業領域
└── README.md
- メイン:CTF問題を解かせるエージェント実行環境
-
サブ:
Solve.logによる事実蓄積 -
補助:
Solver / Analyzerの役割分離
厳密には大会期間中ずっと同一構成だったわけではなく、
最後の Paper-2 でハマった結果、プロンプトと役割設計を途中で改修していったイメージです。
序盤:Sonnet 4.6 を10並列で回した
序盤は Sonnet 4.6 を約10並列 で回し、役割分担はせずに1エージェント1問題 というシンプルな構成を取りました。
平日開催だったので、朝にエージェントを仕掛けて、帰宅後に結果を見る、という運用が基本です。
この運用自体は「問題数をさばく」という意味では相性が悪くなかったです。
ただ、丸1日走らせても答えに辿り着かない問題が目立ってきました。
前回の反省から 具体的な解法方針は入れていない ので、以前のような「テンプレ解法への固執」は減った感触がありましたが、今度は逆に 探索の収束力が足りない 場面もありました。
ここで感じたのは、単に「思考法を与えれば自由に強く探索できる」というほど簡単ではない、ということです。
自由度が上がると、そのぶん 良い探索にも悪い探索にも振れやすい。
中盤:Opus 4.6 単騎に切り替えたら明らかに改善した
中盤からは Opus 4.6 の単騎運用 に切り替えました。
クオータ制限の都合もあり、多重並列ではなく 一体をじっくり動かす 形です。
結論からいうと、ここはかなり良かったです。
- Sonnet で止まっていた問題が解けた
- 体感として、次の有効アクションに進むまでの速度も上がった
- 思考法だけを注入する方針との相性も、Sonnet より良く見えた
現時点では実機ログを見ながら具体例を補いたいので、問題別の詳細比較は後で差し替える前提ですが、少なくとも大会全体の運用感としては、
「並列数で押すより、強いモデルに深く考えさせたほうが良い」
という手応えがありました。
もちろん、これは picoCTF 2026 の問題傾向や、自分の与えたプロンプト設計にも依存します。
ただ、少なくとも今回の条件では、Sonnet 10並列より Opus 単騎のほうが総合的に強かった と感じています。
それでも最後の1問 Paper-2 は解けなかった
とはいえ、最後まで残った Paper-2 は別格でした。
これは picoCTF 2026 の中でもかなり高難度な Web 問題で、公開されている Writeup を見ると、CSS セレクタ・Redis の LRU eviction・サイドチャネル・候補復元 を組み合わせる発想が必要だったことが分かります2。
自分のエージェントは、この問題に対して 24時間以上の長考 に入ったあたりから、だんだん怪しい挙動を見せるようになりました。
観測できた不適切行動
Paper-2 では、問題コンテナが Dockerfile として提供されており、
ローカルで起動して、思いついた攻撃が本当に成立するかを検証しながら進める のが本来あるべき進め方でした。
ところが、長時間回していると次のような振る舞いが見られました。
1. 未検証仮説を「事実」として扱い始める
例えば、
- コンテナログを十分に確認していないのに、「このリクエストは通った」と確信している
- ある仮説が一度テキスト上で出たあと、未検証のまま前提条件に昇格している
といった挙動です。
これは人間でもハマる罠ですが、エージェント化すると
「自分の過去出力」を強い根拠として再利用してしまう ので、思った以上に厄介でした。
ちなみに、検証が不十分な仮説も「核心的な発見です!」と言って嬉しそうに持ってくるので憎めません。かわいいやつめ、と思って受け止めます。
2. 失敗理由を憶測で固定する
例えば、
- 実際には十分に確認していないのに、「うまくいかなかったのはコンテナが起動していないからだ」 と決めつける
といったケースです。
本来やるべきなのは、
- コンテナ起動状態の確認
- リクエスト送出の成否確認
- サーバログ・レスポンス差分確認
- その上で原因仮説を立てる
の順番です。
しかし長考モードに入ると、この順番が崩れ、検証より先に物語ができてしまう。
3. 問題そのものの Writeup 探索に寄り始める
これは実務タスクでも似た現象がありそうですが、
苦しくなると 「同じ問題を誰かがもう解いていないか」 方向に寄っていく挙動も見られました。
もちろん、情報収集自体は悪ではありません。
ただ今回は 大会中の未知問題を、自分のエージェントの探索でどこまで解けるか を見たかったので、これは狙いから外れています。
なぜこうなったのか
長時間タスクでの AI エージェントは、近年の研究でも 長い履歴・記憶圧縮・多ターン継続 の中で不安定さを抱えやすいことを指摘しているものがあるようです。
例えば METR の長時間タスク評価では、AI がこなせるタスク長は伸びている一方で、そもそも 長い手順をミスなく完遂すること自体が難しい という前提が見えます3。
また、LLM ベースのエージェントにおける hallucination を整理したサーベイでも、長期タスクにおける情報圧縮や誤った情報伝播 は重要な論点として扱われています4。
今回の自分の観測でいうと、派手な幻覚というよりはむしろ、
- 仮説と事実の境界がにじむ
- 過去出力が「検証済みっぽいもの」として再注入される
- 行動の正当化が先に立つ
という、エージェント運用ならではの崩れ方 でした。
その他の工夫:Solve.log と役割分離で暴走を抑える
この挙動を見て、最後にプロンプトをかなり改修しました。
やったことはシンプルで、主に2つです。
- 検証された事実だけを
Solve.logに積む - メインエージェント自身には考えさせず、Solver / Analyzer の2役を起動するだけ にする
Solve.log 運用
まず、未検証仮説が既成事実化していくのを抑えるために、
「ログに書いてよいのは検証された事実だけ」 と明示しました。
イメージとしてはこんな感じです。
Solve.log の運用イメージ
- [FACT] Docker コンテナは起動済み。`docker ps` で対象コンテナの稼働を確認した。
- [FACT] `/secret` への GET で 200 が返ることを確認した。
- [FACT] 特定の payload を付けたリクエストでは、期待したログ出力は観測できなかった。
- [HYPOTHESIS] CSS セレクタを使った条件付き取得が成立している可能性がある。
- [TODO] Redis 側の eviction 条件を再確認する。
ポイントは、仮説と事実を混ぜない ことです。
当たり前に見えるのですが、長考で壊れ始めたエージェントにはこれがかなり効きます。
Solver / Analyzer 分離
次に、メインエージェントを「全部やる司令塔」にしないようにしました。
- Solver エージェント:問題分析と検証を行う
- Analyzer エージェント:Solver の検証結果だけを見て、次アクションを決める
- メインエージェント:上記2役をキックするだけ
構造としてはこんなイメージです。
この形にした狙いは、思考と検証と進行管理を1つの文脈に押し込まない ことです。
もし全部を1体でやらせると、
- 自分で仮説を立てる
- 自分で検証したことにする
- 自分で次の方針を正当化する
が一続きになり、誤りが閉じたループで増幅しやすい。
そこで、最低限でも 「手を動かす役」と「証拠を読んで次を決める役」 を分けました。
この発想自体は、過去の Reflexion 系の研究にも通じるところがあります。
言語的なフィードバックや反省を通じて次の行動を改善する、という方向性自体は有効ですが5、実戦では 反省文を増やすだけでは足りず、何を事実として残すかの運用設計が重要 だと感じました。
振り返り
今回の戦略は、かなりハマった部分と、はっきり限界が見えた部分が両方ありました。
69/70問 まで来られたのは素直に良かったですし、Opus 4.6 の強さもかなり感じられました。
一方で、最後の Paper-2 を落としたことで、思考法の注入だけでは届かない領域 も明確になりました。
うまくいったところ
- 前回大会の反省を踏まえ、具体的な解法方針を外した のは良かった
- Opus 4.6 単騎 は、今回の条件ではかなり強かった
- 長考での不適切行動を観測し、運用改善ポイントを具体化 できた
課題
課題①:思考法だけでは突破できない問題があった
原因:
「どう考えるか」を教えるだけでは、Paper-2 のような 発想ジャンプが必要な問題 に届かなかった可能性があります。
公開されている Writeup を見ると、CSS attribute selector、Redis の allkeys-lru、大量マーカー、LLR、beam search など、かなり特殊な発想の接続が必要でした2。
改善案:
次回は Writeup を逆算材料として使い、どの時点でどの発想が必要だったのか を分解した上で、
その発想に近づくようにエージェントの行動を設計し直したいです。
課題②:長考時に未検証仮説へ固着した
原因:
検証ログと仮説ログが頭の中で混線し、過去出力が擬似的な「事実」として再利用されたためです。
長い履歴の中で、モデルが何を根拠にしているのかが曖昧になっていきました。
改善案:
Solve.log の厳格運用を前提にし、
「事実」「仮説」「未確認」「次アクション」 を明示的に分離する。
必要なら、仮説を採用する前に必ず 再検証ステップ を踏ませます。
課題③:1エージェントに責務を持たせすぎた
原因:
分析、検証、進行管理、反省を1つの文脈に集約すると、誤りが自己正当化されやすいです。
改善案:
今回試した Solver / Analyzer 分離 をもっと早い段階から適用する。
必要ならさらに、環境観測専任・ログ監査専任などに分けてもよいかもしれません。
今回いちばん大きな学びは、「モデルを賢くする」より前に、「間違い方を閉じ込める設計」が必要 だという点でした。
まとめ
| 観点 | 今回 | 次回改善 |
|---|---|---|
| ベースモデル | Opus 4.6 がかなり強かった | 問題タイプ別にモデル選択を再整理 |
| プロンプト設計 | 解法方針は入れず、思考法のみ注入 | 発想ジャンプを支える中間表現を設計 |
| 長考時の安定性 | 未検証仮説の固定化が発生 |
Solve.log 厳格運用、再検証ステップ追加 |
| 役割設計 | 後半で Solver / Analyzer 分離 | もっと早い段階から責務分離 |
| 最難問対応 |
Paper-2 は未突破 |
Writeup を逆算し、必要発想を注入できるか検証 |
picoCTF 2026 を通して、LLM はかなり強い。けれど、まだ「強い思考法を渡すだけ」では届かない問題がある、というのが今回の結論でした。
そして自分が次にやりたいのは、まさにその先です。
公開されている Paper-2 の Writeup を読み、あの発想に至るにはエージェントの何を変えるべきか? を逆算してみたいと思っています。
次回は、Writeup をもとに AI エージェントの振る舞いを再設計し、答えに辿り着けるか を検証する記事を書く予定です。
解けなかったからこそ、次に進める材料が手に入った大会でした。
参考リンク
- picoCTF 2026
Paper-2Writeup by Vipin:
https://www.vipin.xyz/blog/picoctf2026
-
Claude Code Remote Control に関する解説例。Research Preview として、ローカルで動く Claude Code セッションを外部デバイスから引き継ぐ形で利用できる旨が紹介されています。
- Serverworks の紹介記事: https://blog.serverworks.co.jp/2026/03/01/170000
- 解説記事: https://www.ai-souken.com/article/what-is-claude-code-remote-control
-
Paper-2の詳細な Writeup。CSS attribute selector による条件付き取得、Redis のallkeys-lruを使ったサイドチャネル化、control calibration、LLR、beam search まで含めて詳しく説明されています。
https://www.vipin.xyz/blog/picoctf2026 ↩ ↩2 -
METR による長時間タスク評価。AI が完了できるタスク長の指標として time horizon を扱い、近年の伸びを報告しています。
- arXiv: Measuring AI Ability to Complete Long Software Tasks
- HTML: https://arxiv.org/html/2503.14499v3
-
LLM ベースのエージェントにおける hallucination のサーベイ。長期タスクや multi-agent 文脈での情報圧縮・誤伝播なども扱っています。
↩ -
言語的フィードバックを通じて次試行を改善する Reflexion。
↩