この実験的な Ghidra プラグインを使用すると、ネイティブ pcode エミュレーションを簡単に処理できます。スクリプトはもう必要ありません。Ghidra から直接使用するだけです。これは、一般的なエミュレータではサポートされていないさまざまな特殊なプロセッサを操作する場合に特に役立ちます。
プロセッサ/VM がリバース エンジニアリング用に Ghidra でサポートされている場合は、エミュレートできます。たとえば、eBPF 命令エミュレーションを以下に示します。
本質的に、プラグインはghidra.app.emulator
パッケージ内のクラスの拡張ラッパーです。実装されたものは次のとおりです。
PCode エミュレーションは理想的には統合を意味しますが、ほとんどのプロセッサーは独自のアプローチを必要とします。問題が発生した場合は、お気軽に報告してください。本当はすべてのプロセッサをテストしたいのですが、それはほとんど不可能です。
すべてのプラグイン ウィンドウが含まれます: スタック ビュー、レジスタ、ブレークポイント ビュー、メイン ウィンドウ。
エミュレーションの開始と終了、ブレークポイントを設定し、変更されたバイトをエミュレータの状態に適用するためのホットキーが含まれています。
必要に応じてレジスタを変更します。リンク レジスタ (緑の矢印) を設定すると、エミュレータがどのレジスタにリターン アドレスが含まれているかを理解するのに役立ちます。プラグインは、スタック、lr レジスタ、AARCH64、および MIPS レジスタを介してプラグインがどのように動作するかを認識しています。エキゾチックなものをお持ちの場合は、リンクレジスタを選択してボタンを押してください。
СodeBrowser でプログラムを開くと、GhidraEmu はスタック領域を自動的にマップします。スタック ポインタはスタック範囲の中央に設定されます。これにより、スタック フレームの上部または下部に値を設定できるようになります。更新またはリセット時にフリーズが発生した場合は、スクロールしてください。エミュレーション プロセス中に、プログラムがスタック用にさらに多くのスペースを必要とする場合、プラグインはそれを自動的に割り当てます。
エミュレーション中にバイトが変更された場合は、従来の ByteViewer で確認できます。 「リセット」ボタンを押すと元の値にリセットされますので、ご安心ください。
変更を行った場合は、変更されたバイトについてエミュレータに通知します (スタックは自動的に更新されます。その必要はありません)。変更後、それらを選択し(緑色になります)、このオプションを押します(またはホットキー「M」を使用します)。
ここでプラグインは出力情報を出力します。たとえば、次のようなエミュレーション エラー メッセージが表示されます。
「ジャンプ オーバー」機能を使用すると、何らかの理由で現在の命令をエミュレートしたくない場合に、1 命令先にジャンプできます。初期化されていないメモリの読み取り試行が検出されるとエミュレーション プロセスが中止されるため、この機能を使用するとそれをバイパスできます。例を見てみましょう。これは、多くの x86_64 プログラムの最初の命令の 1 つであるカナリア スタックの保存です。
MOV RAX, qword ptr FS:[0x28]
ちょっとごまかしてPC値を上げて飛び越えてみます。これを行うには、エミュレートしたくない命令で停止し、 J
ホットキーを押します。そうしないと、さらにステップを進めると、初期化されていないメモリ読み取りエラーが発生します。
サブルーチンにつながる命令 (内部呼び出し) で停止し、次の命令までのすべてをエミュレートしたい場合 (古典的な「ステップ オーバー」)、 F6
ホットキーを押すと、確実に実行されます。
考慮すべき重要な点がいくつかあります:
gradle を使用して拡張機能をビルドします: GHIDRA_INSTALL_DIR=${GHIDRA_HOME} gradle
使用し、Ghidra を使用してインストールします: File → Install Extensions...
CodeBrowser で、 File → Configure → Miscellaneous
に移動し、GhidraEmu プラグインのチェックボックスを選択します。
プラグインの使用中にバグが発生したり、改善のアイデアがありますか?恥ずかしがらずに新しい問題を開いてください。解決します。
EmulatorHelper の制限により、別のプログラム領域を使用することはできません。したがって、たとえば外部共有ライブラリはプログラムのメモリ空間について知ることはありませんし、その逆も同様です。したがって、1 つのメモリ空間を持つ 1 つのプロセスとしてエミュレートすることはできません。ここで何か足りないことがあればお知らせください。