Q : なぜさらに別の逆コンパイラ、特に機能不全の逆コンパイラが必要なのでしょうか?
A : 悲しい現実ですが、世にあるほとんどの逆コンパイラは機能不全に陥っています。多くは簡単な構造を逆コンパイルできず、他のものはより高度な構造を逆コンパイルできず、それらに対処できるように見えるものでも、退屈なアーキテクチャと OS のみをサポートすることで機能不全に陥ります。そして、ほとんどすべてのコードは、調整や新しいアーキテクチャの追加が複雑になるような方法で書かれています。逆コンパイラはリバース エンジニアリング用のツールですが、皮肉なことに、一般的な逆コンパイラを生産的に使用したり、ニーズに合わせて使用したりしたい場合は、まず逆コンパイラ自体をリバース エンジニアリングする必要があり、それには簡単に数か月 (または数年) かかることがあります。 。
逆コンパイラ (およびあらゆるプログラム変換フレームワーク) の中心部分は中間表現 (IR) です。逆コンパイラは IR で動作し、それを入力として受け取る必要があり、特定のアーキテクチャのアセンブラからこの IR への変換は逆コンパイラから十分に分離される必要があります。そうしないと、別のアーキテクチャのサポートを追加するのに並外れた労力がかかります (結果的に制限が生じます)。逆コンパイラのユーザーベース)。
逆コンパイルは複雑なタスクであるため、逆コンパイルのプロセスを簡単に理解できる必要があります。これは、逆コンパイラーによって使用される IR が人間に優しいものである必要があることを意味します。たとえば、プログラマーに馴染みのある構文を使用し、一般的なマシン アセンブラーにできるだけ直接マッピングするなどです。
上記の要件は、それ自体で非常に明らかです。そうでない場合は、その問題に関する書籍から学ぶことができます。たとえば、次のとおりです。
「コンパイラ作成者には、人間が IR プログラムを簡単かつ直接に検査できるメカニズムも必要です。自己利益のために、コンパイラ作成者はこの最後の点に注意を払う必要があります。」
(Keith Cooper、Linda Torczon、「Engineering a Compiler」)
ただし、オープンソースのプロジェクトを含む逆コンパイラー プロジェクトは、これらの要件に日常的に違反しています。これらのプロジェクトは、特定のマシン アーキテクチャと密接に結合されており、IR のフィードを許可しておらず、多くの場合、ユーザーにまったく公開または文書化されていません。
ScratchABlock は、そのような慣行に「ノー」を突き付け、上記の要件に基づいて逆コンパイル フレームワークを開発する試みです。 ScratchABlock は学習/研究プロジェクトと見なすことができ、他のプロジェクトに対する善意や批判を超えて、現時点では、またはおそらくまったく、一般のユーザーにはあまり多くを提供しない可能性があることに注意してください。もちろん、さまざまな面で批判される可能性もあります。
ScratchABlock は、GNU General Public License v3 (GPLv3) の条件に基づいてリリースされています。
ScratchABlock は Python3 言語で書かれており、バージョン 3.3 以降でテストされていますが、3.2 以下でも動作する可能性があります (レガシー Python2 バージョンでは動作しません)。いくつかの依存関係があります。
Debian/Ubuntu Linux では、これらはsudo apt-get install python3-yaml python3-nose
でインストールできます。あるいは、Python 独自のpip
パッケージ マネージャー (どの OS でも機能するはずです) を介してこれらをインストールすることもできます: pip3 install -r requirements.txt
。
ScratchABlock は、 PseudoCアセンブラを IR として使用します。使い慣れた C 言語の構文を可能な限り使用して表現されたアセンブラ言語です。このアイデアは、C プログラマーなら誰でも直感的に理解できる (例) というものですが、PseudoC をより正式に文書化する取り組みが継続的に行われています。
ドキュメントの前のセクションで説明した要件に基づいて、よく知られた「Unix パラダイム」に従って、ScratchABlock は「1 つのこと」、つまり PseudoC プログラムの分析と変換を実行し、特定のアーキテクチャの機械語命令の変換には明示的に関与していないことに注意してください。 (少なくとも現時点では) PseudoC に変換します。つまり、ScratchABlock は特定のコンバーター/リフターの使用を強制するものではなく、好きなものを使用できます。注意: 使用するにはそれが必要です。この点に関するヒントについては、ドキュメントの最後を参照してください。
ソース コードとインターフェイス スクリプトはリポジトリのルートにあります。最も重要なスクリプトは次のとおりです。
apply_xform.py
- 中心的なドライバーで、一連の変換 (または一般に、高レベルの分析/変換スクリプト) を単一のファイルまたはファイルのディレクトリ (「プロジェクト ディレクトリ」) に適用できます。
inter_dataflow.py
- プロシージャ間 (グローバル) データフロー分析ドライバー (WIP)。
script_*.py
- apply_xform.py
の高レベル分析/変換スクリプト ( --script
スイッチ)。
script_i_*.py
- inter_dataflow.py
の分析スクリプト。
run_tests
- 回帰テストスイートのランナー。テストスイートの大部分は高レベルであり、ファイルにさまざまなパスを指定して apply_xform.py を実行し、予想される結果を確認することで構成されます。
リポジトリの他のサブディレクトリ:
tests_unit
- Python で書かれた Python モジュールの古典的な単体テスト。
tests
- メインのテストスイート。本質的には統合的ですが、通常は 1 つの単純なファイルで 1 つのパスをテストするため、単体テストの哲学に従います。テストは PseudoC 入力ファイルとして表され、期待される結果は、基本ブロックの注釈と (該当する場合) .dot 形式の CFG を備えた PseudoC として表されます。これらのテストケースを見て、変更を試み、結果を見ることが、ScratchABlock がどのように機能するかを学ぶ最良の方法です。
docs
- 増え続けるドキュメントのコレクション。たとえば、ScratchABlock の中間表現 (IR) として機能する PseudoC アセンブラー言語の仕様と、別の既存の IR が選択されなかった理由の調査があります。
ScratchABlock の現在のアプローチは、プログラムの分析と変換のために比較的疎結合のアルゴリズム (「パス」) のコレクションを成長させ、それらをテストでカバーし、ユーザーがそれらに簡単にアクセスできるようにすることです。逆コンパイルの魔法は、これらのアルゴリズムを正しい順序と正しい回数で適用することで構成されます。次に、逆コンパイルのパフォーマンスを向上させるために、これらのパスでは通常、より密な結合が必要になります。上で説明したパスのインベントリを実装した後の次の優先事項は、これらの方向を探索することです。
ScratchABlock によって実装されるアルゴリズムと変換:
グラフアルゴリズム:
静的単一割り当てフォーム (SSA):
データフロー分析:
伝搬:
デッドコード除去 (DCE)
書き換え:
制御フローの構造:
出力形式:
ScratchABlock のパートナー ツールは ScratchABit です。これは、データからのコードの分離や関数境界の識別など、逆コンパイル プロセスの最も低レベルのタスクを実行することを目的とした対話型の逆アセンブラです。 ScratchABit は通常、ネイティブ アーキテクチャのアセンブラ構文で動作しますが、一部のアーキテクチャ (通常は忠実な RISC) では、適切なプラグインが利用可能な場合は、ScratchABlock への入力として機能する疑似 C 構文を出力できます。