android jni签名验证(一)

这篇博客介绍了如何在Android的JNI中不依赖Context来获取应用签名,通过动态注册类和native方法,增强了逆向工程的难度。此外,文章还提到了利用ActivityThread的currentApplication方法获取Application对象,以此来防止对签名的伪造,提高了安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jni获取签名一般要传入一个context到jni中,然后通过jni进行签名的相关操作,这种方法有一个缺点,通过重写

PackageManager类 进行签名重写,欺骗从而破解签名的目的

下面给出cpp文件,不传入context获取签名的一种方式:代码中有详细注释

#include <jni.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
/*
author:xiaobaiyey
date:2015年11月7日15:24:02
email:xiaobaiyey@outlook.com
*/
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "xiaobai", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "xiaobai", __VA_ARGS__))
 
void verifySign(JNIEnv *env, jobject obj);
jstring getentyString();
//jstring转char*
char* jstringTostring(JNIEnv* env, jstring jstr)
{
    char* rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode =env->NewStringUTF("utf-8");
    jmethodID mid = env->GetMethodID( clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray)env->CallObjectMethod( jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte* ba = env->GetByteArrayElements( barr, JNI_FALSE);
    if (alen > 0)
    {
        rtn = (char*)malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}
jobject getApplication(JNIEnv *env) {
    jclass localClass = env->FindClass("android/app/ActivityThread");
    if (localClass!=NULL)
    {
        LOGI("class have find");
        jmethodID getapplication = env->GetStaticMethodID(localClass, "currentApplication", "()Landroid/app/Application;");
        if (getapplication!=NULL)
        {
            jobject application = env->CallStaticObjectMethod(localClass, getapplication);
            return application;
        }
        return NULL;
    }
    return NULL;
}
//注册native方法
static JNINativeMethod gMethods[] = {
    { "verifySign", "()V", (void *)verifySign },//对应java中的public native void verifySign();
    { "getentyString", "(I)Ljava/lang/String;", (jstring *)getentyString },
 
};
static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethods,
    int numMethods) {
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
//注册类
static int registerNatives(JNIEnv *env) {
    const char *kClassName = "com/xiaobai/xposedtool/MainActivity";//指定要注册的类 即nativie方法所在的类
    return registerNativeMethods(env,kClassName,gMethods,sizeof(gMethods) / sizeof(gMethods[0]));
 
}
void verifySign(JNIEnv *env, jobject obj) {
    jobject context= getApplication(env);
    jclass  activity = env->GetObjectClass(context);
    // 得到 getPackageManager 方法的 ID
    jmethodID methodID_func = env->GetMethodID(activity, "getPackageManager", "()Landroid/content/pm/PackageManager;");
    // 获得PackageManager对象
    jobject packageManager = env->CallObjectMethod(context,methodID_func);
    jclass packageManagerclass = env->GetObjectClass(packageManager);
    //得到 getPackageName 方法的 ID
    jmethodID methodID_pack = env->GetMethodID(activity,"getPackageName", "()Ljava/lang/String;");
    //获取包名
    jstring name_str = static_cast<jstring>(env->CallObjectMethod(context, methodID_pack));
    // 得到 getPackageInfo 方法的 ID
    jmethodID methodID_pm = env->GetMethodID(packageManagerclass,"getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    // 获得应用包的信息
    jobject package_info = env->CallObjectMethod(packageManager, methodID_pm, name_str, 64);
    // 获得 PackageInfo 类
    jclass package_infoclass = env->GetObjectClass(package_info);
    // 获得签名数组属性的 ID
    jfieldID fieldID_signatures = env->GetFieldID(package_infoclass,"signatures", "[Landroid/content/pm/Signature;");
    // 得到签名数组,待修改
    jobject signatur = env->GetObjectField(package_info, fieldID_signatures);
    jobjectArray  signatures = reinterpret_cast<jobjectArray>(signatur);
    // 得到签名
    jobject signature = env->GetObjectArrayElement(signatures, 0);
    // 获得 Signature 类,待修改
    jclass signature_clazz = env->GetObjectClass(signature);
    //获取sign
    jmethodID toCharString = env->GetMethodID(signature_clazz, "toCharsString", "()Ljava/lang/String;");
    //获取签名字符;或者其他进行验证操作
    jstring signstr = static_cast<jstring>(env->CallObjectMethod(signature, toCharString));
    char* ch = jstringTostring(env, signstr);
    //输入签名字符串,这里可以进行相关验证
    LOGI("the signtures is :%s", ch);
}
//返回字符
jstring getentyString() {
 
 
    return NULL;
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;
 
    LOGI("in jni onload");
    if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    LOGI("register natives");
    if (!registerNatives(env)) {//注册
        LOGI("register failed");
        return -1;
    }
    //成功
    result = JNI_VERSION_1_4;
    LOGI("register success");
    return result;
}
  1. 通过动态注册类和native方法。此方法可以一定程度上增加逆向难度。

  2. 通过ActivityThread中currentApplication方法动态获取Application对象,在通过此对象获取签名相关信息。可以防止重写PackageManager对签名的伪造。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值