名前変更は、Java バイトコードをよりコンパクトにし、リバース エンジニアリングをより困難にするために、PreEmptive Protection™ DashO™ がクラス、メソッド、フィールド、アノテーション、パッケージなどのエンティティの名前を変更するプロセスです。
ソース コードで指定するクラス、メソッド、フィールドなどの名前には、ソフトウェアの個々のコンポーネントが何を行うかを伝える豊富な情報が含まれています。 これらの名前は、さまざまな理由で生成されたバイトコードに保持されます。特定のクラスの main メソッドを呼び出したり、別のプロジェクトのメソッドを参照したりする場合、これらは重要となります。 ただし、ほとんどの場合、これらの名前はコンパイル後に不要であり、攻撃者がアプリケーションを理解しやすくするだけです。
名前の変更により、これらのセマンティック名を無意味な名前(a、b など)に置き換えることができます。
メモ: Android モードの場合、DashO は名前変更を R8 で処理させるため、DashO の名前変更は使用できません。 Android モードを使用する場合は、R8 を有効にしてください。
名前変更の構成
DashO GUI を使用するか、DashO プロジェクト ファイルを編集して、名前の変更を完全に有効または無効にすることができます。 また、クラス名を変更するかどうか、メンバー名を変更するかどうか、内部で定義されたアノテーションの名前を変更するかどうかも制御できます。
パッケージおよびクラス プレフィックス
クラスの名前を変更する場合は、クラスが配置されるパッケージを制御できます。 既定では、DashO はパッケージ階層をフラット化し、名前が変更されたすべてのクラスを同じパッケージ(既定では既定のパッケージ)に配置します。
| 元の名前 | 変更後の名前 |
|---|---|
yoyodyne.application.Main |
a |
yoyodyne.application.LoadData |
b |
yoyodyne.tools.BinaryTree |
c |
yoyodyne.tools.LinkedList |
d |
パッケージを指定するか、名前を変更した各クラスの名前の前にテキストを追加するために、クラス プレフィックス(Class Prefix)を指定できます。 上記の表にクラス プレフィックスを適用したいくつかのサンプルを次に示します。
| 元の名前 | 変更後の名前(yoyodyne. クラス プレフィックス付き) |
変更後の名前(yoyodyne.X_ クラス プレフィックス付き) |
|---|---|---|
yoyodyne.application.Main |
yoyodyne.a |
yoyodyne.X_a |
yoyodyne.application.LoadData |
yoyodyne.b |
yoyodyne.X_b |
yoyodyne.tools.BinaryTree |
yoyodyne.c |
yoyodyne.X_c |
yoyodyne.tools.LinkedList |
yoyodyne.d |
yoyodyne.X_d |
パッケージをフラット化しない場合、DashO は各クラスを元のパッケージに保持し、クラス自体の名前を変更するだけです。 前の例で、パッケージをフラット化せず、クラス プレフィックスのない名前を次に示します。
| 元の名前 | 変更後の名前(クラス プレフィックスなし) | 変更後の名前(internal.X_ クラス プレフィックス付き) |
|---|---|---|
yoyodyne.application.Main |
yoyodyne.application.a |
yoyodyne.application.internal.X_a |
yoyodyne.application.LoadData |
yoyodyne.application.b |
yoyodyne.application.internal.X_b |
yoyodyne.tools.BinaryTree |
yoyodyne.tools.c |
yoyodyne.tools.internal.X_c |
yoyodyne.tools.LinkedList |
yoyodyne.tools.d |
yoyodyne.tools.internal.X_d |
文字集合を構成する
クラスやメンバーの新しい名前を作成するために使用される文字集合を指定できます。 定義済みの文字集合の中から 1 つを選択するか、または独自の文字集合を入力することができます。 独自の文字集合を作成する際は、次の制限が適用されます。
- 文字集合の最小の長さは 2 文字です。 大きなプロジェクトに対しては、3 文字以上を使用することが推奨されます。
- 文字集合の初めの文字は、Java 識別子の開始文字として有効でなければなりません。 少なくとも 1 つは開始文字がある必要があります。
- 文字集合の残りの文字は、Java 識別子で有効な文字でなければなりません。
- 最小の長さ(minlength パラメーター)セクションで説明されているように、文字集合の文字数は、名前変更によって作成されるクラスまたはメンバーの名前に対して許可される長さに影響します。
この文字集合は、DashO GUI の Renaming - Options ページ、またはプロジェクトファイルの <renaming> 要素 で構成できます。
最小の長さ(minlength パラメーター)
このパラメーターには、名前変更で作成されるクラスまたはメンバーの名前の最小の長さを定義します。 たとえば、クラスの最小長を 3 に設定すると、DashO は aaa などのクラス名から始め、それ以上短い名前は生成されません。 このパラメーターに対して許可される最大値は、文字集合で定義されている文字数を考慮し、DashO によって計算されます。文字集合の文字数が少ないほど、値が大きくなります。したがって、値を増やしたい場合は、文字集合を短くする必要があります。たとえば、文字集合を abcdefghijklmnopqrstuvwxyz_0123456789 とした場合、このパラメーターの最大許容値は 6 になり、文字集合を abcdefghijklmno にした場合は、このパラメーターの最大許容値は 7 になります。 現在設定されている文字集合で、このパラメーターの最大許容値を超えた場合、ビルドは失敗し、DashO はパラメーターの現在の値と最大許容値を示すエラー メッセージを表示します(例:"Error: Classes renaming alphabet: Minimum length of 7 exceeds alphabet's maximum 6.")。
ランダム化された名前変更
DashO では、クラスやメンバーの名前を選択する順序をランダム化するように構成できます。 ランダムな名前変更が有効になっている場合、名前変更プロセスは、使用可能な最短の名前のプールから名前をランダムに選択します。 これにより、増分難読化機能がなければ、DashO の実行間でシーケンスの一貫性が失われます。
文字集合 abc が与えられた場合、DashO はランダムな名前変更を行わずに次の名前のシーケンスを生成します。
a, b, c, aa, ab, ac, ba, bb, bc, ca, cb, cc...
ランダムな名前変更では、代わりに次のシーケンスを選択する場合があります。
c, a, b, bc, ab, cc, bb, cb, ca, aa, cc, ac...
2 文字の名前が選択される前に、すべて 1 文字の名前が選択されることに留意してください。
エントリ ポイントおよび名前の変更の除外
static void main(String[]) メソッドやそれらを含むクラスなど、ソフトウェアの一部の要素が正しく動作する場合、それらを名前の変更から除外する必要がある場合があります。 これらは、エントリ ポイントとしてマークしたり、名前変更から除外したりすることができます。
リフレクション
クラスまたはそのメンバーがリフレクションを介してアクセスされる場合、リフレクションを適切に機能させるために、DashO でそれらクラスまたはそのメンバーの名前を変更できない場合があります。
Input - Options の[Determine Reflected Classes]チェックボックスをオンにすると、DashO はリフレクションを介してアクセスされるクラスを特定し名前変更から除外することで、リフレクション呼び出しを中断しないようにします。 さらに同じページで[Rename Reflected Classes]チェックボックスをオンにすると、リフレクション クラスを名前変更から除外する代わりに、文字列定数でこれらのクラスへの参照を更新して新しい名前に一致させようとします。 一般に、リフレクションを介してアクセスされるクラスおよびメンバーをエントリ ポイントとして手動でマークするか、名前変更から除外する方が信頼性が高くなります。
メモ: DashO は、メソッドまたはフィールドのリフレクションベースのアクセスを検出できません。
リフレクションの検出の詳細については、クラスの動的読み込みを参照してください。
割り当てファイル
DashOは、クラス、メソッドなどの元の名前を、保護されたソフトウェアで使用される名前に割り当てする名前変更割り当てファイルを作成できます。
これらのファイルは、例外によって生成されるスタック トレースを理解するのに役立ちます。 保護されたソフトウェアで例外が発生した場合、報告されたスタック トレースは、名前が変更されたパッケージ、クラス、およびメソッド名を使用します。 DashO では、ビルドから保存された名前変更割り当てファイルを使用してスタック トレースをデコードできます。 別の DashO Lucidator ユーティリティを使用して、これらのスタック トレースをデコードすることもできます。 増分難読化を使用する場合は、名前変更割り当てファイルも必要です。
DashO GUIの Renaming - Map Files ページで、DashO が結果の割り当てファイルを配置する場所と、増分難読化の入力割り当てファイルの場所を構成できます。 既定の DashO 互換割り当てファイルに加えて、R8/ ProGuard 互換割り当てファイルを作成して、それらに依存するサード パーティ製ツールで使用できます。
このファイルを不注意で失ってしまうと、将来のアプリケーションの増分更新の機会を失う可能性があります。 そのため、このファイルを適切にバックアップしておくことが非常に重要になります。 このような理由から、DashO は既存のファイルが検出された場合には、自動的にこのファイルを上書きしないようになっています。 DashO GUIの Renaming - Map Files ページで[Overwrite]チェックボックスをオンにすると、DashO がこのファイルを上書きできるようになります。
名前の変更レポート
DashO は、さらに人間が読み取れる名前変更レポート ファイルを提供できます。 これは、DashO GUIの Output - Reports ページで指定できます。
オーバーロード誘導™
DashO は、オーバーロード誘導と呼ばれる手法を使用して、オーバーロードを介して個々のメソッド名を最大限に再利用できるようにします。 たとえば、オーバーロード誘導が有効になっている場合、メソッド foo()、メソッド bar(int)、およびメソッド baz(String) は、異なる署名を持つ a()、a(int)、および a(String) に名前を変更できます。 そうではなく、単純な名前変更が有効になっている場合、foo()、bar(int)、および baz(String) はすべて完全に異なる名前(a()、b(int)、および c(String) など)に変更されます。
オーバーロード誘導を使用して短い名前を再利用すると、コードがわかりにくくなり、バイトコードがコンパクトになります。 処理されたクラスで名前を定義するために必要な定数のプール エントリ数を減らします。また、ベースとなる名前が短いため、必要なエントリはかなり少ないスペースを占有します。
DashO GUI の Renaming - Options ページを使用して、オーバーロード誘導を有効または無効にできます。