jpskill.com
📦 その他 コミュニティ

binary-re-static-analysis

バイナリファイルの構造解析、コードの逆アセンブルやデコンパイルに活用し、radare2やGhidraを用いて関数一覧の抽出、参照関係の解析、制御フローグラフの生成など、詳細な静的解析を実施するSkill。

📜 元の英語説明(参考)

Use when analyzing binary structure, disassembling code, or decompiling functions. Deep static analysis via radare2 (r2) and Ghidra headless - function enumeration, cross-references (xrefs), decompilation, control flow graphs. Keywords - "disassemble", "decompile", "what does this function do", "find functions", "analyze code", "r2", "ghidra", "pdg", "afl"

🇯🇵 日本人クリエイター向け解説

一言でいうと

バイナリファイルの構造解析、コードの逆アセンブルやデコンパイルに活用し、radare2やGhidraを用いて関数一覧の抽出、参照関係の解析、制御フローグラフの生成など、詳細な静的解析を実施するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o binary-re-static-analysis.zip https://jpskill.com/download/16695.zip && unzip -o binary-re-static-analysis.zip && rm binary-re-static-analysis.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/16695.zip -OutFile "$d\binary-re-static-analysis.zip"; Expand-Archive "$d\binary-re-static-analysis.zip" -DestinationPath $d -Force; ri "$d\binary-re-static-analysis.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して binary-re-static-analysis.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → binary-re-static-analysis フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

静的解析 (フェーズ 2-3)

目的

実行せずにバイナリの構造とロジックを理解します。関数をマッピングし、データフローをトレースし、重要なコードをデコンパイルします。

使用するタイミング

  • トリアージでアーキテクチャと ABI が確立された後
  • 興味深いと特定された特定の関数を理解するため
  • 動的解析が非現実的または危険な場合
  • 動的検証の前に仮説を構築するため

事前解析: 既知の I/O を最初に比較する

重要: 逆アセンブルに入る前に、既知の入力/出力が存在するかどうかを確認してください。

⚠️ 人間の承認が必要 - 実行(I/O 比較を含む)を行う前に、明示的な承認を得てください。

# 安全: クロスアーキバイナリにはエミュレーションを使用する (人間の承認後)
# ARM32:
qemu-arm -L /usr/arm-linux-gnueabihf -- ./binary < input.txt > actual.txt

# ARM64:
qemu-aarch64 -L /usr/aarch64-linux-gnu -- ./binary < input.txt > actual.txt

# Docker ベース (macOS/クロスアーキ - dynamic-analysis のオプション D を参照):
docker run --rm --platform linux/arm/v7 -v ~/samples:/work:ro \
  arm32v7/debian:bullseye-slim sh -c '/work/binary < /work/input.txt' > actual.txt

# x86-64 ネイティブ (それでも承認が必要):
./binary < input.txt > actual.txt

# 出力を比較:
diff expected.txt actual.txt
cmp -l expected.txt actual.txt | head -20  # バイトレベルの差異

# 発見事項を記録:
# - 出力が最初に分岐するのはどこか?
# - ファイルサイズは一致するか? (ロジックバグ vs 切り捨て)
# - 破損にどのようなパターンが現れるか?

このステップで、コード解析を行う前にバグのカテゴリが明らかになることがよくあります。


2 段階のアプローチ

ステージ 1 (ライト): 関数列挙、文字列、インポート - 高速、広範囲をカバー ステージ 2 (ディープ): ターゲットを絞ったデコンパイル、CFG 解析 - 低速、焦点を絞る

ステージ 1: ライト解析 (radare2)

解析深度の選択

バイナリサイズ コマンド トレードオフ
< 500KB aaa 完全な解析、遅くなる可能性あり
500KB - 5MB aa; aac 関数 + すべての呼び出しターゲット
> 5MB aa + ターゲットを絞った af @addr 高速、手動で深度を制御

セッションのセットアップ

# 制御された解析で r2 を起動
r2 -q0 -e scr.color=false -e anal.timeout=120 -e anal.maxsize=67108864 binary

# r2 内 (バイナリサイズに基づいて選択):
aa       # 基本的な解析
aac      # すべての呼び出しターゲットも解析する (ほとんどのバイナリに推奨)

重要な設定:

  • anal.timeout=120 - 暴走解析を防ぐ
  • anal.maxsize=67108864 - 最大関数サイズ 64MB
  • 中規模のバイナリには aa; aac を使用し、小規模なバイナリには aaa のみを使用する

解析されていない呼び出しターゲットの処理

既知のインポートに対して axtj が空を返す場合:

# インポートが間接的に呼び出されているか、解析が浅すぎる可能性があります
# オプション 1: より深い解析
aac   # すべての呼び出しを解析する

