Andorid jni本地校验应用签名(MD5/SHA1)
发布日期:2021-10-04 02:53:23
浏览次数:4
分类:技术文章
本文共 5746 字,大约阅读时间需要 19 分钟。
编码环境:android API 19+Android studio
功能:打开应用调用os库的init方法校验app是否被篡改!
流程: —>打开应用 —>os库中init方法 —>C层获取应用签名(md5/sha1) —>和本地正常的签名对比 —>匹配不成功直接在C中退出应用。实现:
在java层,新建一个native方法如:
public static native void init();
在jni下面新建一个.c文件,名字随意如test.c,在该文件中要实现获取应用签名,对比,退出应用。
这个地方的init方法可以使用动态注册的方式避免又长又臭的方法名在C文件中(如何动态注册请移步:) 直接撸代码吧:void init(JNIEnv* env, jobject thiz){ //获取到Context jobject context= getApplication(env); jclass activity = (*env)->GetObjectClass(env,context); // 得到 getPackageManager 方法的 ID jmethodID methodID_func = (*env)->GetMethodID(env,activity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); // 获得PackageManager对象 jobject packageManager = (*env)->CallObjectMethod(env,context,methodID_func); jclass packageManagerclass = (*env)->GetObjectClass(env,packageManager); //得到 getPackageName 方法的 ID jmethodID methodID_pack = (*env)->GetMethodID(env,activity,"getPackageName", "()Ljava/lang/String;"); //获取包名 jstring name_str = (jstring)((*env)->CallObjectMethod(env,context, methodID_pack)); // 得到 getPackageInfo 方法的 ID jmethodID methodID_pm = (*env)->GetMethodID(env,packageManagerclass,"getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); // 获得应用包的信息 jobject package_info = (*env)->CallObjectMethod(env,packageManager, methodID_pm, name_str, 64); // 获得 PackageInfo 类 jclass package_infoclass = (*env)->GetObjectClass(env,package_info); // 获得签名数组属性的 ID jfieldID fieldID_signatures = (*env)->GetFieldID(env,package_infoclass,"signatures", "[Landroid/content/pm/Signature;"); // 得到签名数组,待修改 jobject signatur = (*env)->GetObjectField(env,package_info, fieldID_signatures); jobjectArray signatures = (jobjectArray)(signatur); // 得到签名 jobject signature = (*env)->GetObjectArrayElement(env,signatures, 0); // 获得 Signature 类,待修改 jclass signature_clazz = (*env)->GetObjectClass(env,signature); //---获得签名byte数组 jmethodID tobyte_methodId = (*env)->GetMethodID(env,signature_clazz, "toByteArray", "()[B"); jbyteArray signature_byte = (jbyteArray) (*env)->CallObjectMethod(env,signature, tobyte_methodId); //把byte数组转成流 jclass byte_array_input_class=(*env)->FindClass(env,"java/io/ByteArrayInputStream"); jmethodID init_methodId=(*env)->GetMethodID(env,byte_array_input_class,"","([B)V"); jobject byte_array_input=(*env)->NewObject(env,byte_array_input_class,init_methodId,signature_byte); //实例化X.509 jclass certificate_factory_class=(*env)->FindClass(env,"java/security/cert/CertificateFactory"); jmethodID certificate_methodId=(*env)->GetStaticMethodID(env,certificate_factory_class,"getInstance","(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); jstring x_509_jstring=(*env)->NewStringUTF(env,"X.509"); jobject cert_factory=(*env)->CallStaticObjectMethod(env,certificate_factory_class,certificate_methodId,x_509_jstring); //certFactory.generateCertificate(byteIn); jmethodID certificate_factory_methodId=(*env)->GetMethodID(env,certificate_factory_class,"generateCertificate",("(Ljava/io/InputStream;)Ljava/security/cert/Certificate;")); jobject x509_cert=(*env)->CallObjectMethod(env,cert_factory,certificate_factory_methodId,byte_array_input); jclass x509_cert_class=(*env)->GetObjectClass(env,x509_cert); jmethodID x509_cert_methodId=(*env)->GetMethodID(env,x509_cert_class,"getEncoded","()[B"); jbyteArray cert_byte=(jbyteArray)(*env)->CallObjectMethod(env,x509_cert,x509_cert_methodId); //MessageDigest.getInstance("SHA1") jclass message_digest_class=(*env)->FindClass(env,"java/security/MessageDigest"); jmethodID methodId=(*env)->GetStaticMethodID(env,message_digest_class,"getInstance","(Ljava/lang/String;)Ljava/security/MessageDigest;"); //如果取SHA1则输入SHA1 //jstring sha1_jstring=(*env)->NewStringUTF(env,"SHA1"); jstring sha1_jstring=(*env)->NewStringUTF(env,"MD5"); jobject sha1_digest=(*env)->CallStaticObjectMethod(env,message_digest_class,methodId,sha1_jstring); //sha1.digest (certByte) methodId=(*env)->GetMethodID(env,message_digest_class,"digest","([B)[B"); jbyteArray sha1_byte=(jbyteArray)(*env)->CallObjectMethod(env,sha1_digest,methodId,cert_byte); //toHexString jsize array_size=(*env)->GetArrayLength(env,sha1_byte); jbyte* sha1 =(*env)->GetByteArrayElements(env,sha1_byte,NULL); char hex_sha[array_size*2+1]; int i; for (i = 0;i GetStringUTFChars(env,signstr,NULL); if (strcmp(hex_sha,sha1final)!=0){ LOGV("验证不通过!"); exitApplication(env,0); }else{ LOGV("验证通过!"); }}
获取Context上下文方法:
jobject getApplication(JNIEnv *env) { jclass localClass = (*env)->FindClass(env,"android/app/ActivityThread"); if (localClass!=NULL) { // LOGI("class have find"); jmethodID getapplication = (*env)->GetStaticMethodID(env,localClass, "currentApplication", "()Landroid/app/Application;"); if (getapplication!=NULL) { jobject application = (*env)->CallStaticObjectMethod(env,localClass, getapplication); return application; } return NULL; } return NULL;}
直接退出应用方法:(直接寻找到java/lang/Systemz这个类)
void exitApplication(JNIEnv *env, jint flag){ jclass temp_clazz = NULL; jmethodID mid_static_method; // 1、从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象 temp_clazz =(*env)->FindClass(env,"java/lang/System"); mid_static_method = (*env)->GetStaticMethodID(env,temp_clazz,"exit","(I)V"); (*env)->CallStaticVoidMethod(env,temp_clazz,mid_static_method,flag); (*env)->DeleteLocalRef(env,temp_clazz);}
常量
const char HexCode[]={ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};const char *sha1final="3A0558B19DE14EEC82FFA3721CED4AA9";
以上代码即可实现在应用中直接调用init方法即可触发校验。
转载地址:https://blog.csdn.net/leifengpeng/article/details/52681196 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
很好
[***.229.124.182]2024年04月17日 04时59分01秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
volatile关键字的作用:防止变量被编译器优化
2019-04-25
Makefile 假想目标:.PHONY
2019-04-25
bss、data和rodata区别与联系
2019-04-25
C代码中如何使用链接脚本.lds中定义的变量
2019-04-25
ARM指令和Thumb指令的区别
2019-04-25
作为一个新人,怎样学习嵌入式Linux?
2019-04-25
站在2018看单片机和嵌入式芯片方案选型和发展趋势
2019-04-25
Linux内核编程初探:块设备驱动程序——Ramdisk
2019-04-25
C语言 memcpy 用法
2019-04-25
浅论各种调试接口(SWD、JTAG、Jlink、Ulink、STlink)的区别
2019-04-25
C++深度解析 内联函数分析 内联inline和宏#define(5)
2019-04-25
C++深度解析 函数重载分析(7)
2019-04-25
报表的 SQL 注入风险是什么意思?如何防范?
2019-04-25
JS-part3.3-复杂数据类型之 数组和排序方法
2019-04-25
求和与平均值
2019-04-25
if选择结构
2019-04-25