ソースコードがないのに、ソースコードが公開されてしまう!?
もし、開発プロジェクトに対し「実行ファイルには常にソースコードを添付すること」という条件が課せられたとしたら、「なんて非常識な!」と、とまどうプロジェクトリーダーや関係者は多いでしょう。オープンソース・プロジェクトならばともかく、実行ファイルの中にはユーザーの個人情報を処理するコード、IDやパスワードというセンシティブな情報を扱う部分、時間をかけて開発した高度な分析ロジックなどがあり、ソースコードが開示されれば保護すべきものが保護できなくなってしまうおそれがあります。
企業のコンプライアンスや情報セキュリティが重視される昨今では、ソースコードを厳重に管理し、勝手に持ち出したり、逆に個人コンピューターの持ち込みを厳しく制限している企業も少なくありません。特にパッケージソフトやゲームソフトにおけるソースコード保護の重要性は言うまでもないでしょう。
しかし、.NET Frameworkで開発されたアプリケーションは、ソースコードがなくても、アプリケーション(実行ファイル)から元のソースコードへ、容易に逆コンパイルできてしまいます。.NETでは、「アセンブリ」と呼ばれる構成単位が、相互作用できる情報(メタデータ)を保持しているため、これを使って内部を解析しやすくなっているのです (注1)。
Javaでも同様です。逆に、C/C++言語用の逆コンパイルツールは存在しますが、それほど高精度ではありません。
逆コンパイラ技術の進歩と脅威
現在、逆コンパイラの技術がどのように進化しているかを、簡単なプログラムを使って示します。リスト1は、簡単なコンソールアプリケーションを抜粋したものです。
static void CalcRank() { Array.Clear(count, 0, MAXNUM); // 得点別配列をクリア for (int i = 0; i < MAXNUM; i++) // 全員に対し得点別の配列をカウントアップ count[score[i]]++; int j = 0; // 最高点の人の順位(0基準) for (int i = MAXSCORE; i >= 0; i--) // 最高点から順に順位づけ { ptsrank[i] = j; j += count[i]; } for (int i = 0; i < MAXNUM; i++) rank[i] = ptsrank[score[i]]; // 得点別順位を全員に割り当てる }
ここでは、.NET Reflectorという.NET用の逆コンパイラツールを使います 。図1は、リスト1で生成された実行ファイルを逆コンパイルしている様子です。ここではデバッグ情報を持たないReleaseビルド版を扱っていますが、デバッグ情報が残っていれば定数シンボルやローカル変数の名前を含めて、さらに正確な逆コンパイルリストが得られます。しかも、逆コンパイル時には言語を「C#」や「Visual Basic」など好きな言語を選択できます。
コンパイラは、選んだ言語の文法に沿ってプログラムコードから.NET用のコード(IL、中間言語)を生成します。この変換の仕方を分析し、生成されたコードから元のプログラムを推測するのが逆コンパイラの仕組みです。コード生成のパターン分析は着実に進歩しており、LINQやラムダ式を使う最新版の.NET Frameworkにも対応しています。また、.NET Frameworkが、プログラミングの柔軟性を高めるために、アセンブリ中にさまざまなメタデータを埋め込んでいることも精度の高い解析に役立っています。
C#やVisual Basicのような言語レベルに復元されてしまうと、プログラムの理解は容易です。とくに「コメントがなくても分かりやすいプログラム」を書いている場合は、ソースコードが公開されているのと似たような状態だと言えます。つまり、開発プロジェクトの中で、ソースコードの持ち出しを厳しく制限していても、知的財産の保護や情報セキュリティの面でリスクにさらされてしまうのです。
.NET Reflectorの単体版は無料です。開発中のプロジェクトがあれば、手元の実行ファイルで逆コンパイルを試してみてもよいでしょう。おそらく想像以上に正確なソースコードが得られるはずです。