サンプルルール
Babel Obfuscator の難読化処理を調整するために、独自の XML ルールを作成できます。これらのルールは、難読化ツールが特定のクラス、メソッド、プロパティなどをどう扱うかを決めます。きめ細かく制御できるため、難読化ツールの結果を細かく調整できます。このセクションでは、Babel Obfuscator の XML ルールの例をいくつか紹介します。
クラスのリネームを無効にする
Babel Obfuscator の XML ルールで特定のクラスのリネームを無効にするには、次の XML ルールを使用します。
<Rule name="disable-myclass-renaming" feature="renaming" exclude="true"
applyToMembers="true">
<Target>Classes</Target>
<Pattern>MyNamespace.MyClass</Pattern>
<Description>Disable renaming for MyClass.</Description>
</Rule>注:
MyNamespace.MyClass は、リネームから除外するクラスの完全修飾名に置き換えてください。
feature属性は「renaming」に設定されており、リネーム機能を対象にします。exclude属性は「true」に設定されており、指定したクラスのリネームを防ぎます。applyToMembersは「true」に設定されており、クラスのメンバーのリネームを防ぎます。Target要素は、ルールがクラスに適用されることを指定します。Pattern要素は、クラスの完全修飾名を指定します。
コンパイラー生成コード
次のルールは、コンパイラーが生成したコードに対して、一部の高度な難読化機能を適用しないようにします。
<Rule name="no-compiler-generated"
feature="control flow, value encryption, string encryption"
exclude="true" applyToMembers="false">
<Target>Classes</Target>
<Pattern>*</Pattern>
<HasAttribute onEnclosingType="false">
System.Runtime.CompilerServices.CompilerGeneratedAttribute,
System.Diagnostics.DebuggerHiddenAttribute
</HasAttribute>
<Description>Do not obfuscate compiler-generated methods.</Description>
</Rule>匿名型
C# の匿名型とは、new 演算子とオブジェクト初期化子を使って、名前を付けずに定義する型です。
var query =
from prod in products
select new { prod.Name, prod.Price };
foreach (var v in query)
{
Console.WriteLine("Name={0}, Price={1}", v.Name, v.Price);
}これにより、あらかじめ特定の型を定義しなくても、その場でオブジェクトを作成できます。コンパイラーは匿名型の型名を生成し、その名前は通常 <>f__Anonymous という文字で始まります。生成された名前は一意で、開発者が使用するためのものではありません。
匿名型は、LINQ クエリのほか、ASP.NET Web アプリケーションのように、その場でオブジェクトを作成する必要がある場面で広く使われています。
難読化では、生成された名前が難読化される可能性があるため、匿名型が問題になることがあります。匿名型をリネームすると、それを使用するコードで問題が起こる場合があるため、多くの場合は難読化から除外することが推奨されます。
その方法の 1 つは、次の属性を持つすべてのシンボルを対象とするルールを追加することです。
System.Runtime.CompilerServices.CompilerGeneratedAttribute
これにより、匿名型を含め、コンパイラーが生成したコードがすべて除外されます。
<Rule name="rule1" feature="renaming, dead code" exclude="true" applyToMembers="true">
<Pattern>*</Pattern>
<HasAttribute>System.Runtime.CompilerServices.CompilerGeneratedAttribute</HasAttribute>
</Rule>もう 1 つの方法は、正規表現パターンを使ってインライン型の名前に一致させることです。これらの型には通常、<>f__Anonymous というプレフィックスが付いています。
<Pattern isRegEx="true">
<![CDATA[<>f__Anonymous.*]]>
</Pattern>ILSpy や dotPeek などの .NET アセンブリインスペクターで匿名型の名前を確認すれば、この規則に従っているかどうかを確かめられます。
動的プロキシの呼び出しフィルターの使用
動的プロキシの呼び出しフィルターは、Babel Obfuscator で動的プロキシの生成を細かく調整し、最適なパフォーマンスを保ちながら目的のレベルの難読化を得るのに役立ちます(動的プロキシを参照してください)。
<Rule name="rule1" feature="dynamic proxy" exclude="false" applyToMembers="true">
<Pattern>*</Pattern>
<Description>Set Dynamic Proxy Call Filters</Description>
<Properties>
<DynamicProxyCallFilters>IEnumerator.*;ICollection.*</DynamicProxyCallFilters>
</Properties>
</Rule>この XML ルールは、Babel で動的プロキシの呼び出しフィルターを設定する構成を表しています。
動的プロキシの呼び出しフィルターを設定すると、どのメソッド呼び出しを捕捉して動的プロキシに置き換えるかを正確に定義できます。これにより、コードの重要な部分を保護しつつ、ほかの部分はそのままにできます。フィルターには正規表現を指定できるため、プロキシ化が必要な特定のメソッド命名パターンや動作に合わせて、ルールを柔軟に調整できます。こうして、アプリケーション固有の要件に応じて、難読化と保護の方針を調整できます。
難読化エージェントの制御
Babel Obfuscator の難読化エージェントは、あらかじめ定義されたルールに基づいて、難読化の処理中に一連のタスクを実行します。その主な目的は、難読化によって生じ、結果のアセンブリを壊すおそれのある問題を防ぐことです。たとえばエージェントは、リフレクションで使用されるシンボルが難読化されないようにします。難読化すると実行時エラーにつながることがあるためです。エージェントが実行するタスクは、シリアル化可能な型のフィールドの確認のような単純なチェックから、MSIL コードの静的解析を伴う複雑な処理までさまざまです。
難読化エージェントは、難読化されたコードを問題なく動作させるうえで欠かせません。それでも、特定の難読化結果を得るために、一部のエージェントタスクを無効にする必要がある場合があります。
XML ルールで特定のエージェントタスクをスキップするには、agent 機能を対象とする除外ルールを定義します。たとえば、「Serializable types」や「Reflected strings」などのタスクを無効にする XML ルールは、次のようになります。
<Rule name="rule1" feature="agent" exclude="true">
<Pattern>ACME.Data.*</Pattern>
<Properties>
<TaskNameList>Serializable types;Reflected strings</TaskNameList>
</Properties>
</Rule>まとめると、難読化エージェントは難読化されたコードを支障なく動作させるうえで中心的な役割を果たしますが、目的の難読化結果を得るために特定のタスクを無効にする必要がある場合もあります。その際は、無効にする各タスクが最終的なアプリケーションに与える影響を理解したうえで、慎重に行うことが重要です。