Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
cfgrip — PE/ELF x86/x64 バイナリを逆アセンブルし、GOT、ジャンプテーブル、レジスタトレーシングを介して間接分岐を解決し、静的解析およびパッチ適用のために完全な制御フローグラフを構造化JSONとしてエクスポートします。 | Kitploit
ツール/GitLabGitLab/binaryhardening/cfgrip
静的分析リバースエンジニアリングデバッガバイナリ解析
GitLabbinaryhardening/cfgrip

cfgrip

PE/ELF x86/x64 バイナリを逆アセンブルし、GOT、ジャンプテーブル、レジスタトレーシングを介して間接分岐を解決し、静的解析およびパッチ適用のために完全な制御フローグラフを構造化JSONとしてエクスポートします。

リポジトリを見るウェブサイト
225日前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

cfgrip

PE/ELF x86/x64 CFG 抽出ツール。バイナリを受け取り、逆アセンブルし、すべてのジャンプとコール (GOT、ジャンプテーブル、レジスタトレーシング) を解決し、完全な制御フローグラフを構造化 JSON としてエクスポートします。

理由

すべての分岐がどこへ向かうのかを正確に知る必要があります。読むためではなく、パッチを当てるためです。JSON を Zydis や AsmJit に入力し、フックや変更が必要な正確な命令を特定し、書き戻します。アンチチートチームはこれを使用してゲームバイナリのマッピングを行います。リバースエンジニアリング担当者は、コードを自身の分析パイプラインに持ち上げるために使用します。ソフトウェアアナリストは、バイナリを実行せずに実行パスをトレースします。

cfgrip はマップを提供します。それをどう使うかはあなた次第です。

抽出されるもの

cfgrip が処理するすべてのバイナリに対して、次のものを生成します。

  • 関数リスト:アドレス、オプションの終了アドレス (.pdata から)、名前 (エントリポイント、エクスポート、検出)、およびサンクタグ (PLT スタブ) を含む
  • 基本ブロック:関数ごと — 分岐、コール、リターン、またはトラップで終了する命令シーケンス
  • 制御フローエッジ:各ブロックの後続 (直接分岐、フォールスルー、間接ターゲット)
  • インポートテーブル:解決済みのライブラリインポートとアドレス
  • 間接ターゲット:GOT 解決済みコール、ジャンプテーブルエントリ、レジスタトレースされた分岐、および未解決のもの (そのようにマーク)
  • 関数境界:最大カバレッジのための複数の検出パス (プロローグパターン、コールターゲット、テールコール、.pdata エントリ、データセクション関数ポインタ)

--clean を指定すると、次の追加処理を行います。

  • ジャンプスレッディング:jmp → jmp チェーンを直接エッジに変換
  • デッドブロックの除去:入力エッジのない基本ブロックを削除
  • 各命令への stack_offset 注釈 (関数エントリからの RSP 差分)
  • xrefs セクションの構築:すべてのコール/ジャンプターゲットを呼び出し元にマッピング

また、間接分岐は次の方法で処理します。

  1. GOT (Global Offset Table) をチェックして既知のインポートを特定
  2. 後方に LEA 命令 をスキャンしてジャンプテーブルを見つけ、テーブルエントリを読み取る
  3. レジスタトレーシング:mov/lea チェーンを逆方向にたどって具体的なアドレスを特定

使い方

root@kitploit:~
cfgrip [--subs-only] [--clean] <binary>

バイナリを入力すると、<binary>.cfg が出力されます。
--subs-only を使用すると、エントリポイントからコールグラフ経由で到達可能な関数のみを抽出します。到達不能なエクスポートやプロローグ候補はスキップされます。
--clean を使用すると、ジャンプスレッディング、デッドブロック除去、スタックオフセット追跡、クロスリファレンス分析が適用されます。


