名前の変更
概要
Dotfuscator にはすべてのクラス、メソッド、およびフィールドを短い名前に変更する機能があります。 この機能により、逆コンパイルの出力を非常に理解しづらくするだけでなく、生成される実行可能ファイルのサイズを小さくすることができます。
大部分の商用難読化プログラムは、1 文字程に短い意味のない識別子を適用する名前変更技法を採用しています。 難読化プログラムはコードを処理する際、次に利用可能な意味のない識別子を置き換え用として選択します。 この表面上単純な名前変更方式は、キー属性を持っています。それは元に戻すことはできません。 プログラム ロジックを保持しますが、名前の意味はわからなくなり、コードを解釈するすべての試みを防げます。
オーバーロード誘導
Dotfuscator は PreEmptive Solutions が Dotfuscator のために開発した特許取得済みのオーバーロード誘導™ を、より厳重な難読化に使用します。 オーバーロード誘導は、1 つの古い名前を 1 つの新しい名前に置き換えていくのではなく、できる限り多くのメソッドの名前を同じ名前に変更します。 このように厳重に難読化を行うと、ロジックは壊れませんが、理解不能になります。 実際の例を見てみましょう。次の簡単な例で、オーバーロード誘導技術の威力が理解できます。
難読化前のソース コード:
private void CalcPayroll(SpecialList employeeGroup) {
while (employeeGroup.HasMore()) {
employee = employeeGroup.GetNext(true);
employee.UpdateSalary();
DistributeCheck(employee);
}
}
オーバーロード誘導難読化を行った後のリバース エンジニアリングされたソース コード:
private void a(a b) {
while (b.a()) {
a = b.a(true);
a.a();
a(a);
}
}
この例では、コードが難読化され、かつサイズが小さくなっていることがわかります。これは名前変更による有利な副作用です。
たとえば、20 文字の長さの名前の場合、名前を a()
に変更するとサイズは 95% 縮小されます。
また、名前の変更は文字列ヒープ エントリを節約することでも領域を節約します。
すべての名前を "a
" に変更するということは、a
が 一度だけ格納されることを意味し、名前が a
に変更されたメソッドあるいはフィールドは、それぞれがその名前をポイントできるのです。
オーバーロード誘導は、最短の識別子を連続的に再使用するので、この効果を高めます。
多くのお客様から、全メソッドの最大 1/3 が "a()
" という名前に変更されたという報告をいただいています。
この方法には明確な利点がいくつかあります。
- 名前の変更は、逆コンパイルした出力を理解しづらくします。
しかしながら、逆コンパイラは印字不能文字あるいは、対象ソース言語では無効な名前を再度変更する機能を備えているため、識別子をそのような名前に変更することは無意味です。
一方、オーバーロード誘導でメソッドの 1/3 の名前が "
a()
" になることを考慮すると、逆コンパイルした出力を理解することは間違いなく困難になります。 - オーバーロード誘導は、あらゆる名前変更システムに共通する制限以外の制限は受けません。
- オーバーロード誘導は同じ文字を頻繁に使用する傾向があるので、文字数の多い名前(
aa
、aaa
など)になるまでには時間がかかります。 この点でも領域を節約します。
米国で特許を取得したオーバーロード誘導のアルゴリズムは、発生する可能性のあるすべての名前変更の衝突を判断し、安全な場合にのみメソッドのオーバーロードを誘導します。 この処理が不可逆であることは実証可能です。 つまり、(再度オーバーロード誘導を実行しても)元のメソッド名の関係を再構築するのは不可能です。
拡張オーバーロード誘導
Dotfuscator は、メソッドの戻り値の型またはフィールドの型を、メソッドまたはフィールドの一意性を判断するときの条件として使用できるようにすることによって、拡張オーバーロード誘導(Overload-Induction™)を提供します。 この機能により、名前変更されたメソッド名およびフィールド名の重複性を最大 15% まで高めることができます。 さらに、戻り値の型やフィールドの型によるオーバーロードは(C#、Visual Basic などの)ソース言語では通常は許可されていないので、逆コンパイルをいっそう困難なものにします。
制限事項
XAML コードを含んでいるアセンブリについては、実行時に XAML とコードのリンク方法が決定されることから、通常、オーバーロード誘導は実行されません。 結果として、[拡張オーバーロード誘導を使用する]オプションによって、このようなアセンブリが変更されることはありません。
何らかの種類のリフレクション(XAML を含む)、エントリ ポイントを指定する構成ファイル、他のアプリケーションから呼び出されるライブラリなどを使用している場合に、名前の変更で問題が発生することがあります。 名前の変更後、そのような問題が存在しなくなったことを確認できるまでアプリケーションを十分にテストする必要があります。
特定の対象除外
Dotfuscator は、ライブラリ モードがオフになっているものと仮定して、できる限りすべての名前を変更しようとします。 リフレクションの特定の使用法が原因で、Dotfuscator は名前の変更時に、特定のエンティティへのすべての参照を更新できないことがあります。 次の例では、4 つのクラスとそのフィールドを対象から除外しています。
この例のアプリケーションは、これらの型やメンバーを参照する場合、リフレクションを使用してそれらの名前を検索しています。 名前が変更されると、アプリケーションは実行時にそれらを見つけられなくなる可能性があります。 そのため、対応するチェック ボックスを使用して、名前の変更処理の対象からこれらを除外しています。
カスタム対象除外規則
特定のコーディング規約のために、多数の特定の対象除外を作成しなければならない状況がある可能性があります。 作成した後も、開発者はその規約に従うコードを追加した場合には、その新しいコードのために、さらにもう 1 つ特定の対象除外を作成することを覚えておかなければなりません。
これの解決策が、カスタム対象除外規則です。 前の例から、型名が "Dungeon" で終わるすべての型と、それらの型内の特定の型のフィールドは、何らかの理由で名前の変更対象から除外される必要があることがわかったとします。多数の特定の対象除外を作成するかわりに、1 つのカスタム規則を作成することができます。
規則は右ペインに表示されます。
[型の追加]ボタンを使って規則のルート ノードを追加し、それに .*Dungeon
という名前を付けます。正規表現(regex
)オプションを true
に設定して、この名前を正規表現として扱う必要があることを示します。
これにより、ノードは、型名が "Dungeon" で終わる型と一致します。
[型を除外する](excludetype
)を true
に設定しているので、この名前に一致するあらゆる型が名前の変更対象から除外されます。
もし、このオプションを false
に設定した場合には、一致する型は名前の変更対象から除外されません。それらの子ノードによって指定されるメンバーのみが除外されます。
次に、ルート ノードを右クリックし、この場合は[フィールドの追加]を選択して子ノードを追加します。
このノードの名前を .*
とし、この名前も正規表現として扱う必要があることを示します。
パブリック アクセス修飾子を持ち(+public
を設定する)、署名が string[]
であるフィールドのみを対象とするように規則を制限します。このシナリオには両方が必要です。
規則が構成されたら、ノードを選択して[プレビュー]ボタンをクリックすることができます。クリックすると、左側のツリー ビューで、カスタム規則に一致するエントリが強調表示されます。 この例では、子ノードをプレビューしているので、条件に一致するフィールドが強調表示されています。 "AdventureGame.Validation" の "Key" フィールドは除外されていないことに注目してください。これは、フィールドはこの子ノードに一致していますが、その親の型は親ノードに一致していない(つまり、クラス名 "Validation" は "Dungeon" で終わっていない)からです。
この結果として生じるカスタム規則の構成は、XML として構成ファイルに格納されます。 この例では、次のような設定の XML が生成されます。
<type name=".*Dungeon" regex="true">
<field name=".*" speclist="+public" signature="string[]" regex="true" />
</type>
組み込み規則
組み込み規則は、普遍的にかなり役立つカスタム対象除外規則です。既定で組み込まれているため、ユーザーはそれらを再実装する必要はありません。
それぞれの正確な定義は、%ProgramData%\PreEmptive Solutions\Common\dotfuscatorReferenceRule_v1.4.xml
に記載されています。
たとえば、System.Web.Services 属性を持つメソッドは、次のカスタム規則に変換されます。
<excludelist>
<type name=".*" regex="true" excludetype="false">
<comment>System.Web.services 名前空間の属性で修飾されたすべてのメソッドを除外します。</comment>
<method name=".*" regex="true">
<customattribute name="System.Web.Services.*" regex="true" />
</method>
</type>
</excludelist>
オプション
[名前の変更]の[オプション]タブには、利用できる名前の変更オプションが多数あります。どの名前の変更規則を使用するか、明示的なメソッドのオーバーライドを導入するかどうかなど、その他多くのオプションが含まれます。 これらについては、[名前の変更]エディター セクションに詳しく説明されています。