ビルドとデバッグ
アセンブリのリンク
Dotfuscator は複数の入力アセンブリを 1 つまたは複数の出力アセンブリに結合することができます。 アセンブリのリンクを使用すると、特に、名前の変更および不要なコードの除去と併用した場合にはアプリケーションのサイズをさらに縮小することができ、配置シナリオを簡素化することができます。
たとえば、A、B、C、D、および E という入力アセンブリがあった場合、アセンブリ A、B、C を F という名前のアセンブリとしてリンクし、 同時にアセンブリ D と E を G という名前のアセンブリとしてリンクすることができます。 このリンクの注意点は、同じ入力アセンブリを複数の出力アセンブリにリンクできないということだけです。
アセンブリのリンク機能は Dotfuscator のその他の機能と完全に統合されているため、コードの難読化、未使用の型、メソッド、フィールドの除去、1 つのアセンブリへのリンクを 1 ステップで実行できます。
リンク対象のアセンブリを参照する他の入力アセンブリがある場合でも、アセンブリおよび型の参照の変更は透過的に行われ、出力アセンブリどうしは正しく連携します。
制限事項
Managed C++ アセンブリでは、リンク機能がサポートされていません。
自動入力管理モードでは、リンク機能がサポートされていません。
Dotfuscator は、XAML 内のパッケージ URI に指定されているアセンブリ名を更新しません。そのため、XAML を使用しているアプリケーションのリンクは、通常避けてください。
.NET Core の場合、Dotfuscator はリンク後に *.deps.json ファイルを更新しません。
増分難読化
アプリケーションに対し何度も 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 内でアプリケーションのデバッグを続けることを可能にします。
スタック トレースの変換
難読化処理されたアセンブリによって出力されるスタック トレースは、元のソース名ではなく難読化された名前を使用します。これにより、顧客から報告された問題の診断が困難になります。 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>
ビルド イベント
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
オプションを使って渡されるプロパティ)およびユーザー定義の構成プロパティも参照できます。
外部ツールの検索
Dotfuscator は ILdasm と ILasm を使用してアセンブリを処理します。 ILdasm は、.NET の IL(Intermediate Language:中間言語)逆アセンブラーで、ILasm は IL アセンブラーです。 Dotfuscator ではこれらのツールを 2 つの方法で入手できます。
.NET Framework から。 Dotfuscator が Windows で実行している場合、ILdasm はインストールされる .NET Framework SDK によって提供され、ILasm はインストール される .NET Framework ランタイムによって提供されます。 これらのツールが存在すれば、既知のインストール場所とレジストリ キーを使用して自動的に見つかります。
✅ これらのツールは特定の追加機能をサポートします。
❌ これらのツールは macOS または Linux では実行しません。Windows でのみ実行します。
❌ これらのツールは、.NET Core 3.x や .NET 5 など、より新しいフレームワークをターゲットとするアセンブリをサポートしません。
NuGet から。 Dotfuscator は NuGet を使用して ILdasm と ILasm の両方を取得します。 これらのパッケージの取得と使用はビルド プロセスの一環として自動的に処理されます。
既定の NuGet ソースが利用できない場合は、NuGet ソースと資格情報の作成に使用できる環境変数があります。
DOT_ILTOOLS_CORE_NUGETFEED
は NuGet ソース フィードを設定します。DOT_ILTOOLS_CORE_NUGET_USERNAME
およびDOT_ILTOOLS_CORE_NUGET_PASSWORD
は、NuGet ソース フィード用の資格情報を設定します。
❌ これらのツールは特定の追加機能をサポートしません。
✅ これらのツールは Windows と同様、macOS および Linux で実行します。
✅ これらのツールは、.NET Core 3.x や .NET 5 など、より新しいフレームワークをターゲットとするアセンブリをサポートします。
通常、Dotfuscator はアセンブリのターゲット フレームワークに基づいて、各アセンブリに最適なツールを自動的に選択します。 ただし、Dotfuscator は特別に名前付けされたプロパティでこの動作を上書きすることができます。プロパティで、ファイル システム上の特定の ILdasm および ILasm 実行可能ファイルを使用するよう Dotfuscator に指示できます。
各入力アセンブリ用の ILdasm および ILasm を見つけるために Dotfuscator が使用する完全なアルゴリズムは次のとおりです。
Dotfuscator はアセンブリのメタデータ バージョンを判断します。
多くの場合、このバージョンは
4.0.30319
です。ただし、古いバージョンの Windows 専用 .NET Framework をターゲットとするアセンブリは、これより小さいバージョン番号になるかもしれません。 たとえば、.NET Framework 3.5 をターゲットとするアセンブリのメタデータ バージョンは
2.0.50727
となるはすです。診断目的の場合は、ご自身で ILdasm を使用してアセンブリのメタデータ バージョンを判断します。
// Metadata version:
コメントを探します(GUI を使用している場合、このコメントは "MANIFEST" セクションに表示されます)。
Dotfuscator は、手順 1 で見つかったメタデータ バージョンに関連するユーザー指定のプロパティを調べます。 関連するプロパティが定義されている場合、Dotfuscator は、通常は以下の手順で説明する規則に基づいて使用されるツールではなく、指定された実行可能ファイルを使用します。
Dotfuscator が macOS また Linux で実行している場合は、NuGet からツールを入手するので、この手順でアルゴリズムを終了します。 Dotfuscator が Windows で実行している場合には、このアルゴリズムの手順 4 以降が適用されます。
(理由:.NET Framework ツールを実行できるのは Windows のみなので、NuGet 経由で見つかるツールのみが macOS および Linux と互換性があります。)
アセンブリが既定のインターフェイス メソッドをサポートするランタイムをターゲットとする場合、Dotfuscator は NuGet からツールを取得します。 このカテゴリに該当するターゲット フレームワークは次のとおりです。
- .NET 5.0 以降
- .NET Core 3.0 以降
- .NET Standard 2.1
- Xamarin Android
- Xamarin iOS
- MAUI Android
(理由:既定のインターフェイス メソッドは .NET Core 3.0 で導入された最新のランタイムの変更です。 .NET Framework ツールはそのようなメソッドを無効とみなし、この機能を正しく使用してアセンブリを処理しません。 つまり、Dotfuscator は NuGet 経由で利用できる新しいツールを使用する必要があります)。
アセンブリが Windows 専用のランタイムをターゲットとする場合、Dotfuscator は .NET Framework のツールを使用します。 このカテゴリに該当するターゲット フレームワークは次のとおりです。
- .NET Framework 4.x 以前
- ユニバーサル Windows プラットフォーム(UWP)
(理由:これらのフレームワークのアセンブリをビルドするには、通常は .NET Framework SDK が必要です。 また、Dotfuscator がこれらのツールを必要とすることで、上記のフレームワークを使用するお客様が予期せず機能を喪失しないようにします)。
そうでない場合、Dotfuscator は .NET Framework のツールが存在する場合はそれを使用するか、または .NET Framework ツールが存在しない場合は、NuGet からツールを入手します。 このカテゴリに該当するターゲット フレームワークは次のとおりです。
- .NET Core 2.x 以前
- .NET Standard 2.0 以前
- ポータブル クラス ライブラリ(PCL)
(理由:どちらのツール セットもこれらのフレームワークに使用することができますが、.NET Framework ツールの方がより多くの機能をサポートするので推奨されます)。
Dotfuscator がこれらの外部ツールのいずれかを見つけることができなかったときに発生するエラーについては、トラブルシューティングを参照してください。
.NET Framework SDK を必要とする機能
Dotfuscator は、アセンブリを処理するときは ILdasm と Ilasm ツールに依存するので、これらの利用できるツールのバージョンによっては特定の機能が制限される可能性があります。 Dotfuscator がこれらのバージョンを選ぶ方法については、前のセクションを参照してください。
Dotfuscator が Windows 専用の .NET Framework SDK を使用している場合には、以下の機能のみが利用可能です
- デバッグ シンボル(
.pdb
ファイルなど)。デバッグ オプションは関係ありません。 - ネイティブな Win32 リソース ファイル。アセンブリに埋め込まれています(Windows ファイル バージョン、アプリケーション アイコンなど)。
マネージ リソース(.resx
ファイルなど)はすべてのシナリオでサポートされます。
次の表では、Dotfuscator が実行しているオペレーティング システムとターゲット アプリケーション タイプに基づいて、上記の機能のサポート状況をまとめています。
OS | ターゲット アプリケーション タイプ | デバッグ シンボル | ネイティブ リソース | マネージ リソース |
---|---|---|---|---|
Windows | .NET 5.0 以降 | ❌ | ❌ | ✅ |
Windows | .NET Core 3.0 以降 | ❌ | ❌ | ✅ |
Windows | .NET Core 2.x 以前 | ✅* | ✅* | ✅ |
Windows | .NET Framework 4.x 以前 | ✅ | ✅ | ✅ |
Windows | .NET Standard 2.1 | ❌ | ❌ | ✅ |
Windows | .NET Standard 2.0 以前 | ✅* | ✅* | ✅ |
Windows | ポータブル クラス ライブラリ | ✅* | ✅* | ✅ |
Windows | Xamarin Android | ❌ | ❌ | ✅ |
Windows | Xamarin iOS | ❌ | ❌ | ✅ |
Windows | ユニバーサル Windows プラットフォーム(UWP) | ✅ | ✅ | ✅ |
Windows | MAUI Android | ❌ | ❌ | ✅ |
macOS | すべて | ❌ | ❌ | ✅ |
Linux | すべて | ❌ | ❌ | ✅ |
* NuGet パッケージで Dotfuscator をインストールした場合、この機能を使用するには完全な(Windows).NET Framework SDK もインストールされていなければなりません。
ツールの場所の明示的な指定
プロパティを使用して、ある特定のバージョンの .NET でビルドされたアセンブリ用の ILdasm または ILasm 実行可能ファイルを個別に指定できます。
.NET Core および .NET Standard アセンブリは、常にバージョン4.0
でビルドされていると見なされます。これは、それらのアセンブリに組み込まれたメタデータのバージョンが 4.0 だからです。
次の表は、例を示しています。
プロパティ名 | プロパティ値 | 意味 |
---|---|---|
ILDASM_v2.0.50215 |
C:\1\ildasm.exe |
Dotfuscator は、.NET Framework v2.0.50215 を対象に、当バージョンの IL 逆アセンブラーを使って入力アセンブリを逆アセンブルします。 |
ILDASM_v1.1 |
C:\2\ildasm.exe |
Dotfuscator は、.NET Framework v1.1.x を対象に、当バージョンの IL 逆アセンブラーを使って入力アセンブリを逆アセンブルします。 |
ILASM_v1.0.3705 |
C:\3\ilasm.exe |
Dotfuscator は、.NET Framework v1.0.3705 を対象に、当バージョンの IL アセンブラーを使って出力アセンブリをアセンブルします。 |
ILASM_v4.0 |
C:\4\ilasm.exe |
Dotfuscator は、.NET Framework v4.x、.NET Core、、または .NET Standard を対象に、当バージョンの IL アセンブラーを使って出力アセンブリをアセンブルします。 |
これらのツールに対応するコマンド ライン引数は、.NET Framework と NuGet でそれぞれ提供されるバージョンによって異なるため、Dotfuscator は、ツールのパスを確認することでユーザーが提供したツールの種類をヒューリスティックス(発見的手法)に基づいて判断します。
パスに Microsoft.NETCore
が含まれている場合、 Dotfuscator は NuGet の指定したツールとして扱います。そうでない場合、.NET Framework のツールとして扱います。