例: cfgrip.exe tests\example1.exe format: PE arch: x86-64 entry: 0x1400054bc imports: 85 0x140020000 EncodePointer (KERNEL32.dll) 0x140020008 DecodePointer (KERNEL32.dll) 0x140020010 EnterCriticalSection (KERNEL32.dll) 0x140020018 LeaveCriticalSection (KERNEL32.dll) 0x140020020 InitializeCriticalSectionEx (KERNEL32.dll) 0x140020028 DeleteCriticalSection (KERNEL32.dll) 0x140020030 MultiByteToWideChar (KERNEL32.dll) 0x140020038 WideCharToMultiByte (KERNEL32.dll) 0x140020040 LCMapStringEx (KERNEL32.dll) 0x140020048 GetStringTypeW (KERNEL32.dll) 0x140020050 GetCPInfo (KERNEL32.dll) 0x140020058 RtlCaptureContext (KERNEL32.dll) 0x140020060 RtlLookupFunctionEntry (KERNEL32.dll) 0x140020068 RtlVirtualUnwind (KERNEL32.dll) 0x140020070 UnhandledExceptionFilter (KERNEL32.dll) 0x140020078 SetUnhandledExceptionFilter (KERNEL32.dll) 0x140020080 GetCurrentProcess (KERNEL32.dll) 0x140020088 TerminateProcess (KERNEL32.dll) 0x140020090 IsProcessorFeaturePresent (KERNEL32.dll) 0x140020098 QueryPerformanceCounter (KERNEL32.dll) 0x1400200a0 GetCurrentProcessId (KERNEL32.dll) 0x1400200a8 GetCurrentThreadId (KERNEL32.dll) 0x1400200b0 GetSystemTimeAsFileTime (KERNEL32.dll) 0x1400200b8 InitializeSListHead (KERNEL32.dll) 0x1400200c0 IsDebuggerPresent (KERNEL32.dll) 0x1400200c8 GetStartupInfoW (KERNEL32.dll) 0x1400200d0 GetModuleHandleW (KERNEL32.dll) 0x1400200d8 WriteConsoleW (KERNEL32.dll) 0x1400200e0 RtlPcToFileHeader (KERNEL32.dll) 0x1400200e8 RaiseException (KERNEL32.dll) 0x1400200f0 RtlUnwindEx (KERNEL32.dll) 0x1400200f8 GetLastError (KERNEL32.dll) 0x140020100 SetLastError (KERNEL32.dll) 0x140020108 InitializeCriticalSectionAndSpinCount (KERNEL32.dll) 0x140020110 TlsAlloc (KERNEL32.dll) 0x140020118 TlsGetValue (KERNEL32.dll) 0x140020120 TlsSetValue (KERNEL32.dll) 0x140020128 TlsFree (KERNEL32.dll) 0x140020130 FreeLibrary (KERNEL32.dll) 0x140020138 GetProcAddress (KERNEL32.dll) 0x140020140 LoadLibraryExW (KERNEL32.dll) 0x140020148 GetStdHandle (KERNEL32.dll) 0x140020150 WriteFile (KERNEL32.dll) 0x140020158 GetModuleFileNameW (KERNEL32.dll) 0x140020160 ExitProcess (KERNEL32.dll) 0x140020168 GetModuleHandleExW (KERNEL32.dll) 0x140020170 GetCommandLineA (KERNEL32.dll) 0x140020178 GetCommandLineW (KERNEL32.dll) 0x140020180 HeapAlloc (KERNEL32.dll) 0x140020188 HeapFree (KERNEL32.dll) 0x140020190 FlsAlloc (KERNEL32.dll) 0x140020198 FlsGetValue (KERNEL32.dll) 0x1400201a0 FlsSetValue (KERNEL32.dll) 0x1400201a8 FlsFree (KERNEL32.dll) 0x1400201b0 VirtualProtect (KERNEL32.dll) 0x1400201b8 CompareStringW (KERNEL32.dll) 0x1400201c0 LCMapStringW (KERNEL32.dll) 0x1400201c8 GetLocaleInfoW (KERNEL32.dll) 0x1400201d0 IsValidLocale (KERNEL32.dll) 0x1400201d8 GetUserDefaultLCID (KERNEL32.dll) 0x1400201e0 EnumSystemLocalesW (KERNEL32.dll) 0x1400201e8 GetFileType (KERNEL32.dll) 0x1400201f0 CloseHandle (KERNEL32.dll) 0x1400201f8 FlushFileBuffers (KERNEL32.dll) 0x140020200 GetConsoleOutputCP (KERNEL32.dll) 0x140020208 GetConsoleMode (KERNEL32.dll) 0x140020210 ReadFile (KERNEL32.dll) 0x140020218 GetFileSizeEx (KERNEL32.dll) 0x140020220 SetFilePointerEx (KERNEL32.dll) 0x140020228 ReadConsoleW (KERNEL32.dll) 0x140020230 HeapReAlloc (KERNEL32.dll) 0x140020238 FindClose (KERNEL32.dll) 0x140020240 FindFirstFileExW (KERNEL32.dll) 0x140020248 FindNextFileW (KERNEL32.dll) 0x140020250 IsValidCodePage (KERNEL32.dll) 0x140020258 GetACP (KERNEL32.dll) 0x140020260 GetOEMCP (KERNEL32.dll) 0x140020268 GetEnvironmentStringsW (KERNEL32.dll) 0x140020270 FreeEnvironmentStringsW (KERNEL32.dll) 0x140020278 SetEnvironmentVariableW (KERNEL32.dll) 0x140020280 SetStdHandle (KERNEL32.dll) 0x140020288 GetProcessHeap (KERNEL32.dll) 0x140020290 HeapSize (KERNEL32.dll) 0x140020298 CreateFileW (KERNEL32.dll) 0x1400202a0 RtlUnwind (KERNEL32.dll) functions: 1975 indirect targets: 3453 cfg written to: tests\example1.exe.cfg

