mcpField
C
ctf-rev

ctf-rev

github.com/cyberkaidaセキュリティ885323 回インストール2 日前に更新
リポジトリ

ctf-rev について

ctf-revは、コンパイル済みプログラムを対象とするCTFリバースエンジニアリング用スキルです。入力と検証処理の追跡、パターン認識、静的・動的・複合分析の選択を通じて、フラグやキーの特定を支援します。

主な機能

  1. 01静的・動的分析の手順
  2. 02入力から検証までのデータフロー追跡
  3. 03アルゴリズムとパターンの認識
  4. 04制約の求解と解の検証

活用シーン

  1. 01バイナリの入力検査を追ってフラグを探す
  2. 02難読化コードに適した分析方法の選択
  3. 03制約で表されたキー検査の求解

MCP 対応

ReVaのMCPツールを使ったプログラムの確認、逆コンパイル、クロスリファレンス分析、調査結果の記録方法を説明します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cyberkaida/reverse-engineering-assistant --skill ctf-rev

インストール後、Claude Code で/ctf-revを入力して読み込まれたか確認します。

同梱ファイルpatterns.md

詳細

CTF リバースエンジニアリング

目的

あなたは CTF のリバースエンジニアリングを解く人です。目標は、体系的な分析を通じて プログラムの動作を理解し、フラグ/キー/パスワードを抽出することです。

CTF のリバースエンジニアリングの本質は、制約下での理解です。

  • 限られた時間(競技のプレッシャー)
  • 問題の構造が不明(どの手法が問われているのか?)
  • 最小限のドキュメント(それこそが課題です!)
  • 目標重視(完璧な理解ではなく、フラグを見つけること)

マルウェア分析や脆弱性調査とは異なり、CTF のリバースエンジニアリングでは、次の能力が試されます。

  1. 課題の核心をすばやく特定する(暗号?難読化?アルゴリズムの復元?)
  2. 重要なデータフローを追跡する(入力はどこへ進むのか?どのように検証されるのか?)
  3. パターンを認識する(標準的なアルゴリズム、よくあるトリック)
  4. アプローチを適応させる(静的か動的か、トップダウンかボトムアップか)

概念的なフレームワーク

3 つの問い

リバースエンジニアリングの課題はすべて、次の問いに答えることに集約されます。

1. プログラムは何を期待しているのか?

  • 入力形式(文字列、数値、バイナリデータ?)
  • 入力構造(長さ、形式、エンコーディング?)
  • 検証条件(チェック、比較、制約?)

2. プログラムは何をするのか?

  • 変換(暗号化、ハッシュ化、エンコード、計算?)
  • 比較(ハードコードされた値、導出された値との比較?)
  • アルゴリズム(標準的な暗号、独自のロジック、数学的処理?)

3. どうすれば逆算できるのか?

  • 処理は可逆か?(暗号化かハッシュ化か)
  • ブルートフォースできるか?(キー空間のサイズ、性能)
  • 答えを導き出せるか?(方程式を解く、逆方向に追跡する)
  • 回避できるか?(パッチ適用、デバッグ、状態の操作)
理解することと解くこと

すべてを理解する必要はありません。フラグの取得につながる部分に集中しましょう。

完全な理解(多くの場合、不要です):

  • すべての関数の目的
  • プログラム全体のフロー
  • すべての境界ケースとエラー処理
  • ライブラリの実装詳細

必要十分な理解(必要なのはこれです):

  • エントリーポイントからフラグ検証まで
  • 中核となる変換ロジック
  • 入力と出力の関係
  • 比較方法または成功条件

例:

Program has 50 functions. You identify:
- main() calls validate_key()
- validate_key() calls transform_input() then compare_result()
- transform_input() does AES encryption
- compare_result() checks against hardcoded bytes

Sufficient understanding: "Input is AES-encrypted and compared to constant"
You don't need to reverse the other 45 functions!

中核となる手法

静的解析:コードの理解

目標: 逆コンパイル/逆アセンブルされたコードを読んで、プログラムのロジックを理解する

使用する場面:

  • 小規模で目的が絞られたプログラム(クラックミー、キージェネレーター)
  • アルゴリズムの特定が課題となる場合
  • 動的解析が妨げられる場合(アンチデバッグ、複雑な状態)
  • 変換ロジックを理解する必要がある場合

アプローチ:

  1. 重要な経路を見つける - エントリーポイント → フラグ検証 → 成功
  2. 入力の流れを追跡する - ユーザー入力はどこへ進むのか?どのように使用されるのか?
  3. 処理を特定する - どのような変換が行われるのか?(XOR、ループ、比較)
  4. パターンを認識する - 既知のアルゴリズムに一致するか?(patterns.md を参照)

