属性
Dotfuscator による保護を構成するには、アプリケーションのソース コードに .NET 属性を付けます。 ただし、Dotfuscator では、保護を構成するようにソースを編集する必要はありません。 また、ソースから独立して Dotfuscator による保護を構成するには、Dotfuscator 構成ファイルを使用します。
Dotfuscator は、アセンブリを処理するときに特定の属性を認識します。それらの属性は、それが付けられたコード要素を処理する方法を Dotfuscator に指示します。 既定では、Dotfuscator はアセンブリの処理中にこれらの属性の除去も行い、出荷されるアプリケーションに重要な構成情報が含まれないようにしています。
Dotfuscator の属性のリファレンスについては、難読化属性、チェック属性、インストルメンテーション属性を参照してください。
重要: 属性だけでは、コード要素が保護されるようにはなりません。 保護が適用されるようにするには、コンパイルされたアセンブリをさらに Dotfuscator で処理する必要があります。 属性は、Dotfuscator 構成ファイルの使用とともに、保護を構成するための追加の方法にすぎません。
互換性のある属性
Dotfuscator は、特定の属性のみを認識し、他の属性を無視します。 Dotfuscator によって認識される属性は次のとおりです。
- 難読化属性:宣言による難読化を構成します。
- 差し込み属性:これは次のように細分されます。
- チェック属性:チェックを差し込む方法を Dotfuscator に指示します。
- インストルメンテーション属性:インストルメンテーション機能を差し込む方法を Dotfuscator に指示します。
各属性のセットの詳細については、リンク先ページを参照してください。 このページの残り部分では、多くの属性に共通する側面について説明します。
属性を使用するタイミング
属性を使用することで、ソース コードを読む際に、Dotfuscator がコード要素にどのように作用するかがわかりやすくなります。
たとえば、次の C# のスニペットは、ObfuscationAttribute
を使用して、クラス(そのメンバーではなく)を名前の変更対象から除外することを示しています。
using System.Reflection;
[Obfuscation(Feature = "renaming", Exclude = true, ApplyToMembers = false)]
private class MyClass { /* ...*/ }
しかし、属性を使用するより、Dotfuscator 構成エディターを使用して Dotfuscator 構成ファイルを変更する方が、より良く実現できる場合もいくつかあります。 次のようなシナリオが挙げられます。
- ソース コードを編集できないアセンブリを使用する場合
- 保護設定を変更するたびにコードを再コンパイルするのが、開発プロセスのオーバーヘッドとしては大きすぎる場合
- 規則を使用してコード項目を特定の保護機能の対象として除外または選択した方が、個々のコード項目に属性でアノテーションを付けるより簡単または効率的な場合
- 複数の場所を対象とするチェックを構成する場合
- 遠隔測定を有効にする設定など、属性では利用できない設定を構成する場合
属性と Dotfuscator 構成ファイルの設定を組み合わせることができます。
たとえば、上記のスニペットは、名前の変更対象から MyClass
を除外することを Dotfuscator に指示していますが、Dotfuscator 構成エディターを使用して他の型を除外し、それらの対象除外を構成ファイルに保存しておくことができます。
Dotfuscator は、構成ファイルを使ってアセンブリを処理する際、属性または構成ファイルによって除外されているコード項目の名前を変更しません。
コードへの属性の追加
コードに属性を追加し、それらの属性を Dotfuscator に認識させるには
プロジェクトに適切な参照を追加します。 詳細については、以下を参照してください。
コードに互換性のある属性を適用します。適用方法は通常の属性の場合と同様です。
名前空間(このため、必要な
using
ステートメント)は、属性によって異なります。 詳細については、各属性のセクションを参照してください。他の属性と同様に、使用する際にはサフィックス
Attribute
を省略できます。 たとえば、次はTamperCheckAttribute
の使用例です。[TamperCheck(Action = CheckAction.Exit)] public void MyMethod() { // メソッド本体 }
アプリケーションをビルドします。
難読化属性を使用する場合は、Dotfuscator 構成エディターを使って以下の設定を構成します。
差し込み属性を使用する場合は、Dotfuscator 構成エディターを使って以下の設定を構成します。
差し込み属性が含まれるアセンブリごとに、[差し込み属性の使用]オプションと[差し込み属性の除去]オプションが有効になっていることを確認します。
差し込みが有効になっていることを確認します。
チェックの遠隔測定またはインストルメンテーションを使用する場合は、適切な遠隔測定関連オプションが有効になっていることを確認します。
構成エディター(あるいは、Visual Studio 統合またはコマンド ライン)で構成ファイルを作成します。 Dotfuscator は、構成された属性に従って動作し、その後で、アプリケーションから属性(および関連するアセンブリ参照)を削除します。
アプリケーション コードとの対話
Dotfuscator によって差し込まれたコードが既存のアプリケーション コードと対話できるシナリオがいくつかあります。 差し込まれたコードに情報を提供するアプリケーション コードはソースと呼ばれ、差し込まれたコードから情報を受け取るアプリケーション コードはシンクと呼ばれます。
メモ: これらのコードを、属性でアノテーションを付けられるコード要素や、チェックの対象となるメソッドと混同しないでください。 これらは、インストルメンテーション属性やチェックの場所と呼ばれます。
各インストルメンテーション属性やチェックで、さまざまなコンテキストのために、1 つまたは複数のソースと、1 つまたは複数のシンクを定義できます。 インストルメンテーション属性やチェックのソースとシンクは、次の 3 つのプロパティで定義されます。
element プロパティ。フィールドやメソッドなど、ソースまたはシンクとなるコード項目の種類を指定します。 詳細については、ソース要素の種類サブセクションとシンク要素の種類サブセクションを参照してください。
name プロパティ。コード項目の名前を指定します(該当する場合)。
省略可能な owner プロパティ。コード項目を定義する型を指定します(該当する場合)。 指定されていない場合は、インストルメンテーション属性またはチェックの場所を定義する型が既定値になります。 詳細については、オーナー サブセクションを参照してください。
たとえば、チェックが実行された場合、チェックはアプリケーション通知シンクを介して、結果をアプリケーションに通知できます。 シンクは、チェックの ApplicationNotificationSink プロパティを使って構成できます。
ApplicationNotificationSinkElement
ApplicationNotificationSinkName
ApplicationNotificationSinkOwner
特定のインストルメンテーション属性またはチェックに使用できるソースとシンクの詳細については、チェック属性ページおよびインストルメンテーション属性ページの関連セクションに記載されています。
ソース要素の種類
ソースは、Dotfuscator によって差し込まれたコードに情報を提供するアプリケーション コード要素です。 このセクションでは、差し込まれたコードのソースとして使用できるコード要素の種類を列挙します。
サポートされている要素、要素の署名、ソースから取得される値の意味は、インストルメンテーション属性やチェックによって異なることに留意してください。 詳細については、チェック属性ページおよびインストルメンテーション属性ページを参照してください。
たとえば、SetupAttribute
のオプトイン ソースには、bool
型のメソッド引数、フィールド、またはプロパティか、あるいは bool()
署名付きのメソッドを指定する必要があります。
ブール値は、ユーザーにインストルメンテーションの遠隔測定をオプトインさせる場合は true
、そうでない場合は false
です。
以下に、インストルメンテーション属性やチェックの element プロパティ(たとえば、SetupAttribute
の OptInSourceElement)に使用可能な値を列挙します。
使用可能なソース要素の種類は以下のとおりです。
None:ソースは無効であり、アプリケーションは差し込まれたコードに情報を提供しません。
- name プロパティおよび owner プロパティは、この設定では無視されます。
MethodArgument:差し込まれたコードは、メソッド引数から情報をコピーします。 メソッド引数は、インストルメンテーション属性またはチェックのすべての場所に対応する引数である必要があります。
name プロパティには、メソッド引数の名前を指定します。
owner プロパティはこの設定では無視されます。
Field:差し込まれたコードは、フィールドから情報をコピーします。 このフィールドは、インストルメンテーション属性またはチェックのすべての場所からアクセス可能である必要があります。
name プロパティには、このフィールドの単純名を指定します。
owner プロパティには、このフィールドを宣言する型を指定します。
Property:差し込まれたコードは、プロパティから情報をコピーします。 このプロパティとその getter は、インストルメンテーション属性またはチェックのすべての場所からアクセス可能である必要があります。
name プロパティには、このプロパティの単純名を指定します。
owner プロパティには、このプロパティを宣言する型を指定します。
Method:差し込まれたコードは、情報を返すメソッドを呼び出します。 このメソッドは、インストルメンテーション属性またはチェックのすべての場所からアクセス可能である必要があります。
name プロパティには、このメソッドの単純名(例:
bool MyMethod()
でなくMyMethod
)を指定します。owner プロパティには、このメソッドを宣言する型を指定します。
ApplicationSetting:差し込まれたコードは、アプリケーション設定の構成ファイル(
AssemblyName.exe.config
)から情報を取得します。 この要素の種類は、SetupAttribute
のエンドポイント ソースにのみ使用できます。name プロパティは、アプリケーション構成ファイルにあるキーの名前です。 たとえば、次の構成ファイルの場合は
MyKey
です。<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <appSettings> <add key="MyKey" value="mycompany.com:80/telemetry/endpoint"/> </appSettings> </configuration>
owner プロパティはこの設定では無視されます。
DefaultAction:差し込まれたコードは、いくつかの既定の情報を使用します。 正確な動作は、構成する特定のソースによって異なり、この設定を無効な構成としているものもあります。
これは、その名前に反して、必ずしも element プロパティの既定値ではありません。
name プロパティおよび owner プロパティは、この設定では無視されます。
シンク要素の種類
シンクは、Dotfuscator によって差し込まれたコードから情報を取得するアプリケーション コード要素です。 このセクションでは、差し込まれたコードのシンクとして使用できるコード要素の種類を列挙します。
サポートされている要素、要素の署名、シンクに提供される値の意味は、インストルメンテーション属性やチェックによって異なることに留意してください。 詳細については、チェック属性ページおよびインストルメンテーション属性ページを参照してください。
たとえば、チェックのアプリケーション通知シンクには、bool
型のフィールドまたはプロパティ、あるいは void(bool)
署名付きのメソッド、デリゲート フィールド、またはデリゲート メソッド引数を指定する必要があります。
ブール値は、チェックが不正な状態(デバッガーがアタッチされている、改ざんされている、など)を検出した場合は true
、検出されなかった場合は false
です。
以下に、インストルメンテーション属性やチェックの element プロパティ(たとえば、改ざんチェックの ApplicationNotificationSinkElement)に使用可能な値を列挙します。 使用可能なシンク要素の種類は以下のとおりです。
None:シンクは無効であり、差し込まれたコードはアプリケーションに情報を提供しません。
通常、これが element プロパティの既定値です。
name プロパティおよび owner プロパティは、この設定では無視されます。
Method:差し込まれたコードはメソッドを呼び出し、そのメソッドのパラメーターを介して情報を提供します。 このメソッドは、インストルメンテーション属性またはチェックのすべての場所からアクセス可能である必要があります。
name プロパティには、このメソッドの単純名(例:
void MyMethod(bool)
でなくMyMethod
)を指定します。owner プロパティには、このメソッドを宣言する型を指定します。
Field:差し込まれたコードは、フィールドを設定することによって情報を提供します。 このフィールドは、インストルメンテーション属性またはチェックのすべての場所からアクセス可能、かつ設定可能である必要があります。
name プロパティには、このフィールドの単純名を指定します。
owner プロパティには、このフィールドを宣言する型を指定します。
Property:差し込まれたコードは、プロパティを設定することによって情報を提供します。 このプロパティとその setter は、インストルメンテーション属性またはチェックのすべての場所からアクセス可能である必要があります。
name プロパティには、このプロパティの単純名を指定します。
owner プロパティには、このプロパティを宣言する型を指定します。
MethodArgument:差し込まれたコードは、メソッド引数で指定されたデリゲートを呼び出し、そのデリゲートのパラメーターを介して情報を提供します。 メソッド引数は、インストルメンテーション属性またはチェックのすべての場所に対応する引数である必要があります。
name プロパティには、メソッド引数の名前を指定します。
owner プロパティはこの設定では無視されます。
Delegate:差し込まれたコードは、フィールドで指定されたデリゲートを呼び出し、そのデリゲートのパラメーターを介して情報を提供します。 このフィールドは、インストルメンテーション属性またはチェックのすべての場所からアクセス可能である必要があります。
name プロパティには、このフィールドの単純名を指定します。
owner プロパティには、このフィールドを宣言する型を指定します。
DefaultAction:差し込まれたコードは、情報に基づくいくつかの既定の動作を実行します。 正確な動作は、構成する特定のシンクによって異なり、この設定を無効な構成としているものもあります。
これは、その名前に反して、必ずしも element プロパティの既定値ではありません。
name プロパティおよび owner プロパティは、この設定では無視されます。
オーナー
ソースまたはシンクの owner は、そのソースまたはシンクを宣言する型です。
メモ: ソース要素とシンク要素の一部の種類では、owner プロパティに型を指定する必要がないため、どのような値を構成しても無視されます。 owner プロパティを無視する要素の種類は None、MethodArgument、ApplicationSetting、DefaultAction です。
owner プロパティの値は、アセンブリ名ではなく名前空間を含めて表される型名です。
たとえば、名前空間 Outer.Inner
で宣言されたクラス MyType
のフィールド wasTampered
について考えてみましょう。
このフィールドにシンクを定義するプロパティは、以下のようになります。
element プロパティ:Field
name プロパティ:
wasTampered
owner プロパティ:
Outer.Inner.MyType
ソースまたはシンクには、オーナーのインスタンス メンバーまたは静的メンバーを使用できます。 この違いは、owner プロパティの使用方法に影響します。 また、複数の場所を持つチェックを使用する場合には、各場所に異なるオーナーを参照させることができます。
静的メンバーの場合
ソースまたはシンクが静的メンバーである場合は、ソース/シンクは、インストルメンテーション属性またはチェックのすべての場所からアクセス可能であれば、どのような型で定義されていてもかまいません。 これがどの型であるかを owner プロパティに指定します。 このプロパティの値が空白である場合は、インストルメンテーション属性またはチェックの場所を定義している型と見なされます。
インスタンス メンバーの場合
ソースまたはシンクがインスタンス メンバーである場合は、次の条件を満たしている必要があります。
インストルメンテーション属性またはチェックの場所もインスタンス メンバーである。
インストルメンテーション属性またはチェックの場所は、ソースまたはシンクを宣言した型と同じ型で定義されている。
owner プロパティは、この型の名前であるか、または空白である。
実行時、場所を呼び出す際に使用されたインスタンスが、ソースまたはシンクにも使用されます。
チェックの複数のオーナー
複数の場所を持つチェックを使用する場合、各場所は、ソースおよびシンクに関して個々に評価されます。 つまり、次の条件を満たしていれば、各場所が異なるソースまたはシンクを持つことができます。
チェックの場所を定義する各型に、ソースまたはシンクのメンバーが指定されている。
特定の場所が静的メンバーである場合は、対応するソースまたはシンクのメンバーも静的メンバーである必要があります。
特定の場所がインスタンス メンバーである場合は、対応するソースまたはシンクのメンバーはインスタンス メンバーまたは静的メンバーのどちらでもかまいません。
owner プロパティが空白である。