而没有混淆的程序一旦被反编译后。源代码中大量的敏感信息将会暴露无遗。比方与server交互的url地址信息,假设使用了动态链接库,那么native方法也将暴露。况且混淆时是不混淆native方法的。别人看到native方法,就能够自己载入so文件,那么非常多核心的东西,别人就能够间接的使用了,尽管他不一定能用好,但至少能够调用了。
针对上面的林林总总程序被反编译后可能出现的问题,我的解决方法是使用jni技术。在ndk环境下做包签名信息核查,因为是ndk环境,所以这个非常难反编译,也非常难绕过该核查。理论上,签名文件keystore是唯一的,而且仅仅有程序作者才拥有。详细做法为,在所有的native方法内。添加签名信息核查推断,仅仅有签名信息核查通过。程序才干做进一步操作,否则直接返回NULL,这样,即使别人拿到了so文件,摸清楚了native方法參数及使用方法,但因为签名信息不一致。native方法所有返回NULL,so文件瞬间变成砖头。
相同。对于url地址等敏感信息,添加签名信息核查,仅仅有核查通过。程序才会返回正确的字符串,否则直接返回NULL。这样能够非常好的隐藏和保护敏感信息。
说了半天,关键的一步是怎样在ndk环境下,获取包签名信息,以下的代码为相关实现。
jstring loadSignature(JNIEnv* env, jobject obj) { // 获得Context类 jclass cls = (*env)->GetObjectClass(env, obj); // 得到getPackageManager方法的ID jmethodID mid = (*env)->GetMethodID(env, cls, "getPackageManager", "()Landroid/content/pm/PackageManager;"); // 获得应用包的管理器 jobject pm = (*env)->CallObjectMethod(env, obj, mid); // 得到getPackageName方法的ID mid = (*env)->GetMethodID(env, cls, "getPackageName", "()Ljava/lang/String;"); // 获得当前应用包名 jstring packageName = (jstring)(*env)->CallObjectMethod(env, obj, mid); // 获得PackageManager类 cls = (*env)->GetObjectClass(env, pm); // 得到getPackageInfo方法的ID mid = (*env)->GetMethodID(env, cls, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); // 获得应用包的信息 jobject packageInfo = (*env)->CallObjectMethod(env, pm, mid, packageName, 0x40); //GET_SIGNATURES = 64; // 获得PackageInfo 类 cls = (*env)->GetObjectClass(env, packageInfo); // 获得签名数组属性的ID jfieldID fid = (*env)->GetFieldID(env, cls, "signatures", "[Landroid/content/pm/Signature;"); // 得到签名数组 jobjectArray signatures = (jobjectArray)(*env)->GetObjectField(env, packageInfo, fid); // 得到签名 jobject sign = (*env)->GetObjectArrayElement(env, signatures, 0); // 获得Signature类 cls = (*env)->GetObjectClass(env, sign); // 得到toCharsString方法的ID mid = (*env)->GetMethodID(env, cls, "toCharsString", "()Ljava/lang/String;"); // 返回当前应用签名信息 return (jstring)(*env)->CallObjectMethod(env, sign, mid); }
使用jni技术进行android应用签名信息核查及敏感信息保护
原文:http://www.cnblogs.com/mengfanrong/p/5141066.html