ReVa のワークフロー:

1. get-decompilation of entry/main function
   - includeIncomingReferences=true to see program structure

2. Follow input handling
   - find-cross-references to input functions (scanf, read, etc.)
   - Trace data flow from input to validation

3. Analyze transformations
   - rename-variables to clarify data flow
   - change-variable-datatypes to understand operations
   - set-decompilation-comment to document logic

4. Identify success criteria
   - Find comparison or validation logic
   - Extract expected values or patterns
動的解析:実行時の観察

目標: プログラムの実行中の動作を観察する

使用する場面:

  • 制御フローが複雑な場合(静的解析では追いにくい)
  • コードが難読化またはパッキングされている場合
  • 中間値を確認する必要がある場合
  • 時間依存または環境依存のチェックがある場合

アプローチ:

  1. 重要な箇所にブレークポイントを設定する

    • 入力処理
    • 変換処理
    • 比較処理
    • 成功/失敗の分岐
  2. 状態の変化を観察する

    • レジスター/変数の値
    • メモリの内容
    • 関数の引数/戻り値
  3. 仮説を検証する

    • 「X を入力すると、Y が起きるか?」
    • 「ここではどの値が比較されているのか?」

注: ReVa は静的解析に重点を置いています。動的解析には、外部デバッガー(gdb、x64dbg など)を使用してください。

ハイブリッドアプローチ:両方の利点を活用する

CTF の課題で最も効果的です

ワークフロー:

  1. 静的解析:構造を特定する(検証関数と成功経路を見つける)
  2. 動的解析:実行時の動作を観察する(検証箇所にブレークポイントを設定し、期待値を確認する)
  3. 静的解析:変換処理を理解する(アルゴリズムを逆算する)
  4. 動的解析:解答を検証する(導き出したキー/フラグを試す)

例:

Static: "Input is transformed by function sub_401234 then compared"
Dynamic: Run with test input, breakpoint at comparison → see expected value
Static: Decompile sub_401234 → recognize as base64 encoding
Solve: base64_decode(expected_value) = flag
Dynamic: Verify flag works

問題解決の戦略

戦略 1:トップダウン(目標指向)

成功条件から始め、逆方向にたどります

使用する場面:

  • 成功/失敗の指標が明確(「Correct!」または「Wrong!」と表示される)
  • プログラムの構造が単純
  • 必要最小限の理解を目指す場合

ワークフロー:

1. Find success message/function
2. find-cross-references direction="to" → What calls this?
3. get-decompilation of validation function
4. Identify what conditions lead to success
5. Work backwards to understand required input

例:

1. String "Congratulations!" at 0x402000
2. Referenced by function validate_flag at 0x401500
3. Decompile validate_flag:
   if (transformed_input == expected_value) print("Congratulations!");
4. Now focus on: What's expected_value? How is input transformed?
戦略 2:ボトムアップ(データフロー)

入力から始め、検証まで順方向にたどります

使用する場面:

  • プログラムの構造が複雑(関数が多数ある)
  • 成功条件が不明確
  • 変換処理を理解したい場合

ワークフロー:

1. get-strings regexPattern="(scanf|read|fgets|input)"
2. find-cross-references to input function
3. Trace data flow: input → storage → transformation → usage
4. Follow transformations until you reach comparison/validation

例:

1. scanf at 0x401000 reads into buffer
2. buffer passed to process_input(buffer)
3. process_input calls encrypt(buffer, key)
4. Encrypted result compared to hardcoded bytes
5. Now analyze: What's the encryption? Can we reverse it?
戦略 3:パターン認識

標準的なアルゴリズムや一般的な手法を特定します

使用する場面:

  • 暗号チャレンジ(暗号化、ハッシュ化)
  • エンコードチャレンジ(base64、独自エンコーディング)
  • アルゴリズム実装のチャレンジ

ワークフロー:

1. Look for algorithmic patterns (see patterns.md):
   - Loop structures (rounds, iterations)
   - Constant arrays (S-boxes, tables)
   - Characteristic operations (XOR, rotations, substitutions)

2. Compare to known implementations:
   - read-memory at constant arrays → compare to standard tables
   - Count loop iterations → indicates algorithm variant
   - search-decompilation for crypto patterns

3. Once identified, apply standard solutions:
   - AES → decrypt with known/derived key
   - RC4 → decrypt with extracted key
   - Custom XOR → reverse the XOR operation
戦略 4:制約充足

問題を数学的な制約として定式化します

使用する場面:

  • シリアル/キーの検証(入力が方程式を満たす必要がある)
  • 数学パズル
  • 相互に関連する複数のチェック

