XML ルール
コマンドラインや MSBuild の Babel タスクで指定するオプションに加えて、Babel Obfuscator は外部の XML ファイルに定義したルールでも制御および設定できます。XML ルールを使うと、特定のアセンブリ、型、メソッド、その他のコード要素を対象にして、難読化の処理をきめ細かく制御できます。
ルールファイル
Babel のルールファイルは、難読化の処理をカスタマイズして制御するための構成情報を含む XML ドキュメントです。このファイルでは、コードのどの部分にどの難読化機能を適用するかを正確に定義でき、アセンブリの保護をきめ細かく制御できます。
<Rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Rule name="rule 1" feature="default" exclude="false">
</Rule>
<Rule name="rule 2" feature="control flow" exclude="true">
</Rule>
</Rules>Rules 要素には targetAssembly 属性を定義でき、含まれるルールの適用範囲を特定のアセンブリに限定できます。targetAssembly 属性を指定しない場合、ルールは処理対象のすべてのアセンブリに適用されます。例:
<Rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
targetAssembly="ACME.Data">XML ルールファイルでは、ルールは記述された順に、上から下へ順番に処理されます。この順次処理により、後に記述した、より具体的なルールで既存のルールを上書きできるため、柔軟で階層的なルール構造になります。
Rules 要素
Rules 要素は、ターゲットアセンブリに適用するルールのセットを定義するルートコンテナーです。この要素には複数の Rule 子要素を含めることができ、それぞれが異なる難読化の動作を指定します。
| 属性 | 説明 |
|---|---|
| targetAssembly | ルールを適用するアセンブリの完全修飾名を指定します。定義しない場合、ルールは難読化の処理に関わるすべてのアセンブリに適用されます。 |
Rule 要素
Rule 要素は、Babel の難読化ルールを定義します。1 つのルールで、Babel Obfuscator の 1 つまたは複数の機能を対象にできます。各ルールは、どのコード要素に作用し、難読化機能をどのように適用するかを指定します。
| 属性 | 説明 |
|---|---|
| name | ルールの目的を識別しやすくする、わかりやすい名前 |
| feature | このルールが対象とする難読化ツールの機能名、または機能名のコンマ区切りリスト。複数の機能を指定すると、同じルールを難読化の異なる側面に適用できます |
| exclude | このルールが、指定した機能の実行を防ぐかどうかを示すブール値。シンボルを難読化から除外するには「true」に、明示的に含めるには「false」に設定します |
| applyToMembers | ルールの条件に一致するシンボルのすべてのメンバーにルールを適用するかどうかを示すブール値。有効にすると、ルールは入れ子のメンバーにも適用されます |
| locked | このルールが変更不可で、処理順で後に続くルールによって上書きできないかどうかを示すブール値 |
feature 属性は、ルールが作用する難読化ツールの機能を定義します。name 属性と exclude 属性は必須で、feature 属性は省略できます。指定しない場合、機能は既定で「default」になり、これはリネーム機能を指します。
難読化ツールの機能は、特定の難読化機能に対応する定義済みの文字列です。サポートされている機能名は、すべて次の表に示します。
機能の表
次の機能は、型、メソッド、プロパティ、フィールド、イベントなど、アセンブリ内で定義されたすべての種類のシンボルを対象にできます。
| 機能 | 説明 |
|---|---|
| all | 利用できるすべての難読化機能を対象にします |
| default | 既定の機能で、シンボルのリネームによる難読化を指します |
| agent | 難読化エージェントの機能を対象にします |
| cleanup attributes | アセンブリのメタデータから不要な属性を除去します |
| control flow | 制御フロー難読化を適用し、コードのロジックを理解しにくくします |
| dead code | デッドコード除去の最適化を有効にします |
| dynamic proxy | メソッドの直接呼び出しを動的プロキシ呼び出しに置き換えます |
| embed | 依存アセンブリをターゲットアセンブリに埋め込みます |
| merge | 複数のアセンブリを 1 つのアセンブリにマージします |
| msil encryption | MSIL(Microsoft Intermediate Language)のコード暗号化でメソッド本体を暗号化します |
| renaming | メンバー名(型、メソッド、プロパティ、フィールド、イベント)を難読化します |
| renaming blob | リネームされたシンボルに対応する文字列リテラルをリネームし、コードの機能を保ちます |
| resource encryption | アセンブリ内の埋め込みリソースを暗号化します |
| string encryption | コード内のインラインの文字列リテラルを暗号化します |
| value encryption | インラインの定数値と配列の初期化を暗号化します |
| inline | メソッド呼び出しをインライン展開し、コードの構造を見えにくくします |
| instrumentation | 監視と解析のためのコードのインストルメンテーションを有効にします |
| optimizations | メタデータとコードのさまざまな最適化を適用します |
| xaml | XAML または BAML のリソースで参照されるシンボルのリネームを処理します |
次の難読化機能はメソッド専用で、メソッドのシンボルにだけ適用できます。
| 機能 | 説明 |
|---|---|
| msil encryption get stream | MSIL の復号で、暗号化されたコードのソースストリームを取得するメソッドを宣言します |
| string encryption encrypt method | 文字列リテラルの暗号化に使用するカスタムメソッドを定義します |
| string encryption decrypt method | 実行時に文字列リテラルを復号するカスタムメソッドを定義します |
| instrumentation on entry method | インストルメンテーション対象のメソッドに入るときに呼び出すメソッドを定義します |
| instrumentation on exit method | インストルメンテーション対象のメソッドから出るときに呼び出すメソッドを定義します |
| instrumentation on exception method | インストルメンテーション対象のメソッドで例外が発生したときに呼び出すメソッドを定義します |
| module initializer | ランタイムがモジュールを初期化するときに自動的に実行されるメソッドを指定します |
Rule 要素には、Access、Target、Pattern、HasAttribute、Properties、Description などの子要素を含めることができます。Pattern 要素は必須で、それ以外はすべて省略できます。これらの子要素は、ルールに絞り込みと設定の機能を追加します。例:
<Rule name="DataWriter" feature="msil encryption" exclude="false">
<Target>Methods</Target>
<Pattern>SQLUtils.DataWriter::*</Pattern>
<Properties>
<Cache>true</Cache>
<MinInstructionCount>6</MinInstructionCount>
</Properties>
<Description>Encrypt all methods of the DataWriter class.</Description>
</Rule>Rule の子要素の一覧は次のとおりです。
| 要素 |
|---|
| Access |
| Targets |
| Pattern |
| HasAttribute |
| HasBase |
| Implements |
| Namespace |
| Properties |
| Description |
Access 要素
ルールの適用範囲を、指定した可視性修飾子を持つシンボルに限定します。指定できる値は All、または Public、Protected、Internal、Private、FamilyAndAssembly、FamilyOrAssembly の任意の組み合わせです。この要素がない場合は既定値の All が使われ、ルールはあらゆる可視性のシンボルに適用されます。
| アクセス | 説明 |
|---|---|
| Public | 任意のアセンブリの任意の型からアクセスできます。 |
| Protected | メンバーと同じ型の内部と、その型を継承する派生型からアクセスできます(Family アクセスとも呼ばれます)。 |
| Internal | 型が定義されているのと同じアセンブリ内でのみアクセスできます(Assembly アクセスとも呼ばれます)。 |
| Private | メンバーと同じ型の内部、またはその型の入れ子になった型からのみアクセスできます。 |
| FamilyOrAssembly | Family アクセスまたは Assembly アクセスのいずれかの条件を満たす型からアクセスできます(C# の protected internal)。 |
| FamilyAndAssembly | Family アクセスと Assembly アクセスの両方の条件を満たす型からのみアクセスできます(C# の private protected)。 |
Targets 要素
ルールの適用範囲を、特定の種類のコードシンボルに限定します。指定できる値は All、または Classes、Delegates、Structures、Interfaces、Enums、Events、Methods、Properties、Fields、StaticFields、Resources の任意の組み合わせです。この要素がない場合は既定値の All と見なされ、ルールはすべての種類のシンボルに適用されます。
Pattern 要素
Babel Obfuscator の XML ルール定義にある Pattern 要素は、難読化の対象となるアセンブリのシンボルを識別して一致させるための重要な要素です。この要素には、シンボルの完全修飾名、ワイルドカード式、または正規表現を指定でき、特定のコード要素を対象にするための柔軟な絞り込みの仕組みになります。
ワイルドカード式:より単純な選択条件では、Pattern 要素にワイルドカード文字を使用できます。’?’ は任意の 1 文字を、’*’ は 0 個以上の文字を表します。この機能により、広い範囲を対象にしながらも制御の効いた一致条件を指定でき、複雑なパターンを書かなくても、関連するシンボルのグループを簡単に対象にできます。
正規表現:より複雑で厳密な絞り込みが必要な場合は、Pattern 要素で正規表現を使用できます。正規表現を使用するときは、属性 isRegEx を「true」に設定して、パターンをリテラル文字列やワイルドカードパターンではなく、正規表現として解釈することを示す必要があります。XML が正しく解析され、特殊文字が正確に解釈されるように、正規表現は CDATA セクションで囲むことをお勧めします。たとえば、次のように指定します。
<Pattern isRegEx="true"><![CDATA[^Properties.*]]></Pattern> 完全修飾名の形式
Babel Obfuscator の XML ルールのパターン定義では、シンボルの完全修飾名の形式は、対象とするシンボルの種類によって異なります。種類ごとに形式を分けることで、さまざまな種類のシンボルを正確かつ効果的に難読化でき、明確さと一貫性も保たれます。
型(クラス、構造体、列挙型、インターフェイス):通常の形式は NamespaceName.TypeName で、基本的な型宣言を簡潔に表記できます。
入れ子になった型:入れ子になった型(ほかの型の内部で定義された型)では、スラッシュを区切り文字とする形式 NamespaceName.TypeName/NestedTypeName を使用します。この表記により、入れ子になった型が親の型と明確に区別され、階層関係も保たれます。
ジェネリック型:ジェネリック型は、NamespaceName.TypeName の後に、山かっこで囲んだジェネリック型引数を続けて表します。
NamespaceName.TypeName<GenericArgumentList>
GenericArgumentList:この要素は独立したパターンではなく、ジェネリック型のパターンの一部です。ジェネリック型引数のコンマ区切りリストを定義し、それぞれを完全な名前空間と型名で指定します。
NamespaceName.TypeName1,NamespaceName.TypeName2,...,NamespaceName.TypeNameN
メソッド:メソッドの一般的な形式は、名前空間、型名、メソッド名、パラメーターリスト、および省略可能な戻り値の型で構成されます。
NamespaceName.TypeName::MethodName(ParameterList):ReturnType
なお、パターンに ReturnType を含めるかどうかは任意で、ほとんどの場合は省略できます。
プロパティ:プロパティの形式は次の構造に従います。
NamespaceName.TypeName::PropertyName:PropertyType
通常、プロパティの型はパターンに含める必要がなく、省略できます。
イベント:イベントの形式は次のとおりです。
NamespaceName.TypeName::EventName:EventHandlerType
この形式には、イベント名と、それに関連付けられたハンドラーの型の両方が含まれます。
フィールド:フィールドは次の形式に従います。
NamespaceName.TypeName::FieldName:FieldType
プロパティと同様に、フィールドの型は通常省略でき、ほとんどのパターン定義では必要ありません。
ParameterList:この要素は、メソッドのパターンでのみ使用します。パラメーターの完全修飾型名を、コンマで区切って指定します。
NamespaceName.TypeName1,NamespaceName.TypeName2,...,NamespaceName.TypeNameN
これらのパターンは、Babel Obfuscator がコードのどの部分を難読化の対象にするかを正確に指定するためのものです。厳密な構文は、状況や難読化方針の要件によって多少異なる場合があります。正確なパターンを使用すれば、意図したシンボルだけが難読化ルールの影響を受けます。
HasAttribute 要素
カスタム属性の完全修飾型名のコンマ区切りリストを指定します。対象のシンボルにこれらの属性が 1 つでも付いていれば、そのシンボルにルールが適用されます。この要素により、属性に基づく絞り込みで、ルールの対象を正確に指定できます。
この要素は、省略可能な onEnclosingType 属性をサポートしています。「true」に設定すると、カスタム属性をシンボル自体ではなく、対象のシンボルを囲む型で確認します。
<HasAttribute onEnclosingType="true">System.SerializableAttribute</HasAttribute>この構成は、SerializableAttribute が付いた任意の型に属するメソッド、プロパティ、フィールド、イベントなどのシンボルに一致します。
HasBase 要素
基本型の完全修飾名のコンマ区切りリストを指定します。対象の型が、指定した基本型のいずれかから派生している場合に、ルールはその型のシンボルに一致します。この要素により、継承に基づく絞り込みでルールを適用できます。
この要素は、省略可能な onEnclosingType 属性をサポートしています。「true」に設定すると、Babel は対象のシンボルを囲む型の階層を検索するため、シンボルを含む型の継承構造に基づいてルールを適用できます。
Namespace 要素
ルールを、指定した名前空間内のシンボルに限定します。これにより、名前空間のレベルで絞り込んでルールを適用できます。
<Namespace>ACME.Data</Namespace>ルールは、ACME.Data 名前空間とそのサブ名前空間で定義されたすべてのシンボルに適用されます。
Properties 要素
Properties 要素は、ルールで選択した機能の動作をカスタマイズするための XML 子要素の集まりを定義します。各難読化機能は、その動作を制御し、一致したシンボルの処理方法を細かく調整するための固有のプロパティをサポートしています。
<Rule name="DataWriter" feature="msil encryption" exclude="false">
<Target>Methods</Target>
<Pattern>ACME.Data.DataWriter::*</Pattern>
<Properties>
<Cache>true</Cache>
<MinInstructionCount>6</MinInstructionCount>
</Properties>
<Description>Encrypts code in the DataWriter class.</Description>
</Rule>このルールは、DataWriter クラスのすべてのメソッドに対して Cache プロパティと MinInstructionCount プロパティを指定し、「msil encryption」機能を設定します。
各難読化機能がサポートするプロパティ要素の一覧は次のとおりです。
agent
| プロパティ | 型 | 説明 |
|---|---|---|
| TaskNameList | 文字列 | ルールを適用するエージェントタスク名のコンマ区切りリスト。 |
cleanup attributes
| プロパティ | 型 | 説明 |
|---|---|---|
| Attributes | 文字列 | 検索に含めるメンバーに一致する、属性の修飾型名または正規表現のコンマ区切りリスト。 |
| IncludeMembers | 文字列 | 検索に含めるメンバーに一致する、シンボルの修飾名または正規表現のコンマ区切りリスト。 |
| ExcludeMembers | 文字列 | 検索から除外するメンバーに一致する、シンボルの修飾名または正規表現のコンマ区切りリスト。 |
control flow
| プロパティ | 型 | 説明 |
|---|---|---|
| ILIterations | 整数 | 制御フロー難読化で適用する反復回数を指定します。値を大きくするほど、コードの構造が複雑になります。 |
| EmitInvalidOpcodes | ブール値 | 有効にすると、メソッドのフローに無効な命令オペコードを追加し、逆アセンブラーとデコンパイラーを混乱させます。 |
| ChangeIfStatement | ブール値 | 有効にすると、条件分岐の if 文の命令を変換して難読化し、ロジックを追いにくくします。 |
| AddSwitchStatement | ブール値 | 有効にすると、メソッドのフローに switch 文の命令を挿入して制御フローを強化し、より複雑な実行経路を作ります。 |
| ScrambleControlFlow | ブール値 | 有効にすると、無関係な分岐とジャンプ命令を挿入して「スパゲッティコード」を生成し、元の制御フローを大幅にわかりにくくします。 |
| MaxSwitchTargets | 整数 | switch による制御フロー難読化で許可する case の分岐先の最大数を設定し、生成される switch 文の複雑さを制御します。 |
| HideCaseConstantExpressions | ブール値 | 有効にすると、switch による制御フロー難読化で、リテラル値の代わりに計算式を使って、計算済みの定数値を隠します。 |
| RandomCall | ブール値 | 有効にすると、ランダムなメソッド呼び出し命令を追加して、解析をさらに混乱させます(switch による制御フローが有効な場合にのみ使用できます)。 |
| AddMethodToken (*) | ブール値 | 有効にすると、メソッドのフローにトークン読み込み命令を追加して制御フローを強化し、さらに複雑にします。 |
| StackUnderflow (*) | ブール値 | 有効にすると、評価スタックがアンダーフローする状態を作る命令を挿入し、静的解析を難しくします。 |
(*) これらのオプションは検証不可能な IL コードを生成します。アセンブリを部分信頼環境で実行する必要がある場合や、PEVerify の検証に合格する必要がある場合は、これらのオプションを有効にしないでください。
renaming
| プロパティ | 型 | 説明 |
|---|---|---|
| DisableOverloading | ブール値 | 有効にすると、オーバーロードリネームを無効にします。シグネチャの異なるメソッドは同じ名前を共有せず、それぞれ異なる難読化された名前になります。 |
| DisableUnicode | ブール値 | 有効にすると、難読化された名前に Unicode 文字を使用せず、名前を ASCII 文字だけに制限します。 |
| Internalize | ブール値 | 有効にすると、ルールに一致するすべてのパブリック型の可視性を public から internal に変更し、アセンブリの API サーフェスを小さくします。 |
| NameLength | 整数 | リネームされたシンボル名の長さを指定します。難読化された識別子をどの程度の長さにするかを制御できます。 |
| NamePrefix | 文字列 | リネームされたすべてのシンボルの先頭に付けるプレフィックス文字列を定義します。難読化された名前の識別や分類に役立ちます。 |
string encryption
| プロパティ | 型 | 説明 |
|---|---|---|
| MinInstructionCount | 整数 | ルールを適用するために必要な、メソッドの命令数の下限を設定します。命令数がこれより少ないメソッドは除外されます。 |
| MaxInstructionCount | 整数 | ルールを適用できる、メソッドの命令数の上限を設定します。命令数がこれより多いメソッドは除外されます。 |
merge
| プロパティ | 型 | 説明 |
|---|---|---|
| CopyAttributes | 文字列 | マージの際にソースアセンブリからターゲットアセンブリへコピーする属性を絞り込むための、カスタム属性の完全修飾型名または正規表現のコンマ区切りリスト。 |
| NoCopyAttributes | 文字列 | マージの際にターゲットアセンブリへコピーしない属性を絞り込むための、カスタム属性の完全修飾型名または正規表現のコンマ区切りリスト。 |
| Internalize | ブール値 | 有効にすると、ルールに一致するすべてのマージされた型の可視性を public から internal に変更し、外部のアセンブリから見えないようにします。 |
| MergeAction | Default/Discard/Redirect | 選択した型に対して行うマージの動作を指定します。Default は通常のマージを行い、Discard は型をマージから除外し、Redirect は参照をターゲットアセンブリ内の別の型(RedirectTo プロパティで指定)にリダイレクトします。 |
| RedirectTo | 文字列 | マージの動作に Redirect を指定した場合に、ソースの型を置き換えるターゲットアセンブリの型の完全修飾名を指定します。 |
msil encryption
| プロパティ | 型 | 説明 |
|---|---|---|
| Cache | ブール値 | 有効にすると、復号したメソッドをメモリにキャッシュします。JIT コンパイルは最初のアクセス時にだけ行われ、以降のパフォーマンスが向上します。 |
| Internal | ブール値 | 有効にすると、MSIL 暗号化されたコードをターゲットアセンブリ自体の内部に格納します。無効にすると、外部ファイルに格納します。 |
| Password | 文字列 | メソッドのコードの暗号化に使用するパスワードを指定し、保護レイヤーを 1 つ追加します。 |
| Source | 文字列 | 暗号化されたコードのソース識別子の名前を定義します。複数の暗号化ソースを整理するのに便利です。 |
| MinInstructionCount | 整数 | ルールを適用するために必要な、メソッドの命令数の下限を設定します。 |
| MaxInstructionCount | 整数 | ルールを適用できる、メソッドの命令数の上限を設定します。 |
optimizations
| プロパティ | 型 | 説明 |
|---|---|---|
| ClassSealing | ブール値 | 有効にすると、クラスのシールの最適化を適用します。派生型のないクラスを sealed(final)としてマークし、パフォーマンスを向上させます。 |
| ConstRemoval | ブール値 | 有効にすると、定数フィールドのメタデータを除去し、参照をコード内のリテラル値に直接置き換えます。 |
| DisgregateRemoval | ブール値 | 有効にすると、プロパティとイベントのメタデータを除去し、アセンブリのメタデータのサイズを減らします。 |
| EnumRemoval | ブール値 | 有効にすると、列挙型の定義を除去し、基になる整数型に置き換えます。 |
| UnwantedAttributes | ブール値 | 有効にすると、実装の詳細やデバッグ情報を露出するおそれのある不要なカスタム属性を除去します。 |
Description 要素
ルールの目的と動作を説明するテキストを指定します。この説明は難読化のログに表示されるため、難読化の処理を確認するときに、各ルールの働きを把握しやすくなります。
ルールの設定
ルールファイルは、コマンドライン、MSBuild の Babel タスク、Babel Desktop のいずれからでも Babel Obfuscator に渡せます。お使いのビルドに合った方法を選択してください。
コマンドライン
babel myapp.exe --rules babelRules.xml--rules オプションは、コマンドラインで複数回指定して、XML ルールファイルを追加できます。これにより、ルールを別々のファイルに整理し、必要に応じて組み合わせられます。
MSBuild の Babel タスク
<ItemGroup>
<RuleFile Include="babelRules.xml" />
</ItemGroup>
<Babel RulesFiles="@(RuleFile)" />Babel Obfuscator の RulesFiles オプションには、XML ルールファイルのリストを指定できます。このリストは、MSBuild プロジェクトファイルの ItemGroup 要素で定義できます。この方法では、複数のルールファイルを指定して、プロジェクト構造の中で簡単に管理できます。項目グループに列挙した各ルールファイルは、Babel Obfuscator への個別の入力として扱われ、コードベースの部分ごとに異なる難読化ルールと設定を指定するのに使えます。
外部の XML ルールファイルを使用するほかに、次のように Babel タスクの XmlRules 属性を使って、XML ルールの定義をプロジェクトファイルに直接埋め込むこともできます。
<PropertyGroup>
<XmlRules>
<Rules targetAssembly="Acme, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f66185f16ea61c16">
<Rule name="rule1" feature="msil encryption" exclude="false">
<Target>Methods</Target>
<Pattern>Acme.Engine*</Pattern>
<Description>Enable MSIL Code Encryption in Acme Engine</Description>
</Rule>
</Rules>
<Rules targetAssembly="Acme.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f66185f16ea61c16">
<Rule name="rule2" feature="control flow" exclude="true">
<Target>Methods</Target>
<Pattern>Acme.Entities.*</Pattern>
<Description>Disable Control Flow Obfuscation for EF classes</Description>
</Rule>
</Rules>
</XmlRules>
</PropertyGroup>
<Babel XmlRules="$(XmlRules)" />Babel Obfuscator でプロジェクト内の複数のターゲットアセンブリを処理する場合は、XML ルールの targetAssembly 属性を使って、ルールのセットを適用するターゲットアセンブリを指定できます。この属性では、バージョン、カルチャ、公開キートークンを含む完全修飾名で、特定のアセンブリを対象にできます。targetAssembly 属性を省略すると、ルールはプロジェクトで定義されたすべてのターゲットアセンブリに適用されます。
Babel Desktop
外部の XML ルールファイルを使用するには、プロジェクトのキャンバスでターゲットアセンブリを選択し、プロパティパネルの「ファイルと依存関係」グループにある RulesFiles にファイルを追加します。
ルールをインラインで記述するには、選択したアセンブリの「XML ルール」ビューを開きます(プロパティパネルの「XML ルール」タブ、または「設定 > 選択したアセンブリ > XML ルール」)。エディターは Babel の XML スキーマに照らしてルールを検証し、エラーを行と列とともに報告します。また、ルールドキュメントを XML ファイルとして開いたり保存したりできます。
インラインルールは、上の MSBuild の例と同じように、プロジェクトファイルの Babel タスクの XmlRules プロパティに格納されます。そのため、プロジェクトの構成と一緒に保存され、バージョン管理されます。Babel Desktop でのプロジェクトの扱い方は、難読化プロジェクトを参照してください。