技術屋さんなので、プログラマーなのでそれらしいネタで情報提供しましょう、ってことで始めた 「.NETで○○○を試してみる」シリーズ 第2弾。

第1弾はソフトウェア工学なんてお題目を掲げたものの、終始ソフトウェアの機能紹介と用語解説に甘んじてたようにも見える。
いや、ソースコードも書いていたし、一応C#**、.NET Framework**っていう範疇ではありましたが。

今回は難読化に挑戦します。

Explanation

まずは、難読化が何か、というところから。

そもそも、.NET 用に作成されたプログラムは、CやC++で作成されたプログラムに比べてリバース エンジニアリングが極めて容易です。
なぜなら、ソースコードがコンパイルされて作成された実行ファイルやアセンブリは、その時点ではネイティブコードに変換されていないためです。
C#やVisual Basic .NETで記述されたソースコードは、コンパイルが実行されると、MSIL (Microsoft Intermediate Language) に変換されます。
このMSILはマシン語であるネイティブコードよりも高度(ここで言う高度とは機能的な意味ではなく、人間に理解しやすいかどうか)であり、マシン語固有の知識が不要であるため解析が容易です。
CやC++で記述され、コンパイルによって生成されたプログラムに比べてリバース エンジニアリングが極めて容易、と言う理由はここにあります。

そこで、ソースコードからMSILに変換する段階で、処理結果に影響を与えないようにロジックの理解度を低下させます。
たとえば、変数名、メソッド名、クラス名等人間の理解力を補佐する情報を空白や記号に置換したりする等の手法が挙げられます。
これが難読化です。あくまで、読みにくくする、というのが目標ですので、人間には解読不可能だ!!!、リバースエンジニアリング不可能にする!!、とかそういうのはお門違いです。

Microsoft難読化が必要な理由というページで下記のように述べています。

NET 用に作成されたプログラムは、リバース エンジニアリングが簡単です。これは .NET のデザインに不備があるからではありません。最新の中間コンパイル言語が採用されているからです。.NET は表出的なファイル構文を使用して実行可能コード、すなわち MSIL (Microsoft Intermediate Language) を配信します。このような中間ファイルは、バイナリのマシン語コードよりも高度なもので、直接表示でき、最終的に理解可能な識別子やアルゴリズムを積み重ねたものです。判読性を高め、柔軟性と拡張性を持たせながら、同時に重要な部分を難読化することは、もちろん容易なことではありません。
.NET 逆コンパイラは誰でも無償で入手でき、これを使用してコードを簡単にリバース エンジニアリングできます。誰でもすぐに、ライセンス供与されたコード、コピー保護メカニズム、所有権を有するビジネス ロジックなどを、(合法的であるかどうかは別として) かなり判別しやすい状態にすることができます。どのような目的であれ、ソフトウェアの詳細を隅々まで調べることができるため、セキュリティ上の欠陥を探して利用したり、ユニークなアイデアを盗んだり、プログラムをクラックすることなども可能です。
これが必ずしもリスク、または重大な問題になるわけではありません。知的財産について懸念のある組織は、.NET プラットフォームを考える際、リバース エンジニアリングを防ぐためのソリューションが存在することを知っておく必要があります。難読化は、アセンブリ内のシンボルの名前をシームレスに変更する技法であり、その他にも逆コンパイラを妨害する対策を備えています。難読化を正しく適用すると、アプリケーションはそのままにして、さまざまな規模の逆コンパイルに対する保護を高めることができます。

Microsoft自身はこのように警鐘を鳴らしてはいますが、Microsoftは難読化というソリューションを提供してはいません。
個人的には、MSILに対して一番理解がある(当たり前ですが)Microsoftが難読化の機能をVisualStudioなりに備えておくのが一番だと思いますが、そうなっていないなら仕方ありません。

そういうわけですので、難読化を行うための手段は3通りです。

  1. コーディング中に変数名、クラス名、メソッド名を記号や空白に置き換える。
  2. 特許が含まれるようなロジックはアンマネージドなアセンブリに退避させ P/Invoke呼び出し で利用する。
  3. 難読化ツールを利用する。

1. まぁ、どう考えてもないでしょう。コーディングやコードレビューの効率が著しく低下しますが、そこに膨大な工数を費やせる予算潤沢なプロジェクトならありでしょう。まぁ保守する人間が絶叫すること間違いないでしょうが..

2. これは現実路線でしょう。というか特許云々は置いておいて、処理速度の関係からこうするソフトウェアもありますので、お馴染みの手法と言えばそうだと言えますが、既存の特許ロジックが.NETで作られている場合に、C++やCにポーティングする工数を考えるとこれは次善策でしょう。

3. 今回の本命です。というかここに来るまでが長い。変数名等の難読化やリテラル文字列の暗号化など様々な機能を提供してくれます。が、ツールのコストは無料のものから数十万円と開きがあります。予算や顧客からの要求に応じて検討しましょう。

Introduce

現在、難読化機能を提供しているツールは調べた限り以下になります。
無償

この中から、Webサイトの印象や評判やI/Fなどから選ぶと

  1. Eazfuscator.NET
  2. Express Obfuscator
  3. NanDoKu
  4. Babel.NET
  5. CodeFort
  6. Spices .Net Obfuscator
  7. SmartAssembly
  8. Dotfuscator

というのが個人的な順位付けになります。予算があるなら、Dotfuscatorとか選ぶんでしょうけど…

Conclusion

というわけで、次回は個人的ランキング1位に輝いた Eazfuscator.NET を使って難読化を行っていきたいと思います。
Web上でも利用しているというか使い方を説明している方が、UROBOROS XNA様くらいしかいなかったので、私が人柱有意義な情報提供を行える人物になろうと思います。

あ、他のソフトについては未定です。SmartAssemblyの使用レポをしろ!等という意見は受け付けません(お財布の暖かさ的な理由で)