
デコンパイラからデバッガに対話型シンボルを導入するプラグイン
リバースエンジニアリングには静的解析(デコンパイラ)と動的解析(デバッガ)の両方が含まれますが、これらの解析を相互に知識共有せずに使用することがよくあります。静的なバイナリをリバースする場合、デバッガのアセンブリと、デコンパイルでリバースしたシンボルとの間でコンテキストを切り替えるのは非効率です。
decomp2dbgは、デコンパイラとデバッガの間でシンボルを同期するための汎用APIを導入することで、コンテキストスイッチのギャップを短縮することを目的としています。これにより、リバースエンジニアはデバッガの能力を、デコンパイラで復元したシンボルやデコンパイル行と組み合わせて活用できるようになります。

実際のdecomp2dbgの動作を見てみませんか? CactusCon 2023でのトーク(録画)をご覧ください。Ghidraのシンボルを使ってx64マシンからリモートのarm32バイナリをデバッグする様子が紹介されています。
アクティブなサポートについては、以下のBinSync Discordに参加してください。decomp2dbgに関する質問にも回答しています。
pipでインストール後、組み込みのインストーラをデコンパイラ用に使用します。
pip3 install decomp2dbg && decomp2dbg --install
これによりプロンプトが開き、使用するデコンパイラとデバッガのパスを入力するよう求められます。Ghidraの場合は、PyGhidraモードで起動し、プラグイン(d2d_client.py)を有効にする必要があります。詳細はこちらをご覧ください。Binjaプラグインマネージャでデコンパイラ側をインストールした場合でも、上記の手順でデバッガ側をインストールする必要があります。注意:decomp2dbgはデコンパイラおよびデバッガと同じPython環境にインストールする必要があります。
注: decomp2dbgがデコンパイラに接続できるよう、ポート3662(または使用するポート)へのインバウンド接続を許可する必要がある場合があります。GEFまたはpwndbgと共にdecomp2dbgをインストールする場合、~/.gdbinit内でd2d.pyファイルがGEFまたはpwndbgの後に読み込まれるようにすることが重要です。
上記のインストールがエラーなくできた場合は、この手順はスキップしてください。 上記の組み込みスクリプトを使用できない場合(非WSL Windowsへのデコンパイラインストールなど)は、以下の手順に従ってください。
デコンパイラ側のみ必要な場合は、対応するデコンパイラプラグインをデコンパイラのプラグインフォルダにコピーします。IDAでの方法は次の通りです。
まず、リポジトリをクローンします。
git clone https://github.com/mahaloz/decomp2dbg.git
インストール:
pip install .
サーバファイルをすべてコピー:
cp ./decomp2dbg/d2d_server.py /path/to/ida/plugins/
gdb側もインストールする必要がある場合は、以下の行を使用します。
cp ./decomp2dbg/d2d_client.py ~/.d2d.py && echo "source ~/.d2d.py" >> ~/.gdbinit
まず、デコンパイラでデコンパイルサーバを起動します。デコンパイラの通常の解析が完了するのを待ってから起動することをお勧めします。通常解析後、ホットキーCtrl-Shift-Dを使用するか、関連プラグインタブのdecomp2dbg: configureタブを選択することで実行できます。サーバ起動後、デコンパイラに以下のメッセージが表示されるはずです。
[+] Starting XMLRPC server: localhost:3662
[+] Registered decompilation server!
次に、デバッガで以下を実行します。
decompiler connect <decompiler_name>
デコンパイラをVMや別のマシンで実行している場合は、接続先のホストとポートをオプションで指定できます。例:
decompiler connect ida --host 10.211.55.2 --port 3662
すべてのコマンドの使い方は、decompilerコマンドに--helpフラグを付けて確認できます。
初回接続は、バイナリ内のグローバル変数の量によって登録に最大30秒かかることがあります。すべて正常なら、次のように表示されます。
[+] Connected to decompiler!
ライブラリに対してdecomp2dbgを使用している場合(つまり、デバッガがアタッチしているメインバイナリがソースを取得したいバイナリではない場合)、READMEの「Advanced Usage - Shared Libs」セクションを参照してください。
ブレークポイントイベントが発生するたびに、デコンパイル文が表示され、ブレークアドレスに対応する行が強調表示されます。
デコンパイルから得られた関数とグローバル変数が、通常のソースレベルのシンボルと同様にGDBにマッピングされます。つまり、通常のGDBコマンド(printやexamineなど)がネイティブに動作します。
b sub_46340
x/10i sub_46340
p dword_267A2C
x dword_267A2C
関数内に局所的に格納される一部の変数はスタック変数です。スタックやレジスタにマッピング可能な変数については、便宜変数としてインポートします。通常のGDBの便宜変数と同様に内容を確認できます。
p $v4
スタック変数は常にスタック上のアドレスを保持します。そのスタック変数の実際の値を確認するには、単に変数をデリファレンスします。
x $v4
これは関数引数にも該当する場合があります(動作は状況によります)。
p $a1
注意:この場合の$v4は、同じ関数内にいる間だけマッピングされます。関数を離れると、マッピングが解除されるか、別の値に再マッピングされる可能性があります。
メインバイナリ以外のメモリ領域(共有ライブラリのデバッグ時など)のデコンパイル(およびシンボル)を表示したい場合は、追加の手順が必要です。現在、d2dは一度に1つのデコンパイラとの接続しかサポートしていないため、ライブラリ以外のデコンパイラが接続されている場合は、それを切断する必要があります。
共有ライブラリ用にd2dサーバを実行しているデコンパイラを通常通りセットアップした後、このライブラリのベースアドレスと終了アドレスを手動で設定する必要があります。
decompiler connect ida --base-addr-start 0x00007ffff7452000 --base-addr-end 0x00007ffff766d000
ライブラリがメモリ内にロードされているベースアドレスを調べるには、GEFのvmmapコマンドなどを使用して、メモリ空間内でライブラリ名を検索することをお勧めします。この手動で設定したアドレスで接続すると、通常のd2dと同様にシンボルが機能するようになります。デコンパイルは、このアドレス範囲内にいる場合にのみ画面に表示されます。