使用jni技术进行android应用签名信息核查及敏感信息保护

最近业余时间写了一款应用《摇啊摇》,安智、安卓、360等几个应用商店已经陆续审核通过并上线。从有想法到最终将产品做出来并发布,断断续续花了近二个半月的业余时间,总体来讲还算顺利,虽然期间也遇到几个小技术难点,最后解决的还算满意。今天说下其中一个小技术难点,现在想想这个小技术难点也很平常,但还是分享出来,希望对有相同疑惑的同学有帮助。

因为java语言自身特性的原因,导致android程序很容易被反编译,虽然可以采用代码混淆的方式,但是如果用了第三方库,混淆脚步编写不好,代码混淆后又会出现程序运行不稳定问题。而没有混淆的程序一旦被反编译后,源码中大量的敏感信息将会暴露无遗。比如与服务器交互的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);
}

上述代码获得的包签名信息实际是一个很长的字符串,为了更高效的进行签名信息比对,还可以将其进行md5加密,加密成32位字符串形式。另外,我在查阅资料过程中,看到有的资料提到用包签名的hashcode值做比对,这种方式更简单一点,但我没有采用这种方式,总觉得这种方式可能不精确,仅仅是个人觉得,有兴趣的同学可以查阅更多相关资料。这里还要说明一点,上面代码获得的包签名字符串信息,使用md5加密后,得到的加密结果与包签名实际的md5
fingerprint是不一致的。主要是因为将签名信息使用toCharsString()转换成字符串后在进行md5加密所致,如果使用toByteArray()将其转成数组,然后加密,加密结果与包签名实际md5 fingerprint将是一致的。

时间: 2024-11-07 10:55:08

使用jni技术进行android应用签名信息核查及敏感信息保护的相关文章

【转】Android 学习笔记——利用JNI技术在Android中调用、调试C++代码

原文网址:http://cherishlc.iteye.com/blog/1756762 在Android中调用C++其实就是在Java中调用C++代码,只是在windows下编译生成DLL,在Android中会生成Linux系统下的.so文件(好吧,其实我基本没用过Linux). 没写过JNI的可以看看我之前的博客(Windows下利用Visual Studio开发的过程):http://cherishlc.iteye.com/admin/blogs/1328136 以及自动生成工具swig的

Pikachu:目录遍历、敏感信息泄漏及URL重定向

目录遍历: 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量,从而让前端的功能便的更加灵活. 当用户发起一个前端的请求时,便会将请求的这个文件的值(比如文件名称)传递到后台,后台再执行其对应的文件. 在这个过程中,如果后台没有对前端传进来的值进行严格的安全考虑,则攻击者可能会通过“../”这样的手段让后台打开或者执行一些其他的文件. 从而导致后台服务器上其他目录的文件结果被遍历出来,形成目录遍历漏洞. 看到这里,你可能会觉得目录遍历漏洞和不安全的文件下载,甚至文件包含漏洞有差不多的

pikachu 目录遍历 敏感信息泄露

目录遍历漏洞概述在web功能设计中,很多时候我们会要将需要访问的文件定义成变量,从而让前端的功能变的更加灵活. 当用户发起一个前端的请求时,便会将请求的这个文件的值(比如文件名称)传递到后台,后台再执行其对应的文件. 在这个过程中,如果后台没有对前端传进来的值进行严格的安全考虑,则攻击者可能会通过“../”这样的手段让后台打开或者执行一些其他的文件. 从而导致后台服务器上其他目录的文件结果被遍历出来,形成目录遍历漏洞. 看到这里,你可能会觉得目录遍历漏洞和不安全的文件下载,甚至文件包含漏洞有差不

pikachu靶场-重定向、目录遍历、敏感信息泄露

一.URL重定向 1.概述 不安全的url跳转 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方. 如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话 就可能发生"跳错对象"的问题. url跳转比较直接的危害是: -->钓鱼,既攻击者使用漏洞方的域名(比如一个比较出名的公司域名往往会让用户放心的点击)做掩盖,而最终跳转的确实钓鱼网站 2.不安全的URL跳转 点击第一个和第二个没有变化,第三个跳转

Android技术4:Android4.4中如何更新相册信息

当你到这篇文章时,你肯定遇到了在Android4.4版本中需要使用本地相册时,无法找到最新的照片这一问题.在Android4.4以前在需要获取手机本地图片信息时,只需要发送一个广播更新相册信息,然而系统更新到4.4之后该广播无效且报错. 广播如下: sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

Android APK 签名比对详解

发布过Android应用的朋友们应该都知道,Android APK的发布是需要签名的.签名机制在Android应用和框架中有着十分重要的作用. 例如,Android系统禁止更新安装签名不一致的APK:如果应用需要使用system权限,必须保证APK签名与Framework签名一致,等等.在<APK Crack>一文中,我们了解到,要破解一个APK,必然需要重新对APK进行签名.而这个签名,一般情况无法再与APK原先的签名保持一致.(除非APK原作者的私钥泄漏,那已经是另一个层次的软件安全问题了

Android APK 签名比对

发布过Android应用的朋友们应该都知道,Android APK的发布是需要签名的.签名机制在Android应用和框架中有着十分重要的作用. 例如,Android系统禁止更新安装签名不一致的APK:如果应用需要使用system权限,必须保证APK签名与Framework签名一致,等等.在<APK Crack>一文中,我们了解到,要破解一个APK,必然需要重新对APK进行签名.而这个签名,一般情况无法再与APK原先的签名保持一致.(除非APK原作者的私钥泄漏,那已经是另一个层次的软件安全问题了

android的签名

安装好了android studio,默认是使用期限为一年的签名,并且不可以发布到正式版的apk里. 在使用第三方模块或者服务的时候,经常要求提供签名及其sha1或者MD5信息. 事实上这个签名和及其信息跟android studio没啥关系,都是由jdk生成和查看的.当然了借助android studio的界面的管理来生成签名,比较方便,但是活不是他干的. 如果,你有一个jks签名,可以如下操作来查看有关信息. 打开命令行 将jdk里的keytool拖到命令行里 空格 -list 空格 -v

JNI技术基础(2)——从零开始编写JNI代码

书接上文: <JNI技术基础(1)——从零开始编写JNI代码> 2.编译源程序HelloWorld.java并生成HelloWorld.class 3.生成头文件HelloWorld.h 在Linux控制台输入命令:javah –jni HelloWorld 生成HelloWorld.h头文件 //HelloWorld.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header