ビルドとデバッグ
アセンブリのリンク
Dotfuscator は複数の入力アセンブリを 1 つまたは複数の出力アセンブリに結合することができます。 アセンブリのリンクを使用すると、特に、名前の変更および不要なコードの除去と併用した場合にはアプリケーションのサイズをさらに縮小することができ、配置シナリオを簡素化することができます。
たとえば、A、B、C、D、および E という入力アセンブリがあった場合、アセンブリ A、B、C を F という名前のアセンブリとしてリンクし、 同時にアセンブリ D と E を G という名前のアセンブリとしてリンクすることができます。 このリンクの注意点は、同じ入力アセンブリを複数の出力アセンブリにリンクできないということだけです。
アセンブリのリンク機能は Dotfuscator のその他の機能と完全に統合されているため、コードの難読化、未使用の型、メソッド、フィールドの除去、1 つのアセンブリへのリンクを 1 ステップで実行できます。
リンク対象のアセンブリを参照する他の入力アセンブリがある場合でも、アセンブリおよび型の参照の変更は透過的に行われ、出力アセンブリどうしは正しく連携します。
制限事項
Managed C++ アセンブリでは、リンク機能がサポートされていません。
自動入力管理モードでは、リンク機能がサポートされていません。
Dotfuscator は、XAML 内のパッケージ URI に指定されているアセンブリ名を更新しません。そのため、XAML を使用しているアプリケーションのリンクは、通常避けてください。
増分難読化
アプリケーションに対し何度も Dotfuscator を実行するような場合には、増分難読化を使用することによって一貫性のある名前変更規則を維持することができます。 名前割り当てファイルを参照することで、型やメンバーの名前を長期にわたり一貫して変更することができます。 たとえば、従属グループの構成要素となるファイルのサブセットを再配布するとか、リソースに制約された環境でアセンブリの難読化を順次実行するなどの複合的なシナリオでは、名前の変更が一貫していることが望まれます。 この機能を適切に活用すれば、アプリケーション内の一部のアセンブリのみ再配布が必要な場合には、難読化処理がより迅速になるという利点も生じます。
あるアプリケーションに対し Dotfuscator を使用し、そのアプリケーションを顧客に配布するというシナリオについて考えてみましょう。 さて、アセンブリの 1 つに変更を加え、それをアップデートとして提供したいとします。 当該アプリケーションに対し Dotfuscator を単純に再実行した場合、以前からあるクラスやメソッドの名前が前の変更結果とは異なるものにされてしまい、アプリケーション全体を顧客に再配布しなければならなくなる可能性があります。 Dotfuscator の増分難読化を使用すれば、変更したアセンブリを公開できるため、同じ名前を保持できます。
順次ビルドのシナリオでも増分難読化が有用です。増分難読化によって、大規模なアプリケーションの難読化を、もっと処理しやすいアセンブリ グループの小規模な難読化に分解することが可能になります。
3 つのファイル、A.exe
、B.dll
、および C.dll
で構成される仮想アプリケーションがあり、A
は B
を、B
は C
を参照している場合、このアプリケーションは次のようにビルドされている可能性があります。最初に C.dll
を難読化し、次に C.dll
の実行で生成された割り当てファイルを使って B.dll
を増分難読化してから、最後に B.dll
からの割り当てファイルを使って A.exe
を難読化しているかもしれません。
増分難読化には、再利用する必要のある名前を含んでいる入力割り当てファイルが必要です。 ファイルの形式は、Dotfuscator を実行するごとに生成される出力割り当てファイルと同じです。 最良の方法は、アプリケーションのビルドをリリースするごとに、出力割り当てファイルのコピーを安全な場所、 たとえばバージョン管理などに保存しておくことです。 そうすれば、増分更新が必要になったときはいつでも、そのファイルを入力割り当てファイルとして使用できます。
増分難読化を使用して実行する場合、構成に含まれるアセンブリがすべて必要なわけではなくても、Dotfuscator はアプリケーションのすべてのアセンブリへのアクセス権を持っていなければなりません。 それらのアセンブリは、Dotfuscator が参照アセンブリを探すために使用する調査規則と同じ規則によって見つかりさえすればよいです。
難読化されたコードのデバッグ
難読化の重大な欠点は、難読化処理されたアプリケーションの管理やトラブルシューティングの作業が困難になるということです。 特に、制御フローの難読化を実行すると、アセンブリ内の命令の順序がソース言語のコマンドの順序と一致しなくなるため、デバッグがかなり困難になります。 名前の変更による難読化を実行すると、デバッグがより困難になるうえ、さらに、スタック トレース(リリースされたアプリを使用する顧客によって報告されるものなど)で難読化された名前が使用されるようになります。
幸いにも、Dotfuscator には、難読化処理されたアプリケーションをデバッグしたり、そのアプリケーションのスタック トレースを解釈したりすることができる機能が備わっています。
デバッグ シンボル
Dotfuscator には、保護されたアセンブリに対してデバッグ シンボルを出力する機能があり、たとえば PDB ファイルを作成できます。 これらのシンボルを使用すると、デバッガーによって、難読化されたアセンブリをステップ スルーしたり、元のソース コードに対してブレークポイントをヒットしたりすることが可能になります。
この機能は、新しい Dotfuscator 構成ファイルでは既定で有効になります。Visual Studio プロジェクトに Dotfuscator を統合し、アプリケーションを難読化された構成(Release など)でビルドした場合でも、Visual Studio 内でアプリケーションのデバッグを続けることを可能にします。
メモ:アプリケーションをリリースするときに、アプリケーションと一緒に PDB ファイル(または、デバッグ シンボルのその他の形式)を配布しないでください。これらのファイルには、リバース エンジニアリングに役立つ可能性のある、ソース ファイルの情報が含まれています。
スタック トレースの変換
難読化処理されたアセンブリによって出力されるスタック トレースは、元のソース名ではなく難読化された名前を使用します。これにより、顧客から報告された問題の診断が困難になります。 Dotfuscator 構成エディターには、難読化されたスタック トレースをデコードして、元の名前を使用する同等のスタック トレースに戻すためのツールが備わっています。 PreEmptive Solutions は、Dotfuscator をインストールしていない開発者のために、同様の変換を実行できるスタンドアロン ツールの Lucidator を提供しています。
どちらのツールも、難読化中に Dotfuscator によって生成された名前の変更割り当てファイルを必要とするため、後で難読化されたスタック トレースを変換できるよう、アプリケーションをリリースするごとに、このファイルを個人でアーカイブしておく必要があります。
厳密名のアセンブリの難読化
厳密名が付けられたアセンブリはデジタル署名されています。 これにより、署名後にアセンブリが変更されていないかどうかを実行時に確認できます。 署名には SHA1 ハッシュが使用され、ハッシュは RSA 公開/秘密キー ペアの秘密キーで署名されています。 署名と公開キーは、共にアセンブリのメタデータに埋め込まれています。
Dotfuscator はアセンブリを変更してしまうため、Dotfuscator を使ってアセンブリを処理した後に署名を行うことは不可欠です。
Dotfuscator では、このステップを難読化処理の一環として扱います。
難読化後の自動再署名
Dotfuscator では、難読化処理後に厳密名を持つアセンブリを自動的に再署名するため、手動で実行する必要がなくなりました。 Dotfuscator は、既に署名済みのアセンブリを再署名し、遅延署名されているアセンブリの署名プロセスを完了します。
厳密名のアセンブリの再署名
Dotfuscator は、ビルド処理の一環として、既に厳密名が付けられているアセンブリを再署名することができます。 公開/秘密キー ペアを探す場所を Dotfuscator に明示的に知らせるか、または入力アセンブリのカスタム属性(たとえば System.Reflection.AssemblyKeyFileAttribute)で指定される場所を使用することができます。
以下に、XML 構成ファイル内で明示的なキー ファイルを使用して再署名を設定する箇所を示します。 カスタム属性によって指定されるキー ファイルはどれも使用されません。
明示的なキー ファイルによる再署名:
<signing>
<resign>
<option>dontuseattributes</option>
<key>
<file dir="c:\temp" name="key.snk" />
</key>
</resign>
...
</signing>
遅延署名されたアセンブリの署名プロセスの完了
入力アセンブリが遅延署名されている場合、Dotfuscator はその署名プロセスを完了することができます。 署名を完了するために必要な秘密キーの場所を Dotfuscator に知らせる必要があります。
以下に、XML 構成ファイル内で明示的なキー ファイルを使用して遅延署名を設定する箇所を示します。
遅延署名:
<signing>
...
<delaysign>
<key>
<file dir="c:\temp" name="key.snk" />
</key>
</delaysign>
</signing>
難読化されたアセンブリの、Authenticode による再署名
Authenticode で署名されたアセンブリは、信頼されたルート証明機関で発行したコード署名証明書によってデジタル署名されます。 これを使用すれば、オペレーティング システムやランタイムがアプリケーションの発行元を特定したり、署名後にアセンブリが変更されたかどうかを判断することができます。 この署名は、コード署名証明書の秘密キーで暗号化されたハッシュです。 署名と公開キーは、共にアセンブリのメタデータに埋め込まれています。
Dotfuscator はアセンブリを変更してしまうため、Dotfuscator を使ってアセンブリを処理した後に Authenticode 署名を行うことは不可欠です。
Dotfuscator の Authenticode のサポートは、使用されるハッシュ関数によって異なります。 SHA-1 による署名は自動で行えますが、SHA-256 による署名は手動で行う必要があります。
自動 SHA-1 署名
Dotfuscator は構成設定に基づいて、SHA-1 を使用して出力アセンブリを再署名することができます。 詳細については、Dotfuscator 構成エディター ページの Authenticode デジタル署名セクションを参照してください。
以下に、Dotfuscator 構成ファイル内で Authenticode 署名を構成している箇所を示します。 署名に使用される Personal Information Exchange(.pfx)ファイルのパスとパスワードの両方が指定されています。
<digitalsigning>
<pfx password="secret123">
<file dir="C:\test" name="authenticode.pfx" />
</pfx>
</digitalsigning>
手動 SHA-256 署名
Dotfuscator は、SHA-256、または SHA-1 を除く他のハッシュ関数を使用した再署名は行いません。 代わりに、ビルド後のイベントを利用して、この種の署名を行うことができます。
SHA-256 による署名のために、ビルド後のイベントを次のように構成することができます。
プログラム
コマンド ライン:
sign /fd sha256 /f [証明書ファイルのパス] /p [証明書パスワード] /tr [証明書のタイムスタンプ サーバーの URL] /as ${dotf.current.out.module}
[証明書ファイルのパス]
には、Dotfuscator 構成ファイルのディレクトリとの相対パスを示す${configdir}
を使用できます。
プログラム パス:Microsoft 署名ツールへの絶対パス。 これは、開発者コマンド プロンプトを開いて
where signtool
と入力することで、調べられます。
各モジュールで実行:はい
以下は、Dotfuscator 構成ファイル内で、ビルド後のイベントを構成している箇所を示します。
<eventlist>
<event type="postbuild">
<option>runoneachmodule</option>
<option>buildsuccessful</option>
<program>
<file dir="[sign tool dir]" name="signtool.exe" />
<environment commandline="sign /fd sha256 /f [証明書ファイル名].pfx /p [証明書パスワード] /tr [タイムスタンプ URL] /as ${dotf.current.out.module}" workingdir="" />
</program>
</event>
</eventlist>
デュアル署名
前述の 2 つのセクションの手順を同時に行えば、SHA-1 と SHA-256 の両方でアセンブリをデュアル署名することができます。
ビルド イベント
Dotfuscator では、ビルド工程の前後に実行するプログラムを指定できます。
ビルド前のイベント
Dotfuscator はそのビルド処理において、他のどの入力アセンブリを処理するよりも前に、ビルド前のイベントによって指定されたプログラムを実行します。
ビルド後のイベント
Dotfuscator はビルド処理の一番最後に、ビルド後のイベントによって指定されたプログラムを実行します。 ビルドが成功した場合のみ、ビルドが失敗した場合のみ、または常時、プログラムを実行するように Dotfuscator に指示できます。 また、出力モジュールごとに 1 回プログラムを実行するよう指示することもできます。
ビルド イベント プロパティ
Dotfuscator のビルド エンジンは、ビルド イベントを構成するときに使用できるプロパティをいくつか公開しています。
プロパティ名 | 説明 |
---|---|
dotf.destination | 出力先ディレクトリへのパス。 |
dotf.inputmap.xml | 入力割り当てファイルが指定されている場合、そのファイルの完全なパスと名前。 |
dotf.outputmap.xml | 出力割り当てファイルが指定されている場合、そのファイルの完全なパスと名前。 |
dotf.removal.xml | XML 形式の除去ファイルが指定されている場合、そのファイルの完全なパスと名前。 |
dotf.config.file | 現在の構成ファイルの完全なパス。 |
dotf.current.out.module | 現在の出力モジュールの完全なパス。ビルド後のイベントで、出力モジュールごとにプログラムを呼び出す場合に使用されます。 |
dotf.current.in.module | 現在の入力モジュールの完全なパス。ビルド後のイベントで、出力モジュールごとにプログラムを呼び出す場合に使用されます。 |
ビルド イベントでは、外部プロパティ(環境変数や、コマンド ラインで -p
オプションを使って渡されるプロパティ)およびユーザー定義の構成プロパティも参照できます。