25

「逆コンパイル」という言葉が何度か使われているのを聞いたことがありますが、それがどのように機能するのか非常に興味を持ち始めています。

私はそれがどのように機能するかについて非常に一般的な考えを持っています。アプリケーションをリバースエンジニアリングして、どの機能が使用されているかを確認しますが、それ以上のことはよくわかりません。

「逆アセンブラ」という言葉も聞いたことがありますが、逆アセンブラと逆コンパイラの違いは何ですか?

だから私の質問を要約すると:何かを逆コンパイルするプロセスには正確に何が関係していますか?それは通常どのように行われますか?プロセスはどれくらい複雑/簡単ですか?正確なコードを生成できますか?そして、逆コンパイラーと逆アセンブラーの違いは何ですか?

4

2 に答える 2

26

Hex- RaysDecompilerの作者であるIlfakGuilfanovが、あるコンで彼の逆コンパイラーの内部動作についてスピーチをしました。ここにホワイトペーパープレゼンテーションがあります。これは、逆コンパイラーを構築する際のすべての困難と、それをすべて機能させる方法の概要を説明しています。

それとは別に、クリスティーナ・シフエンテスの古典的な博士論文など、かなり古い論文がいくつかあります。

複雑さに関しては、すべての「逆コンパイル」は、バイナリの言語と実行時間に依存します。たとえば、.NETとJavaの逆コンパイルは、成功率が非常に高い(元のソースを生成する)無料の逆コンパイラが利用可能であるため、「完了」と見なされます。ただし、これは、これらのランタイムが使用する仮想マシンの非常に特殊な性質が原因です。

C、C ++、Obj-C、Delphi、Pascalなどの真にコンパイルされた言語に関しては、タスクははるかに複雑になります。詳細については、上記の論文をお読みください。

逆アセンブラと逆コンパイラの違いは何ですか?

バイナリプログラム(実行可能ファイル、DLLライブラリなど)がある場合、それはプロセッサ命令で構成されます。これらの命令の言語は、アセンブリ(またはアセンブラ)と呼ばれます。バイナリでは、これらの命令はバイナリエンコードされているため、プロセッサは直接実行できます。逆アセンブラはこのバイナリコードを取得し、テキスト表現に変換します。この翻訳は通常1対1です。つまり、1つの命令が1行のテキストとして表示されます。このタスクは複雑ですが、簡単です。プログラムは、すべての異なる命令と、それらがバイナリでどのように表されるかを知る必要があります。

一方、逆コンパイラーははるかに難しいタスクを実行します。バイナリコードまたは逆アセンブラ出力(1対1であるため、基本的に同じ)のいずれかを受け取り、高レベルのコードを生成します。例を示しましょう。このC関数があるとしましょう:

int twotimes(int a) {
    return a * 2;
}

コンパイルすると、コンパイラは最初にその関数のアセンブリファイルを生成します。これは次のようになります。

_twotimes:
    SHL EAX, 1
    RET

(最初の行は単なるラベルであり、実際の命令ではありませんSHL。左シフト操作を実行します。これは、2をすばやく乗算RETすることで、関数が完了したことを意味します)。結果のバイナリでは、次のようになります。

08 6A CF 45 37 1A

(私はそれを作りました、本当のバイナリ命令ではありません)。これで、逆アセンブラがバイナリ形式からアセンブリ形式に移動することがわかりました。逆コンパイラーは、アセンブリーフォームからCコード(または他の高級言語)に移動します。

于 2012-04-25T07:43:38.967 に答える
4

逆コンパイルは本質的にコンパイルの逆です。つまり、オブジェクトコード(バイナリ)を取得し、そこからソースコードを再作成しようとします。

逆コンパイルは、ソースコードの構造を確認するために使用できるオブジェクトコードに残っているアーティファクトに依存します。

C / C ++では、逆コンパイルプロセスを支援するために残されたものがあまりないため、非常に困難です。ただし、JavaやC#、および仮想マシンを対象とするその他の言語では、言語がオブジェクトコード内にさらに多くのヒントを残すため、逆コンパイルが容易になる可能性があります。

于 2012-04-25T07:32:07.323 に答える