# オプション 2: 呼び出しターゲットで関数を手動で作成する
af @0x8048abc

# オプション 3: インポートアドレスへの参照を検索する
axtj @sym.imp.connect

関数の列挙

# すべての関数を JSON として
aflj

# 名前パターンでフィルタリング
aflj~main
aflj~init
aflj~network
aflj~send
aflj~recv

# 関数数
afl~?

クロスリファレンス解析

# 誰がこの関数を呼び出しているか?
axtj @sym.imp.connect

# この関数は何を呼び出しているか?
axfj @sym.main

# アドレスへのデータ参照
axtj @0x12345

文字列と関数の相関

# 文字列を含む関数を見つける
izj~api.vendor.com
# vaddr に注意し、それを含む関数を見つける
afi @0xVADDR

# または検索してマッピングする
"/j api"    # 文字列を検索
axtj @@hit* # すべてのヒットへの Xrefs

インポート/エクスポートのマッピング

# アドレス付きのインポート
iij

# アドレス付きのエクスポート
iEj

# シンボル (ストリップされていない場合)
isj

クイック逆アセンブル

# 関数を JSON として逆アセンブル
pdfj @sym.main

# アドレスから N 個の命令を逆アセンブル
pdj 20 @0x8400

# 関数の概要を出力
afi @sym.main

ステージ 2: ディープ解析

r2ghidra の可用性チェック

デコンパイルを試みる前に、r2ghidra がインストールされていることを確認してください:

# r2ghidra が利用可能かどうかを確認
r2 -qc 'pdg?' - 2>/dev/null | grep -q Usage && echo "r2ghidra OK" || echo "SKIP: r2ghidra がインストールされていません"

# 見つからない場合は、次のようにインストールします:
r2pm -ci r2ghidra

r2ghidra が利用できない場合: 逆アセンブル (pdf) とクロスリファレンス解析 (axt/axf) に頼ってください。

ターゲットを絞ったデコンパイル (r2ghidra)

# 特定の関数をデコンパイル
pdgj @sym.target_function

# または名前付き関数
pdgj @sym.main

Ghidra ヘッドレス (大規模なバイナリ)

複雑な関数の場合、または r2ghidra が苦労する場合:

# 解析プロジェクトを作成し、スクリプトを実行
analyzeHeadless /tmp/ghidra_proj proj \
  -import binary \
  -overwrite \
  -processor ARM:LE:32:v7 \
  -postScript ExportDecompilation.java sym.target_function \
  -deleteProject

プロセッサ文字列:

  • ARM 32 ビット: ARM:LE:32:v7 または ARM:LE:32:Cortex
  • ARM 64 ビット: AARCH64:LE:64:v8A
  • x86_64: x86:LE:64:default
  • MIPS LE: MIPS:LE:32:default
  • MIPS BE: MIPS:BE:32:default

制御フロー解析

# 関数内の基本ブロック
afbj @sym.main

# 関数呼び出しグラフ (dot 形式)
agCd @sym.main > callgraph.dot

# 制御フローグラフ
agfd @sym.main > cfg.dot

データ構造の復元

# ローカル変数を解析
afvj @sym.main

# スタックフレームレイアウト
afvd @sym.main

# グローバルデータ参照
adrj

解析パターン

パターン: ネットワーク関数のトレース

# すべてのネットワーク関連の呼び出しを見つける
axtj @sym.imp.socket
axtj @sym.imp.connect
axtj @sym.imp.send
axtj @sym.imp.recv
axtj @sym.imp.SSL_read
axtj @sym.imp.SSL_write

# 呼び出し元チェーンをトレース
for func in $(aflj | jq -r '.[].name'); do
  axfj @$func | grep -q "socket\|connect" && echo $func
done

パターン: 構成ファイル解析

# ファイル操作を見つける
axtj @sym.imp.open
axtj @sym.imp.fopen

# 文字列引数をトレース
"/j /etc"
"/j .conf"
"/j .json"

# これらのパスを参照する関数を確認する

パターン: 暗号の識別


# 一般的な暗号インポート
axtj @sym.imp.EVP_EncryptInit
axtj @sym.imp.AES_encrypt
axtj @sym.imp.SHA256

# ハードコードされたキー (暗号呼び出しの近くの文字列を確認)
izj | jq '.strings[] | select

