6

難読化に問題があります。より良い想像力のために:

ジャバコード

class JniTest...

public void test()
{
    //some code
}

public void runJniCode()
{
    //here I call native code
}

ネイティブコード

JNIEXPORT void JNICALL
Java_path_to_class_test(JNIEnv* env, jobject  obj)
{
    //here I call test method from Java

}

難読化されたバージョンをリリースするまで、すべてが正常に機能します。Java クラス (JniTestたとえば)の名前とtestこのクラスのメソッドは、proguard によって "a" と "a()" に名前が変更されます (これは常に同じであるとは限りません) が、ネイティブ コードではメソッドとクラスの元の名前次のように文字列としてハードコーディングされているため、残ります。

jmethodID mid = env->GetMethodID(cls, "test", "someSignature");

...メソッド名を動的に設定する方法はありますか?

4

3 に答える 3

10

While researching this exact same problem I came across a solution which I think is reasonable. Unfortunately, the solution does not automatically obfuscate the native Java code and JNI methods as requested, but I still thought it would be worth sharing.

Quote from the source:

I present here a simple trick which allows obfuscation of the JNI layer, renaming the method names to meaningless names on both the Java and native side, while keeping the source code relatively readable and maintainable and without affecting performance.

Let’s consider an example, initial situation:

class Native {
    native static int rotateRGBA(int rgb, int w, int h);
}

extern "C" int Java_pakage_Native_rotateRGBA(JNIEnv *env, jclass, int rgb, int w, int h);

In the example above Proguard can’t obfuscate the method name rotateRGBA, which remains visible on the Java side and on the native side.

The solution is to use directly a meaningless method name in the source, while taking care to minimally disrupt the readability and maintainability of the code.

class Native {
    private native static int a(int rgb, int w, int h); //rotateRGBA

    static int rotateRGBA(int rgb, int w, int h) {
        return a(rgb, w, h);
    }
}

// rotateRGBA
extern "C" int Java_pakage_Native_a(JNIEnv *env, jclass, int rgb, int w, int h);

The JNI method is renamed to a meaningless a. But the call on the Java side is wrapped by the meaningfully named method rotateRGBA. The Java clients continue to invoke Native.rotateRGBA() as before, without being affected at all by the rename.

What is interesting is that the new Native.rotateRGBA method is not native anymore, and thus can be renamed by Proguard at will. The result is that the name rotateRGBA completely disappears from the obfuscated code, on both Dalvik and native side. What’s more, Proguard optimizes away the wrapper method, thus removing the (negligible) performance impact of wrapping the native call.

Conclusion: eliminated the JNI method name from the obfuscated code (both Dalvik bytecode and native library), with minimal impact to readability and no performance impact.

Source: Obfuscating the JNI surface layer

I'm still on the hunt for a tool which can obfuscate native Java code and the associated JNI automatically.

于 2014-01-20T20:10:05.377 に答える