Android功守道-so库混淆加密

Android

Android NDK开发中加密so库,旨为保护自己的开发成果。

so反编译

使用IDA工具反编译so文件,破解分析时,很容易查看到so文件里,被Java层调用的函数,以及一些加密算法等等信息,进一步破解应用代码。
但是这种是我们不想见到的,我们希望把一些核心功能或者数据加密,如key,这就引入了so文件加固。

so加固

原理:JNI_OnLoad方法,当在系统中调用System.loadLibrary函数时,该函数会找到对应的动态库,然后首先试图找到”JNI_OnLoad”函数,如果该函数存在,则调用它。JNI_OnLoad可以和JNIEnv的registerNatives函数结合起来,实现动态的函数替换。

  1. CMakeList开启配置,隐藏符号表
    编辑Android Studio工具的CMakeList文件,添加下面两个语句:

    1
    2
    set(CMAKE_C_VISIBILITY_PRESET hidden)	# C语言写法
    set(CMAKE_CXX_VISIBILITY_PRESET hidden) # C++写法
  2. 注册JNI_OnLoad方法,函数对照表

    • 记录调用C代码的Java文件路径

      1
      static const char *JNI_REG_CLASS = "com/excellence/test/tool/KeyUtils";
    • gMethods方法替换
      将native方法getKey,指向gK,这样反编译就查不到getKey方法。

      1
      2
      3
      static JNINativeMethod gMethods[] = {
      {"getKey", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) gK},
      };

      JNINativemethod中结构体的定义:

      1
      2
      3
      4
      5
      6
      7
      8
      typedef struct {
      // Java中函数的名字
      const char* name;
      // 描述了Java中函数的参数和返回值
      const char* signature;
      // fnPtr是函数指针,指向native函数。前面都要接 (void *)
      void* fnPtr;
      } JNINativeMethod;
    • 在JNI调用的C文件里注册

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      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;
      }

      static int registerNatives(JNIEnv *env) {
      if (!registerNativeMethods(env, JNI_REG_CLASS, gMethods,
      sizeof(gMethods) / sizeof(gMethods[0])))
      return JNI_FALSE;

      return JNI_TRUE;
      }

      jint JNI_OnLoad(JavaVM *vm, void *reserved) {
      JNIEnv *env;
      if (vm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK) {
      return -1;
      }
      assert(env != NULL);

      //注册
      if (!registerNatives(env)) {
      return -1;
      }

      return JNI_VERSION_1_6;
      }

这样加固了so文件,就可以做到一定的保护作用,使用IDA工具查看,会起到混淆的作用。

谢谢老板,请尽情用红包来蹂躏我吧!!!
0%