オーバーロード誘導によるメソッドの名前の変更
Dotfuscator は、メソッドの名前を変更するOverload-Induction™ (オーバーロード誘導) という米国で特許を取得したテクノロジを実装しています。名前変更システムの大部分が、単に古い名前 1 つにつき新しく 1 つの名前を割り当てる (つまり、"getX()
" が "a()
" に、"getY()
" が "b()
" になる) のに対し、オーバーロード誘導はメソッドのオーバーロードを最大限に誘導します。その根底にある考え方は、アルゴリズムに可能な限り多くの名前をまったく同じ名前に変更させようというものです。多くの顧客から、すべてのメソッドの最大 33% が "a()" という名前に変更されたという報告をいただいています。このような場合、この数字は名前を変更可能なメソッドの最大 50% に相当します。「名前を変更可能な」と言ったのは、コンストラクタや "クラス コンストラクタ"、およびランタイムによる呼び出しを想定したメソッドなどを始めとする多くのメソッドはもともと名前を変更できないためです。
このように厳重に難読化を行うと、ロジックは壊れませんが、理解不能になります。実際の例を見てみましょう。次の簡単な例で、オーバーロード誘導技術の威力が理解できます。
難読化前のソース コード |
---|
private void CalcPayroll(SpecialList employeeGroup) { while (employeeGroup.HasMore()) { employee = employeeGroup.GetNext(true); employee.UpdateSalary(); DistributeCheck(employee); } } |
Dotfuscator によるオーバーロード誘導を行った後のリバース エンジニアリングされたソース コード |
---|
private void a(a b) { while (b.a()) { a = b.a(true); a.a(); a(a); } } |
この例でわかるのは、難読化後のコードの方がサイズが小さくなっていることです。名前の変更での良い副作用は、サイズが小さくなることです。たとえば、20 文字の長さの名前の場合、a()
に名前を変更すると、領域は大幅に (具体的には 19 文字分) 節約されます。また、名前の変更は文字列ヒープ エントリを節約することでも領域を節約します。すべての名前を "a
" に変更するということは、"a
" が 1 度だけ格納されることを意味し、名前が "a
" に変更されたメソッドあるいはフィールドは、それぞれがその名前をポイントできるのです。オーバーロード誘導は、最短の識別子を連続的に再使用するので、この効果を高めます。
この方法には明確な利点がいくつかあります。
長い間、名前の変更は、逆コンパイルした出力を理解しづらくする方法でした。しかしながら、逆コンパイラは印字不能文字 (あるいは、対象ソース言語では無効な名前) を再度変更する機能を備えているため、識別子をそのような名前に変更することは無意味です。一方、オーバーロード誘導でメソッドの 3 分の 1 の名前が "a()" になることを考慮すると、逆コンパイルした出力を理解することは間違いなく困難になります。
オーバーロード誘導は、あらゆる名前変更システムに共通する制限以外の制限は受けません (そのような制限については後で説明します)。
オーバーロード誘導は同じ文字を頻繁に使用する傾向があるので、(aa、aaa など) 文字数の多い名前になるまでには時間がかかります。この点でも領域を節約します。
米国で特許を取得したオーバーロード誘導のアルゴリズムは、発生する可能性のあるすべての名前変更の衝突を判断し、安全な場合にのみメソッドのオーバーロードを誘導します。この処理が不可逆であることは実証可能です。つまり、(再度オーバーロード誘導を実行しても) 元のメソッド名の関係を再構築するのは不可能です。
© 2002-2007 PreEmptive Solutions. All rights reserved.