Android开发:使用JNI读取应用签名

版权所有,禁止匿名转载;禁止商业使用。


为了防止被反编译,打算把关键代码写到so里(比如加解密),在so里加上判断APk包签名是否一致的代码,避免so被二次打包。其实用JNI读签名就是用了Java的反射机制。

先看Java读取签名的方法:

try {

      PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 64);

      Signature sign = info.signatures[0];

      Log.i("test", "hashCode : " + sign.hashCode());

    } catch (NameNotFoundException e) {

      e.printStackTrace();

    }

然后我们用JNI c语言实现,同样需要传递Context:

int getSignHashCode(JNIEnv *env, jobject context) {

  //Context的类

  jclass context_clazz = (*env)->GetObjectClass(env, context);

  // 得到 getPackageManager 方法的 ID

  jmethodID methodID_getPackageManager = (*env)->GetMethodID(env, context_clazz,

      "getPackageManager", "()Landroid/content/pm/PackageManager;");

 

  // 获得PackageManager对象

  jobject packageManager = (*env)->CallObjectMethod(env, context,

      methodID_getPackageManager);

// // 获得 PackageManager 类

  jclass pm_clazz = (*env)->GetObjectClass(env, packageManager);

  // 得到 getPackageInfo 方法的 ID

  jmethodID methodID_pm = (*env)->GetMethodID(env, pm_clazz, "getPackageInfo",

      "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");

//

// // 得到 getPackageName 方法的 ID

  jmethodID methodID_pack = (*env)->GetMethodID(env, context_clazz,

      "getPackageName", "()Ljava/lang/String;");

 

  // 获得当前应用的包名

  jstring application_package = (*env)->CallObjectMethod(env, context,

      methodID_pack);

  const char *str = (*env)->GetStringUTFChars(env, application_package, 0);

  __android_log_print(ANDROID_LOG_DEBUG, "JNI", "packageName: %s\n", str);

 

  // 获得PackageInfo

  jobject packageInfo = (*env)->CallObjectMethod(env, packageManager,

      methodID_pm, application_package, 64);

 

  jclass packageinfo_clazz = (*env)->GetObjectClass(env, packageInfo);

  jfieldID fieldID_signatures = (*env)->GetFieldID(env, packageinfo_clazz,

      "signatures", "[Landroid/content/pm/Signature;");

  jobjectArray signature_arr = (jobjectArray)(*env)->GetObjectField(env,

      packageInfo, fieldID_signatures);

  //Signature数组中取出第一个元素

  jobject signature = (*env)->GetObjectArrayElement(env, signature_arr, 0);

  //读signature的hashcode

  jclass signature_clazz = (*env)->GetObjectClass(env, signature);

  jmethodID methodID_hashcode = (*env)->GetMethodID(env, signature_clazz,

      "hashCode", "()I");

  jint hashCode = (*env)->CallIntMethod(env, signature, methodID_hashcode);

  __android_log_print(ANDROID_LOG_DEBUG, "JNI", "hashcode: %d\n", hashCode);

  return hashCode;

}

第二个参数jobject不是JNI函数的默认参数,而是传入的Context实例。

 

0 0