原地址:http://blog.csdn.net/i5suoi/article/details/19036975
最近在研究android应用中的安全问题,貌似只有将核心代码写到JNI底层才是最安全的。通过底层来判断签名是否正确,如果正确则继续执行核心代码,否则退出程序,这样就可以防止别人恶意反编译,并进行二次打包。所以这里的关键就是如何在JNI中获得签名。
我上网查了好多资料,都没有现成的答案,但是我慢慢的找到了一些思路,于是潜心研究,终于有了结果。不敢独享,所以过来分享给大家。
大家都知道,在android中的java代码里获得签名的哈希值,很简单,过程如下:
- try{
- PackageInfopackageInfo=getPackageManager().getPackageInfo(
- "com.klxx.as",PackageManager.GET_SIGNATURES);
- Signature[]signs=packageInfo.signatures;
- Signaturesign=signs[0];
- Log.i("test","hashCode:"+sign.hashCode());
- }catch(Exceptione){
- e.printStackTrace();
- }
在JNI中提供了许多方法,可以反向调用java中的方法,比如下面一句代码:
PackageInfo packageInfo = getPackageManager().getPackageInfo("com.klxx.as", PackageManager.GET_SIGNATURES);
我们可以用JNI写成这样:
- //获得Context类
- jclassnative_clazz=(*env)->GetObjectClass(env,context);
- //得到getPackageManager方法的ID
- jmethodIDmethodID_func=(*env)->GetMethodID(env,native_clazz,
- "getPackageManager","()Landroid/content/pm/PackageManager;");
- //获得应用包的管理器
- jobjectpackage_manager=(*env)->CallObjectMethod(env,thiz,methodID_func);
- //获得PackageManager类
- jclasspm_clazz=(*env)->GetObjectClass(env,package_manager);
- //得到getPackageInfo方法的ID
- jmethodIDmethodID_pm=(*env)->GetMethodID(env,pm_clazz,
- "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
- //获得应用包的信息
- jobjectpackage_info=(*env)->CallObjectMethod(env,package_manager,
- methodID_pm,(*env)->NewStringUTF(env,"com.example.hellojni"),64);
这种方法在java中叫做反射,更多的JNI反射方法可以参考博客《android开发之绝对安全(三) JNI方法集合》。
通过类似于这种反射机制,我进行一步一步调试和解析,终于获得了应用的签名信息,并从签名信息中获得了签名的哈希值。
我将这段代码传到了CSDN上,欢迎大家下载,如果有什么漏洞,也欢迎大家指点一下。
下载地址:http://download.csdn.net/detail/iloveyoueveryday/6909583。
源码使用注意事项:一定要传过来正确的context参数;项目中的包名("com.example.hellojni")别忘了修改;JNI的代码使用不是很容易,请耐心修改调试,我也是调了好久才测试通过的。