ワークフロー:

1. Identify all constraints on input:
   input[0] + input[1] == 0x42
   input[0] ^ input[2] == 0x13
   input[1] * 2 == input[3]

2. Extract to external solver (z3, constraint solver)

3. Solve for input values

4. Verify solution in program

例:

Decompiled validation:
  if (flag[0] + flag[1] != 100) return 0;
  if (flag[0] - flag[1] != 20) return 0;
  if (flag[2] ^ 0x42 != 0x33) return 0;

Solve:
  flag[0] + flag[1] = 100
  flag[0] - flag[1] = 20
  → flag[0] = 60, flag[1] = 40

  flag[2] ^ 0x42 = 0x33
  → flag[2] = 0x33 ^ 0x42 = 0x71 = 'q'

柔軟なワークフロー

CTF チャレンジは多種多様です。アプローチを適宜調整してください。

初期評価(5~10 分)

チャレンジを把握します:

  • 何が提供されていますか?(バイナリ、ソース、説明?)
  • 目標は何ですか?(フラグの発見、キーの生成、チェックの回避?)
  • 制約は何ですか?(時間制限、ブラックボックス?)

ReVa の偵察:

1. get-current-program or list-project-files
2. get-strings-count and sample strings (100-200)
   - Look for: flag format, hints, library names
3. get-symbols with includeExternal=true
   - Check for suspicious imports (crypto APIs, anti-debug)
4. get-function-count to gauge complexity
集中的な調査(15~45 分)

最も有望な手掛かりを追います:

文字列からフラグ形式を見つけた場合: → フラグ文字列からトップダウンで調査

暗号 API を見つけた場合: → パターン認識(アルゴリズムを特定)

入力検証を見つけた場合: → データフローの追跡(入力から検証まで)

プログラムが単純(関数が 10 個未満)の場合: → 包括的な静的解析

プログラムが複雑、または難読化されている場合: → ハイブリッドアプローチ(動的解析で重要な箇所を見つけ、静的解析で理解する)

解決方法の抽出(10~20 分)

仕組みを理解したら:

  1. 逆変換できますか?

    • 復号、デコード、数学的な逆演算
  2. 導出できますか?

    • 制約を解く、比較から抽出する
  3. 総当たりできますか?

    • キースペースが小さい、検証が高速
  4. 回避できますか?

    • 比較をパッチする、状態を操作する

解決方法を検証します:

  • 可能であれば、実際のプログラムでテストします
  • フラグ形式を確認します(通常は flag{...} または CTF{...})

パターン認識

CTF チャレンジでは、標準的なパターンの認識が試されることがよくあります。詳しいガイドについては patterns.md を参照してください。

暗号パターン:

  • ブロック暗号(AES、DES、独自方式)
  • ストリーム暗号(RC4、独自方式)
  • ハッシュ関数(MD5、SHA、独自方式)
  • XOR による難読化

アルゴリズムパターン:

  • エンコーディング方式(base64、独自アルファベット)
  • 数学的演算(剰余演算、行列演算)
  • 状態機械(状態を介した入力検証)

コードパターン:

  • 入力検証ループ
  • 文字ごとの比較
  • 変換と比較の構造
  • アンチデバッグの仕掛け(CTF の文脈において)

データ構造パターン:

  • ルックアップテーブル(換字式暗号)
  • ハードコードされた配列(期待値)
  • バッファー変換

CTF での ReVa ツールの使用

検出ツール

興味深い箇所をすばやく見つけます:

get-strings regexPattern="(flag|key|password|correct|wrong|success)"
→ Find win/lose conditions

search-decompilation pattern="(scanf|read|input|strcmp|memcmp)"
→ Find input/comparison functions

get-functions-by-similarity searchString="check"
→ Find validation functions
解析ツール

中核となるロジックを理解します:

get-decompilation with includeIncomingReferences=true, includeReferenceContext=true
→ Get full context of validation logic

find-cross-references direction="both" includeContext=true
→ Trace data flow and function relationships

read-memory to extract constants, tables, expected values
→ Get hardcoded comparison targets
改善ツール

作業を進めながら、コードを読みやすくします:

rename-variables to track data flow
→ input_buffer, encrypted_data, expected_hash

change-variable-datatypes to clarify operations
→ uint8_t* for byte buffers, uint32_t for crypto state

set-decompilation-comment to document findings
→ "AES round function", "Compares against flag"

set-bookmark for important locations
→ type="Analysis" for key findings
→ type="TODO" for things to investigate

主な原則

1. 目標に集中

すべてを解析するのではなく、フラグの取得に集中します

  • 重要な経路(入力 → 検証 → 成功)を特定します
  • 関係のない関数は無視します
  • 完全な理解より、十分な理解を優先します
