2011-04-17 7 views
2

私は2つの一般的な解決策があるように思われることがわかった: コードが難読化される場合、常にReflection APIを使用できますか?

  • [JobfuscateRetroguard]リフレクションAPIを介して呼ばれるものを難読化していない

    1. は、難読化された名前のリフレクションAPIの呼び出しで文字列を置換します。

    これらのソリューションは、同じプロジェクト内の呼び出しでのみ機能します。クライアントコード(別のプロジェクト)は、非公開APIメソッドにアクセスするためにリフレクションAPIを使用できません。

    2の場合、Reflection APIがコンパイル時に知られている文字列(プライベートメソッドのテスト?)で使用されている場合にのみ機能します。そのような場合には、dp4jは難読化の後に反射コードを注入する解決法も提供します。

    ProGuardのが自動的に Class.forNameの( "工ass")と SomeClass.classなどの 構造を扱う:2がそうでなければ、常にそれが言うとき働いていた場合

    Proguard FAQを読んで、私は疑問に思いました。参照された クラスは、縮退する フェーズで保持され、文字列引数は、難読化 フェーズで正しく置き換えられます( )。

    可変文字列引数では、一般には の可能な値を決定することはできません。

    Q:太字の文は何を意味しますか?どんな例?

  • 答えて

    2

    可変文字列引数では、一般的に可能な値を決定することはできません。

    public Class loadIt(String clsName) throws ClassNotFoundException { 
        return Class.forName(clsName); 
    } 
    

    あなたはClass.forNameのに非定数文字列を渡す場合は基本的に、ProGuardのための方法や、あなたが話しているか、クラスを把握するために任意の難読化ツールは、一般的にありませんので、自動的に調整することはできませんあなたのためのコード。

    +0

    大丈夫です。つまり、文字列はコンパイル時にはわかりません。つまり、このケースのサブセット(つまり、コンパイラーがそれを理解できないときはいつでも)です。 – simpatico

    +0

    が正しい。実際、上記のサンプルは、理論的には反射を介して読み込まれるクラスの100を意味する可能性があります。 – MeBigFatGuy

    1

    それは、このことを意味します

    String className; 
    if (Math.random() <= 0.5) className = "ca.simpatico.Foo"; 
    else className = "ca.simpatico.Bar"; 
    Class cl = Class.forName(className); 
    

    は、難読化後に動作しません。 ProGuardは、十分な深さのデータフロー解析を行って、読み込まれるクラス名が2つの文字列リテラルから来ていることを確認していません。

    本当に、唯一のもっともらしい選択肢は、どのクラス、インターフェイス、およびメソッドがリフレクションを通じてアクセス可能であるかを判断し、それを難読化しないことです。あなたは、クライアントに奇妙な種類のAPIを効果的に定義しています.1つは、反射的にしかアクセスされません。

    2

    Zelix KlassMaster Java obfuscatorは、すべてのReflection API呼び出しを自動的に処理できます。それには、 "暗号化された古い名前"を "難読化された名前"ルックアップテーブルに使用するAutoReflectionと呼ばれる関数があります。

    ただし、同じ難読化されたプロジェクト内のコールに対してのみ機能します。

    http://www.zelix.com/klassmaster/docs/tutorials/autoReflectionTutorial.htmlを参照してください。

    関連する問題