美文网首页Android
so库中JNI方法混淆

so库中JNI方法混淆

作者: bujue | 来源:发表于2017-04-07 11:23 被阅读803次

    so库中JNI方法混淆

    例如java中调用jni方法的类如下图所示

    此方法的C++代码如下图所示

    我们将运行后生成的so库文件进行反汇编得到如下内容

    即能看到调用的so库中的C++代码的方法名

    接下来要做的就是混淆这个方法名,将方法隐藏起来,反汇编之后找不到对应的方法,类似于Android中的混淆,加大了破解的难度。

    这种方法的特点是:

    • 源码改动少,只需要添加JNI_Onload函数
    • 无需加解密so,就可以实现混淆so中的JNI函数
    • 后续可以添加so加解密,使破解难度更大

    混淆步骤如下

    一、在jni目录下新建一个.cpp文件,文件名任意

    二、.cpp文件的内容如下:

    #include <assert.h>
    #include <stdio.h>
    #include "longrise_phone_xjbjjt_com_myrecyclerviewapp_JniUtils.h"
    
    #define JNIREG_CLASS "longrise/phone/xjbjjt/com/myrecyclerviewapp/JniUtils"//指定要注册的类
    
    
    __attribute__((section (".mytext"))) JNICALL jstring getStringc(JNIEnv *env, jclass obj) {
        return  (env)->NewStringUTF("hello world2");
    }
    /**
    * Table of methods associated with a single class.
    */
    //绑定,注意,V,Z签名的返回值不能有分号“;”
    //这里就是把JAVA层的getStringFromC()函数绑定到Native层的getStringc()函数,就无需使用原生的Java_com_xx_xx_classname_methodname这种恶心的函数命名方式了
    static JNINativeMethod gMethods[] = {
            { "getStringFromC", "()Ljava/lang/String;", (void*)getStringc},
    
    };
    
    
    /*
    * Register several native methods for one class.
    */
    
    static int registerNativeMethods(JNIEnv* env, const char* className,
                                     JNINativeMethod* gMethods, int numMethods)
    {
        jclass clazz;
        clazz = (env)->FindClass(className);
        if (clazz == NULL) {
            return JNI_FALSE;
        }
        if ((env)->RegisterNatives(clazz, gMethods, numMethods) < 0) {
            return JNI_FALSE;
        }
    
        return JNI_TRUE;
    }
    
    
    /*
    * Register native methods for all classes we know about.
    */
    
    static int registerNatives(JNIEnv* env)
    {
        if (!registerNativeMethods(env, JNIREG_CLASS, gMethods,
                                   sizeof(gMethods) / sizeof(gMethods[0])))
            return JNI_FALSE;
    
        return JNI_TRUE;
    }
    
    
    /*
    * Set some test stuff up.
    *
    * Returns the JNI version on success, -1 on failure.
    */
    
    jint JNI_OnLoad(JavaVM* vm, void* reserved)
    {
        JNIEnv* env = NULL;
        jint result = -1;
    
        if ((vm)->GetEnv( (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
            return -1;
        }
        assert(env != NULL);
    
        if (!registerNatives(env)) {//注册
            return -1;
        }
    
    /* success -- return valid version number */
    
        result = JNI_VERSION_1_4;
    
        return result;
    }
    

    这里的关键是,在函数前加上attribute((section (“.mytext”))),这样的话,编译的时候就会把这个函数编译到自定义的名叫”.mytext“的section里面去了。

    三、文件中要修改和注意的地方

    四、隐藏符号表,在Android.mk文件里面添加一句LOCAL_CFLAGS := -fvisibility=hidden

    五、这几步做完之后

    此处getstringfromc这个方法可以删除掉,java调用c++中的getstringfromc这个方法时,将会自动去找getstringc而不再是原来的getstringfromc,至此达到了混淆so库中c的方法名的目的

    混淆后再次反编译so库

    相关文章

      网友评论

        本文标题:so库中JNI方法混淆

        本文链接:https://www.haomeiwen.com/subject/pmfhattx.html