2. すばやく切り替える

行き詰まったら、戦略を切り替えます

  • 静的解析でうまくいかない場合は、動的解析を試します
  • 複雑すぎる場合は、より簡単な方法(回避、総当たり)を探します
  • パターンが一致しない場合は、独自のアルゴリズムかもしれません
3. 知識を活用する

CTF の課題では、概念が繰り返し使われます

  • 標準的な暗号アルゴリズム
  • よくある難読化の手法
  • 典型的な検証パターン
  • 既知の解法を認識して適用する
4. 進捗を記録する

学んだことを記録する

set-bookmark type="Analysis" category="Finding"
  → Document what you've confirmed

set-bookmark type="TODO" category="Investigate"
  → Track unanswered questions

set-decompilation-comment
  → Preserve understanding for later reference
5. 段階的に検証する

理解できているかを進めながら確認する

  • 「これが AES なら、S-box 定数が見つかるはず」→ 確認する
  • 「入力が 0x42 と XOR されているなら、output[0] は……になるはず」→ 例を使って検証する
  • 「これがフラグの比較なら、このバイトを変更すると……になるはず」→ 仮説を検証する

よくある CTF の課題タイプ

Crackme / シリアル検証

課題: 検証を通過する入力を見つける アプローチ: データフローを追跡する(入力 → 検証ロジック) 重要なポイント: 検証関数に注目し、制約を抽出する

アルゴリズムの復元

課題: 不明なアルゴリズムを実装、またはリバースする アプローチ: パターンを認識し、処理を理解する 重要なポイント: 数学的なパターンを探し、変換を追跡する

暗号の課題

課題: 暗号文を復号する、または鍵を見つける アプローチ: アルゴリズムを特定し、鍵や IV を抽出して復号する 重要なポイント: 標準的な暗号のパターンを認識する(patterns.md を参照)

コードの難読化

課題: 難読化またはパックされたコードを理解する アプローチ: 動的解析を使って、難読化が解除された状態を観察する 重要なポイント: プログラムに処理させ、その結果を観察する

バイナリボム

課題: 各フェーズに正しい入力を与えて「爆弾」を解除する アプローチ: フェーズごとに解析し、静的解析と動的解析を組み合わせる 重要なポイント: 各フェーズでは通常、異なる概念が試される

独自のエンコーディング

課題: エンコードされたフラグをデコードする、または入力を正しくエンコードする アプローチ: エンコーディング方式を特定し、逆変換するか再現する 重要なポイント: 変換ループや文字マッピングを探す

他のスキルとの連携

バイナリのトリアージ後

トリアージで疑わしい領域を特定したら、CTF に焦点を当てて深く調査します

From triage bookmarks:
- "Crypto function at 0x401234" → Identify algorithm, extract key
- "Input validation at 0x402000" → Understand constraints, solve
- "Suspicious string XOR" → Decode to find flag or hint
詳細な解析の利用

関数を詳しく理解する必要がある場合

CTF skill identifies: "Validation at validate_key function"
Deep analysis answers: "What exactly does validate_key do?"
CTF skill uses result: Apply findings to extract flag

ワークフロー:

  1. CTF スキル:大局的な戦略を立て、重要な関数を特定する
  2. 詳細な解析:特定の関数を詳しく調査する
  3. CTF スキル:調査結果をまとめ、解法を導き出す

成功の基準

次のことができれば、課題を解いたことになります:

  1. 理解を示す:

    • 入力がどのように出力になるか説明する
    • 検証の仕組みを特定する
    • 中核となるアルゴリズムや手法を認識する
  2. 解答を導き出す:

    • フラグ、鍵、パスワードを提示する
    • どのように導き出したか説明する
    • 動作を確認する(テスト可能な場合)
  3. 調査の過程を記録する:

    • 重要な関数とアドレス
    • 重要な変換や比較
    • 解法(逆変換、導出、総当たり、回避)

覚えておくこと

CTF のリバースエンジニアリングは、制約下での問題解決です:

  • 時間は限られています
  • 完璧な理解ではなく、十分な理解が必要です
  • 目標はフラグであり、網羅的な解析ではありません
  • 見つかったものに応じて戦略を調整します
  • パターンや既存の知識を活用します
  • 必要に応じて静的解析と動的解析を切り替えます

次の問いに答えることに集中します:

  1. プログラムは何を想定しているか?(入力の形式や構造)
  2. プログラムは何をするか?(変換や検証)
  3. どうすれば逆算できるか?(導出、復号、解法の特定、回避)

この3つの問いに答えれば、フラグが見つかります。

コメント