(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Static Analysis (Phases 2-3)

Purpose

Understand binary structure and logic without execution. Map functions, trace data flow, decompile critical code.

When to Use

  • After triage has established architecture and ABI
  • To understand specific functions identified as interesting
  • When dynamic analysis is impractical or risky
  • To build hypotheses before dynamic verification

Pre-Analysis: Compare Known I/O First

CRITICAL: Before diving into disassembly, check if known inputs/outputs exist.

⚠️ REQUIRES HUMAN APPROVAL - Get explicit approval before any execution, even for I/O comparison.

# SAFE: Use emulation for cross-arch binaries (after human approval)
# ARM32:
qemu-arm -L /usr/arm-linux-gnueabihf -- ./binary < input.txt > actual.txt

# ARM64:
qemu-aarch64 -L /usr/aarch64-linux-gnu -- ./binary < input.txt > actual.txt

# Docker-based (macOS/cross-arch - see dynamic-analysis Option D):
docker run --rm --platform linux/arm/v7 -v ~/samples:/work:ro \
  arm32v7/debian:bullseye-slim sh -c '/work/binary < /work/input.txt' > actual.txt

# x86-64 native (still requires approval):
./binary < input.txt > actual.txt

# Compare outputs:
diff expected.txt actual.txt
cmp -l expected.txt actual.txt | head -20  # Byte-level differences

# Record findings:
# - Where does output first diverge?
# - Does file size match? (logic bug vs truncation)
# - What pattern appears in corruption?

This step often reveals the bug category before any code analysis.


Two-Stage Approach

Stage 1 (Light): Function enumeration, strings, imports - fast, broad coverage Stage 2 (Deep): Targeted decompilation, CFG analysis - slow, focused

Stage 1: Light Analysis (radare2)

Analysis Depth Selection

Binary Size Command Tradeoff
< 500KB aaa Full analysis, may be slow
500KB - 5MB aa; aac Functions + all call targets
> 5MB aa + targeted af @addr Fast, manual depth control

Session Setup

# Launch r2 with controlled analysis
r2 -q0 -e scr.color=false -e anal.timeout=120 -e anal.maxsize=67108864 binary

# Inside r2 (choose based on binary size):
aa       # Basic analysis
aac      # Also analyze all call targets (recommended for most binaries)

Critical settings:

  • anal.timeout=120 - Prevent runaway analysis
  • anal.maxsize=67108864 - 64MB max function size
  • Use aa; aac for medium binaries, aaa only for small ones

Handling Unanalyzed Call Targets

If axtj returns empty for known imports:

# The import may be called indirectly or analysis was too shallow
# Option 1: Deeper analysis
aac   # Analyze all calls

# Option 2: Manually create function at call target
af @0x8048abc

# Option 3: Search for references to import address
axtj @sym.imp.connect

Function Enumeration

# All functions as JSON
aflj

# Filter by name pattern
aflj~main
aflj~init
aflj~network
aflj~send
aflj~recv

# Function count
afl~?

Cross-Reference Analysis

# Who calls this function?
axtj @sym.imp.connect

# What does this function call?
axfj @sym.main

# Data references to address
axtj @0x12345

String-Function Correlation

# Find which function contains a string
izj~api.vendor.com
# Note the vaddr, then find containing function
afi @0xVADDR

# Or search and map
"/j api"    # Search for string
axtj @@hit* # Xrefs to all hits

Import/Export Mapping

# Imports with addresses
iij

# Exports with addresses
iEj

# Symbols (if not stripped)
isj

Quick Disassembly

# Disassemble function as JSON
pdfj @sym.main

# Disassemble N instructions from address
pdj 20 @0x8400

# Print function summary
afi @sym.main

Stage 2: Deep Analysis

r2ghidra Availability Check

Before attempting decompilation, verify r2ghidra is installed:

# Check if r2ghidra is available
r2 -qc 'pdg?' - 2>/dev/null | grep -q Usage && echo "r2ghidra OK" || echo "SKIP: r2ghidra not installed"

# If missing, install with:
r2pm -ci r2ghidra

If r2ghidra unavailable: Rely on disassembly (pdf) and cross-reference analysis (axt/axf).

Targeted Decompilation (r2ghidra)

# Decompile specific function
pdgj @sym.target_function

# Or named function
pdgj @sym.main

Ghidra Headless (Large Binaries)

For complex functions or when r2ghidra struggles:

# Create analysis project and run script
analyzeHeadless /tmp/ghidra_proj proj \
  -import binary \
  -overwrite \
  -processor ARM:LE:32:v7 \
  -postScript ExportDecompilation.java sym.target_function \
  -deleteProject

Processor strings:

  • ARM 32-bit: ARM:LE:32:v7 or ARM:LE:32:Cortex
  • ARM 64-bit: AARCH64:LE:64:v8A
  • x86_64: x86:LE:64:default
  • MIPS LE: MIPS:LE:32:default
  • MIPS BE: MIPS:BE:32:default

Control Flow Analysis

# Basic blocks in function
afbj @sym.main

# Function call graph (dot format)
agCd @sym.main > callgraph.dot

# Control flow graph
agfd @sym.main > cfg.dot

Data Structure Recovery

# Analyze local variables
afvj @sym.main

# Stack frame layout
afvd @sym.main

# Global data references
adrj

Analysis Patterns

Pattern: Network Function Tracing

# Find all network-related calls
axtj @sym.imp.socket
axtj @sym.imp.connect
axtj @sym.imp.send
axtj @sym.imp.recv
axtj @sym.imp.SSL_read
axtj @sym.imp.SSL_write

# Trace caller chain
for func in $(aflj | jq -r '.[].name'); do
  axfj @$func | grep -q "socket\|connect" && echo $func
done

Pattern: Configuration File Analysis

# Find file operations
axtj @sym.imp.open
axtj @sym.imp.fopen

# Trace string arguments
"/j /etc"
"/j .conf"
"/j .json"

# Check what functions reference these paths

Pattern: Crypto Identification

# Common crypto imports
axtj @sym.imp.EVP_EncryptInit
axtj @sym.imp.AES_encrypt
axtj @sym.imp.SHA256

# Hardcoded keys (check strings near crypto calls)
izj | jq '.strings[] | select(.length == 16 or .length == 32)'

r2 JSON Commands Reference

Command Output Use Case
aflj Functions list Map code structure
axtj @addr Xrefs TO address Who uses this?
axfj @addr Xrefs FROM address What does it call?
pdfj @addr Disassembly Understand instructions
pdgj @addr Decompilation Pseudo-C output
afbj @addr Basic blocks Control flow
izj Data strings Configuration, URLs
iij Imports External dependencies
iEj Exports Public interface
afvj @addr Local variables Stack analysis

Output Format

Record analysis findings as structured facts:

{
  "functions_analyzed": [
    {
      "name": "sub_8400",
      "address": "0x8400",
      "size": 256,
      "calls": ["socket", "connect", "send"],
      "called_by": ["main", "init_network"],
      "strings_referenced": ["api.vendor.com"],
      "hypothesis": "network_initialization"
    }
  ],
  "call_graph": {
    "main": ["init_config", "init_network", "main_loop"],
    "init_network": ["sub_8400", "SSL_CTX_new"]
  },
  "data_flow": [
    {
      "source": "config_file_read",
      "through": ["parse_config", "extract_url"],
      "sink": "connect_to_server"
    }
  ]
}

Knowledge Journaling

After static analysis, record findings for episodic memory:

[BINARY-RE:static] {filename} (sha256: {hash})

Functions analyzed: {count}
Decompilation performed: {yes|no}

Key functions:
  FACT: Function at {addr} calls {imports} (source: r2 axfj)
  FACT: Function at {addr} references string "{string}" (source: r2 axtj)
  FACT: Function {name} appears to {purpose} (source: decompilation)

Cross-references:
  FACT: {caller} calls {callee} (source: r2 axtj)

HYPOTHESIS UPDATE: {refined theory} (confidence: {new_value})
  Supporting: {fact_ids}
  Contradicting: {fact_ids}

New questions:
  QUESTION: {discovered unknown}

Answered questions:
  RESOLVED: {question} → {answer}

Example Journal Entry

[BINARY-RE:static] thermostat_daemon (sha256: a1b2c3d4...)

Functions analyzed: 47
Decompilation performed: yes (function 0x8400)

Key functions:
  FACT: Function 0x8400 calls curl_easy_perform, curl_easy_setopt (source: r2 axfj)
  FACT: Function 0x8400 references string "api.thermco.com/telemetry" (source: r2 axtj)
  FACT: Function 0x9200 parses JSON using jsmn library (source: decompilation)
  FACT: Function 0x10800 is main loop, calls 0x8400 after sleep(30) (source: r2 pdf)

Cross-references:
  FACT: main calls init_config (0x9000) then main_loop (0x10800) (source: r2 axtj)
  FACT: main_loop calls send_telemetry (0x8400) in loop (source: r2 pdf)

HYPOTHESIS UPDATE: Telemetry client sending to api.thermco.com every 30 seconds (confidence: 0.85)
  Supporting: URL string, curl imports, sleep(30) in loop
  Contradicting: none

New questions:
  QUESTION: What data fields are included in telemetry payload?
  QUESTION: Is there any authentication/API key?

Answered questions:
  RESOLVED: "What endpoint?" → api.thermco.com/telemetry via HTTPS

Decision Points

After static analysis:

  1. Identified critical functions? → Ready for dynamic verification
  2. Unclear behavior? → Try dynamic analysis for runtime observation
  3. Crypto detected? → Document key handling, note for security review
  4. Anti-analysis patterns? → Consider Unicorn snippet emulation

Next Steps

binary-re-dynamic-analysis to verify hypotheses with runtime observation → binary-re-synthesis if sufficient understanding reached