P/Invoke メソッド
P/Invoke メソッド(つまり、ネイティブ プラットフォーム メソッド)の名前は、対応するネイティブ関数の検索に使用されていることが Dotfuscator によって検出された場合、名前の変更対象から自動的に除外されます。 エイリアスまたは序数によってネイティブ関数に対応付けられている P/Invoke メソッドの場合は、メソッドの名前を変更できます。
Managed C++ および IJW(It Just Works)のサンク
Dotfuscator は、たとえば Managed C++ コンパイラで生成されるような、マネージ コードとアンマネージ コード(ネイティブ コード)が共に含まれているアセンブリを処理することができます。 Dotfuscator はそのようなコードの混在するモジュールに対して、名前の変更とメタデータの除去は行いますが、文字列の暗号化、制御フローの難読化、および不要なコードの除去については自動的に無効にします。 ただし、これらの機能は、実行に含まれるその他の "純粋なマネージ" 入力モジュールに対しては有効なままです。
マネージ リソースを持つアセンブリの難読化
マネージ リソースはモジュール(内部)に埋め込まれる場合と、モジュール外部のファイルに存在する場合があります。 多くの場合、一部のマネージ リソースの名前は型の名前です(マネージ リソースの検索のための "ハブ アンド スポーク モデル" に関する詳細については、.NET Framework ドキュメントを参照してください)。
型の名前を変更すると、Dotfuscator は、対応するマネージ リソースを見つけて名前を変更しようとします。 リソースがアセンブリの内部にある場合、名前は自動的に変更されます。 リソースが外部ファイル内に埋め込まれている場合、そのファイルは参照元のモジュールと同じディレクトリに存在する必要があります。 リソースが他のアセンブリ内に埋め込まれている場合、そのアセンブリは入力アセンブリの 1 つである必要があります。
サテライト DLL を使用するアセンブリの難読化
ローカライズされたアプリケーションは、それらが使用するサテライト リソース DLL と共に、シームレスに難読化処理を行うことができます。 Dotfuscator はランタイムが使用するルールと同じルールを使ってそのような DLL を自動検出し、難読化処理の入力として自動的に追加します。 そのため、それらの DLL を入力として明示的に指定する必要はありません。
サテライト DLL に含まれるローカライズされたリソースは、メイン アセンブリ内にあるニュートラル カルチャのリソースと同期して名前変更されます。
マルチ モジュール アセンブリの難読化
.NET アセンブリは複数のモジュール (つまり、ディスク上の複数のファイル) で構成されている場合があります。 通常、1 つのアセンブリは 1 つのモジュールで構成されています。Visual Studio など、ほとんどのツールでサポートされているのは、このような単一モジュールのアセンブリです。 しかし、ときには、複数のモジュールで構成されたアセンブリを作成することが望ましい場合もあります。 Dotfuscator は、このようなマルチ モジュール アセンブリが使用されているシナリオもサポートします。 マルチ モジュール アセンブリの難読化は、複数の入力アセンブリの難読化とは異なることに注意してください。
マルチ モジュール アセンブリを難読化する場合、入力アセンブリとして指定する必要があるのは主モジュールだけです。 主モジュール以外のモジュールは、主モジュールと同じディレクトリ内から検索されます。
主モジュールのアセンブリ マニフェストに記述されている他のモジュールのハッシュ値は、Dotfuscator によって自動的に更新されます。
64 ビット アセンブリの難読化
Dotfuscator では、64 ビット アーキテクチャなど、特定の CPU アーキテクチャ用に明示的に作成されたマネージ アセンブリの難読化処理を透過的に実行できます。
Dotfuscator 自体はマネージ アプリケーションであり、32 ビットおよび 64 ビット バージョンの Windows 上で実行できます。
リフレクションおよび動的クラス読み込み
リフレクションおよび動的クラス読み込みは、.NET アーキテクチャにおいては非常に優れたツールです。 しかし、プログラムの実行時にこのレベルのカスタマイズが行われると、Dotfuscator は指定されたプログラムに読み込まれたすべての型の名前を変更しても安全かどうかを確実に判断できなくなります。
次の(C#)コードを考えてみましょう。
C# コード:
public object GetNewType() {
Type type = Type.GetType( GetUserInputString(), true );
object newInstance = Activator.CreateInstance( type );
return newInstance;
}
このコードは名前で指定された型を読み込み、その型のインスタンスを動的に作成します。 さらに、その名前はユーザーが入力する文字列によって指定されます。
ユーザーがどの型の名前を入力するかは、Dotfuscator では予測できません。 その解決策として、読み込める可能性のあるすべての型の名前を対象から除外するために Dotfuscator を設定します。 そうしても、メソッドおよびフィールドの名前を変更することは可能です。 このような訳で、ユーザーの手作業による構成が重要な役割を果たしているのです。
多くの場合、状況は上記の場合ほど困難ではありません。 次のコード例は、前述のコードを一部だけ変更したものです。
C# コードの変更例:
public MyInterface GetNewType() {
Type type = Type.GetType( GetUserInputString(), true );
object newInstance = Activator.CreateInstance( type );
return newInstance as MyInterface;
}
コードから明らかなように、この例の場合、対象から除外する必要があるのは一部の特定の型(MyInterface
を実装している型)だけです。
カスタム属性を使用した宣言による難読化
.NET Framework で、アセンブリの自動難読化を容易にするための 2 つのカスタム属性が用意されました。これらの属性により、構成ファイルを設定する必要がなくなりました。 このセクションでは、Dotfuscator でこれらの属性を使用する方法を概説します。 ここでの説明は、カスタム属性の基本的な使用方法や開発言語でのカスタム属性の適用方法を理解していることを前提としています。
これらのカスタム属性がない、以前のバージョンの .NET Framework をお使いの場合、Dotfuscator には、互換性のある属性が格納された DLL が付属しています。
System.Reflection.ObfuscateAssemblyAttribute
ObfuscateAssemblyAttribute
はアセンブリ レベルで使用され、Dotfuscator に対してアセンブリ全体の難読化方法を指示します。 この属性のプロパティでは、アセンブリをライブラリ モードで実行するかどうかや、難読化属性の除去がアセンブリに対して有効かどうかを指定します。
ObfuscateAssemblyAttribute
の設定の詳しい説明は、ここにあります。
System.Reflection.ObfuscationAttribute
ObfuscationAttribute
は型とそのメンバーを対象として使用されます。この属性には、アノテーションが付けられたコード要素に対して Dotfuscator が行うアクションを指定する Feature プロパティがあります。
Dotfuscator は ObfuscationAttributes
を介して以下の機能の設定をサポートします。
アノテーションが付けられた単独のコード要素ごとに複数の機能を設定することができます。これには、それぞれ対応する Feature プロパティ値を指定した複数の ObfuscationAttribute
を使用します。
Dotfuscator では Dotfuscator が認識できない機能文字列が指定されている属性は無視されます。
ObfuscationAttribute
の設定の詳しい説明は、ここにあります。
宣言による難読化の有効化と無効化
Dotfuscator では、入力アセンブリの一部またはすべてに対する宣言による難読化を有効または無効に切り替えることができます。 無効になっている場合、難読化に関連するカスタム属性は完全に無視されます。
Dotfuscator 構成エディターで難読化属性の使用を設定します。
宣言による難読化の属性の除去
Dotfuscator では、処理の完了後に難読化に関する属性を除去して、難読化の処理方法を調べる手掛かりを出力アセンブリ内に残さないようにできます。
Dotfuscator 構成エディターで難読化属性の除去を設定するか、または難読化に関連するカスタム属性のプロパティ StripAfterObfuscation を介して属性の除去を設定します。
機能割り当て文字列の使用
Dotfuscator では、ObfuscationAttribute
の Feature プロパティで指定された値に Dotfuscator が認識できる機能文字列を割り当てることができます。
たとえば、アプリケーションにおいて "testmode"
という名前の機能を参照する難読化属性 ObfuscationAttributes
を指定したとします。 Dotfuscator は既定値ではこの機能文字列を認識しないので、その属性は無視されます。 後で、名前の変更や制御フローの難読化を設定するためにこれらの属性の使用が必要になった場合は、機能文字列の "testmode"
に Dotfuscator に組み込みの "renaming"
および "controlflow"
文字列を割り当てます。
Dotfuscator 構成エディターの[設定]タブにある機能割り当て文字列を設定します。
フレンド アセンブリ
.NET Framework では「フレンド アセンブリ」という概念が導入され、指定した他のアセンブリに対してアセンブリ内の型定義を公開する宣言を行えるようになりました。 この宣言を行うには、System.Runtime.CompilerServices.InternalsVisibleToAttribute
を使用します。 Dotfuscator はこの属性の使用を検出し、設定されている名前の変更規則および不要コードの除去規則を以下の説明のように変更します。
A、B という 2 つのアセンブリがあり、B は A を参照し、A は InternalsVisibleTo ( B )
とマークされているとします。
この場合、いくつかのケースが考えられます。
- A および B が共にライブラリ モードの入力アセンブリである場合。 A に他の外部の入力アセンブリ以外のフレンドがない場合は、Dotfuscator は内部名を安全に改変し、アセンブリ B 内の参照を修正します。 A に他の外部フレンドがある場合、内部名は保持されます。
- A および B が共にライブラリ モードでない入力アセンブリであるが場合。 他の外部フレンド アセンブリが存在するかどうかに関係なく、既定では A 内の内部名は改変され、B 内の参照は修正されます。 通常どおり、手動で構成することによって、名前および名前のグループを保持することができます。
- A はライブラリ モードの入力アセンブリ、B は入力アセンブリ以外である場合。 B 内の潜在的な参照を壊さないために、A 内の内部名は改変されません。
- A はライブラリ モードでない入力アセンブリ、B は入力アセンブリ以外である場合。 内部名は改変され、B 内の潜在的な参照は、B が入力アセンブリでないために修正されません。 通常どおり、手動で構成することによって、名前および名前のグループを保持することができます。 このケースでは、実際に B が A の内部を参照する場合は、手作業による構成が必要になります。
XAML の考慮事項
XAML の書き換え
Dotfuscator は次の項目を分析し、更新します。
-
バインディング マークアップ拡張機能。式内の基本プロパティが、そのノードよりも上にある XML 階層内のクラスに属している場合。
- 例:
<Textbox Text="{Binding Path='Dealership.SalesTeam'}">
- 例:
-
要素名。(名前空間に基づいて)入力内で見つかるクラスによって裏付けられると判断した場合。
- 一致が見つかった場合は、属性/子ノードも適切に書き換えます。
XAML の書き換えの制限
Dotfuscator は次の項目を処理しません。
- 実際の XML 名前空間
- テンプレート/スタイル内の項目の更新を試みますが、あまり正しく行えない可能性があります。一般的に、テンプレート/スタイルから参照されるプロパティと型を除外することをお勧めします。
- 添付プロパティおよび添付インベント
- XAML 参照のバッキング フィールド、メソッド、および登録名は更新しません。
最適な方法
次の項目を手動で除外します。
- すべての添付プロパティおよび添付インベント。
- 添付プロパティおよび添付インベントの、すべてのバッキング フィールドおよび登録メソッド。
-
System.Windows.DependencyProperty
型のフィールドを探します。 -
System.Windows.DependencyObject
型のパラメーターを持つメソッドを探します。- 残念ながら、現在のバージョンでは、カスタム規則でこれをサポートできません。そのため、すべてのインスタンスを手動で検出する必要があります。
-
- テンプレート/スタイルから参照されるすべてのプロパティ(場合によっては、入力内で同じリテラルの名前を持つその他すべてのプロパティ)。
XAML ビルド警告
Dotfuscator で XAML の部分を分析して、CLR オブジェクトと適合させることができない多くの場合は、警告を発して、それらは手動で変更を加える必要があることをユーザーに知らせます。ランタイム エラーの原因を特定しようとする場合は、警告をチェックすることが重要です。