出力形式

.cfg ファイルは構造化 JSON です。以下がその外観です:

root@kitploit:~
{
  "binary": "tests\\example1.exe",
  "mode": "full",
  "arch": "x86-64",
  "format": "PE",
  "entry_point": "0x1400054bc",
  "imports": [
    {
      "address": "0x140020000",
      "name": "EncodePointer",
      "library": "KERNEL32.dll"
    },
    {
      "address": "0x140020008",
      "name": "DecodePointer",
      "library": "KERNEL32.dll"
    },
    {
      "address": "0x140020010",
      "name": "EnterCriticalSection",
      "library": "KERNEL32.dll"
    },
    {
      "address": "0x140020018",
      "name": "LeaveCriticalSection",
      "library": "KERNEL32.dll"
    },
    {
      "address": "0x140020020",
      "name": "InitializeCriticalSectionEx",
      "library": "KERNEL32.dll"
    },
    ...
    ...
    ...
  "functions": [
    {
      "address": "0x1400054bc",
      "name": "entry",
      "blocks": [
        {
          "address": "0x1400054bc",
          "size": 4,
          "is_prolog": false,
          "is_epilog": false,
          "instructions": [
            {
              "address": "0x1400054bc",
              "size": 4,
              "mnemonic": "sub",
              "operands": "rsp, 0x28"
            },
            {
              "address": "0x1400054c0",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x140005d30"
            },
            {
              "address": "0x1400054c5",
              "size": 4,
              "mnemonic": "add",
              "operands": "rsp, 0x28"
            },
            {
              "address": "0x1400054c9",
              "size": 5,
              "mnemonic": "jmp",
              "operands": "0x140005340"
            }
          ],
          "successors": [
            "0x140005340"
          ]
        },
        {
          "address": "0x140005340",
          "size": 8,
          "is_prolog": false,
          "is_epilog": false,
          "instructions": [
            {
              "address": "0x140005340",
              "size": 5,
              "mnemonic": "mov",
              "operands": "qword ptr [rsp + 8], rbx"
            },
            {
              "address": "0x140005345",
              "size": 5,
              "mnemonic": "mov",
              "operands": "qword ptr [rsp + 0x10], rsi"
            },
            {
              "address": "0x14000534a",
              "size": 1,
              "mnemonic": "push",
              "operands": "rdi"
            },
            {
              "address": "0x14000534b",
              "size": 4,
              "mnemonic": "sub",
              "operands": "rsp, 0x30"
            },
            {
              "address": "0x14000534f",
              "size": 5,
              "mnemonic": "mov",
              "operands": "ecx, 1"
            },
            {
              "address": "0x140005354",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x14000550c"
            },
            {
              "address": "0x140005359",
              "size": 2,
              "mnemonic": "test",
              "operands": "al, al"
            },
            {
              "address": "0x14000535b",
              "size": 6,
              "mnemonic": "je",
              "operands": "0x140005497"
            }
          ],
          "successors": [
            "0x140005497",
            "0x140005361"
          ]
        },
        {
          "address": "0x140005497",
          "size": 15,
          "is_prolog": false,
          "is_epilog": false,
          "instructions": [
            {
              "address": "0x140005497",
              "size": 5,
              "mnemonic": "mov",
              "operands": "ecx, 7"
            },
            {
              "address": "0x14000549c",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x140005e44"
            },
            {
              "address": "0x1400054a1",
              "size": 1,
              "mnemonic": "nop",
              "operands": ""
            },
            {
              "address": "0x1400054a2",
              "size": 5,
              "mnemonic": "mov",
              "operands": "ecx, 7"
            },
            {
              "address": "0x1400054a7",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x140005e44"
            },
            {
              "address": "0x1400054ac",
              "size": 2,
              "mnemonic": "mov",
              "operands": "ecx, ebx"
            },
            {
              "address": "0x1400054ae",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x14000ec14"
            },
            {
              "address": "0x1400054b3",
              "size": 1,
              "mnemonic": "nop",
              "operands": ""
            },
            {
              "address": "0x1400054b4",
              "size": 2,
              "mnemonic": "mov",
              "operands": "ecx, ebx"
            },
            {
              "address": "0x1400054b6",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x14000ebcc"
            },
            {
              "address": "0x1400054bb",
              "size": 1,
              "mnemonic": "nop",
              "operands": ""
            },
            {
              "address": "0x1400054bc",
              "size": 4,
              "mnemonic": "sub",
              "operands": "rsp, 0x28"
            },
            {
              "address": "0x1400054c0",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x140005d30"
            },
            {
              "address": "0x1400054c5",
              "size": 4,
              "mnemonic": "add",
              "operands": "rsp, 0x28"
            },
            {
              "address": "0x1400054c9",
              "size": 5,
              "mnemonic": "jmp",
              "operands": "0x140005340"
            }
          ],
          "successors": [
            "0x140005340"
          ]
        },
        ...
        ...
        ...

各関数にはオプションフィールドが含まれるようになりました:

  • end_address — 利用可能な場合の正確な関数終了アドレス (PE .pdata 例外テーブルから)。それ以外の場合は、すべてのブロックの最大命令アドレスとして計算されます。
  • is_thunk — PLT スタブおよびインポートサンク (別のアドレスにリダイレクトするだけの関数) の場合に true。

--subs-only 出力

root@kitploit:~
{
  "binary": "C:\\binaries\\target.exe",
  "mode": "subs-only",
  "arch": "x86-64",
  "format": "PE",
  "entry_point": "0x1400054bc",
  "imports": [ ... ],
  "indirect_targets": [ ... ],
  "functions": [
    {
      "address": "0x1400054bc",
      "name": "entry",
      "blocks": [ ... ]
    },
    ...
  ]
}

"mode": "subs-only" フィールドは、ダウンストリームツールにこの CFG がエントリポイントから到達可能な関数のみを含むことを伝えます。到達不能なエクスポートとプロローグ候補は除外されます。関数が少なくなり、分析対象がよりクリーンになります。

--clean 出力

root@kitploit:~
{
  "binary": "C:\\binaries\\target.exe",
  "mode": "full+clean",
  "arch": "x86-64",
  "format": "PE",
  "entry_point": "0x1400054bc",
  "imports": [ ... ],
  "indirect_targets": [ ... ],
  "functions": [
    {
      "address": "0x1400054bc",
      "name": "entry",
      "blocks": [
        {
          "address": "0x1400054bc",
          "size": 4,
          "is_prolog": false,
          "is_epilog": false,
          "instructions": [
            {
              "address": "0x1400054bc",
              "size": 4,
              "mnemonic": "sub",
              "operands": "rsp, 0x28",
              "stack_offset": 0
            },
            {
              "address": "0x1400054c0",
              "size": 5,
              "mnemonic": "call",
              "operands": "0x140005d30",
              "stack_offset": -40
            },
            {
              "address": "0x1400054c5",
              "size": 4,
              "mnemonic": "add",
              "operands": "rsp, 0x28",
              "stack_offset": -40
            },
            {
              "address": "0x1400054c9",
              "size": 5,
              "mnemonic": "jmp",
              "operands": "0x140005340",
              "stack_offset": 0
            }
          ],
          "successors": [ "0x140005340" ]
        },
        ...
      ]
    },
    ...
  ],
  "xrefs": [
    {
      "target": "0x140011b00",
      "callers": [
        { "address": "0x14001a30f", "type": "call" },
        { "address": "0x140019ec1", "type": "call" },
        ...
      ]
    },
    {
      "target": "0x140007394",
      "callers": [
        { "address": "0x14001a31a", "type": "call" },
        ...
      ]
    },
    ...
  ]
}

--clean モードのすべての命令には stack_offset が含まれます — その命令ポイントにおける関数エントリからの RSP 差分です。xrefs セクションは、各コール/ジャンプターゲットをそれを参照するすべての命令にマッピングします。

--subs-only --clean 結合出力

root@kitploit:~
{
  "binary": "C:\\binaries\\target.exe",
  "mode": "subs-only+clean",
  ...
}

--clean と同じ構造ですが、"mode": "subs-only+clean" で両方のフィルタが適用されたことを示します。関数数はエントリポイントから到達可能な関数のみに削減され、残りの関数にはスタックオフセットと xrefs が含まれます。

関数境界検出

cfgrip は複数の検出パスを通じて関数を発見します:

is_thunk: true の関数は PLT スタブまたはインポートサンクです。別のアドレスにリダイレクトする単一ブロックの関数です。

ビルド

CMake と C++17 コンパイラが必要です。Capstone は自動的に取得されます。

root@kitploit:~
cmake -B build
cmake --build build --config Release
./build/cfgrip <binary>

または Windows で Visual Studio を使用する場合:

root@kitploit:~
cmake -B build -S .
cmake --build build --config Release
.\build\Release\cfgrip.exe <binary>

alt text alt text


対応内容

| | | |:-:| | フォーマット | PE (32/64-bit) | YES | | | ELF (64-bit) | YES | | アーキテクチャ | x86 | YES | | | x86-64 | YES | | 間接コール | GOT resolution | YES | | | Jump table detection | YES | | | Backward register tracing | YES | | 関数検出 | Entry point | YES | | | Exports | YES | | | call targets | YES | | | Prolog scanning (MSVC x64, GCC, CET endbr64) | YES | | | Tail-call detection (jmp → function) | YES | | | PE .pdata (exception handler table) | YES | | | Data-section function pointer scan | YES | | サンク検出 | PLT stubs / import thunks (is_thunk) | YES | | 関数境界 | end_address from .pdata or max instruction | YES | | Subs-only モード | --subs-only flag | YES | | CFG クリーニング | --clean (jump-thread, dead-block prune, stack deltas, xrefs) | YES |

研究

このツールの関数境界検出は、"Function Boundary Detection in Stripped Binaries" (Alves-Foss & Song, 2019) で説明されているアプローチに基づいています。この論文では、 stripped x86/x64 バイナリで関数の開始と終了を見つけるためのマルチヒューリスティックアルゴリズムを導入しています。

論文は papers/Function_Boundary_Detection_in_Stripped_Binaries.pdf で入手できます。

論文のヒューリスティックへの実装のマッピング:

この論文の重要な洞察は、機械学習なしのアルゴリズム的ヒューリスティックがストリップされたバイナリで高い精度を達成できることです。当実装はこの哲学に従い、各パスが他のパスが見逃す可能性のある関数を捕捉するマルチパスアプローチを使用しています。

ツールをダウンロード
パス検出内容カバレッジ
プロローグスキャンpush rbp, push r15/r14/r13/r12/rbx/rdi/rsi, sub rsp, >=0x20, enterMSVC x64, GCC, リーフ関数, CET (endbr64)
コールターゲットすべての call 命令のターゲットは関数開始点直接コールおよび GOT 解決済み間接コール
テールコールプロローグ候補をターゲットとする jmp 命令最適化されたテールコールチェーン
.pdata (PE)例外ハンドラテーブルからのランタイム関数エントリすべての x64 PE 関数の正確な開始/終了
データポインタ.rdata/.data 内の実行可能コードを指す 8 バイト値関数ポインタ、vtable、コールバック
ヒューリスティック論文の説明当実装
H1–H4Prolog signatures (push rbp, callee-saved regs, stack sub, enter)isProlog() in disasm/engine.cpp — push rbp, push r15..rbx, sub rsp >= 0x20, enter を検出
H5Call-target seedingすべての直接 call ターゲットは関数開始点
H6Jump-to-function (tail call) detectionプロローグ候補への jmp はターゲットを関数キューに追加
H7Exception table parsingPE .pdata RUNTIME_FUNCTION エントリが正確な開始/終了を提供
H8Data reference analysisscanDataPointers() はデータセクションをスキャンしてコードポインタを探す