cec*_*n89 6 obfuscation java-native-interface android native
我有混淆的问题.为了更好的想象力:
JAVA CODE
class JniTest...
public void test()
{
//some code
}
public void runJniCode()
{
//here I call native code
}
Run Code Online (Sandbox Code Playgroud)
本地代码
JNIEXPORT void JNICALL
Java_path_to_class_test(JNIEnv* env, jobject obj)
{
//here I call test method from Java
}
Run Code Online (Sandbox Code Playgroud)
一切正常,直到我想发布一个混淆版本.此类中的Java类(JniTest例如)和方法test的名称由proguard重命名为"a"和"a()"(这可能并不总是相同),但在本机代码中,方法和类的原始名称保持,因为它被硬编码为字符串,如:
jmethodID mid = env->GetMethodID(cls, "test", "someSignature");
Run Code Online (Sandbox Code Playgroud)
...有没有办法动态设置方法名称?
在研究这个完全相同的问题时,我遇到了一个我认为合理的解决方案.不幸的是,该解决方案不会按要求自动模糊本机Java代码和JNI方法,但我仍然认为值得分享.
从来源引用:
我在这里介绍一个简单的技巧,它允许混淆JNI层,在Java和本机端将方法名称重命名为无意义的名称,同时保持源代码相对可读和可维护,并且不影响性能.
让我们考虑一个例子,初始情况:
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);
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,Proguard无法模糊方法名称rotateRGBA,它在Java端和本机端仍然可见.
解决方案是在源代码中直接使用无意义的方法名称,同时注意尽可能地降低代码的可读性和可维护性.
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);
Run Code Online (Sandbox Code Playgroud)
JNI方法被重命名为无意义的a.但Java方面的调用由有意义的方法rotateRGBA包装.Java客户端继续像以前一样调用Native.rotateRGBA(),而不会受到重命名的影响.
有趣的是,新的Native.rotateRGBA方法不再是原生的,因此可以由Proguard随意重命名.结果是,名称rotateRGBA完全从混淆代码中消失,在Dalvik和本机端.更重要的是,Proguard优化了包装器方法,从而消除了包装本机调用的(可忽略的)性能影响.
结论:从混淆代码(Dalvik字节码和本机库)中消除了JNI方法名称,对可读性的影响最小,没有性能影响.
来源:混淆JNI表面层
我仍然在寻找一种可以自动混淆原生Java代码和相关JNI的工具.
基于 AndrewJC 的答案,如果您的应用程序使用 Kotlin,您还可以使用@JvmName注释而不是使用包装方法,例如:
object Native {
@JvmName("a")
private external fun rotateRGBA(rgb: Int, w: Int, h: Int): Int
}
// rotateRGBA
extern "C" int Java_mypackage_Native_a(JNIEnv *env, jclass, int rgb, int w, int h);
Run Code Online (Sandbox Code Playgroud)
现在您可以在 Kotlin 中调用 JNI 方法,Native.rotateRGBA(0, 200, 400)但是编译时,Kotlin 会自动将您的方法调用重命名为:Native.a。