jni验证application
This commit is contained in:
@@ -46,8 +46,13 @@ public class APISecurity {
|
||||
* @param str
|
||||
*/
|
||||
public static native String sign(String str);
|
||||
public static native String getRelayPackName();
|
||||
|
||||
public static native String getRealyAppName();
|
||||
|
||||
public static native void verifyApp(Application applicationByReflect);
|
||||
|
||||
public static native boolean verifyApplication();
|
||||
|
||||
public static native boolean init(Context context);
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,7 +80,6 @@ public class AppSigning {
|
||||
IllegalAccessException,
|
||||
NoSuchFieldException,
|
||||
NullPointerException {
|
||||
|
||||
// 反射获取 ActivityThread 的 currentActivityThread 获取 mainThread
|
||||
Class activityThreadClass = Class.forName("android.app.ActivityThread");
|
||||
Method currentActivityThreadMethod =
|
||||
@@ -115,12 +114,12 @@ public class AppSigning {
|
||||
/**
|
||||
* 校验 application
|
||||
*/
|
||||
public static boolean checkApplication(){
|
||||
public static boolean sameApplication(){
|
||||
//在这里使用反射 获取比较靠谱 如果 被替换换 就查出来了
|
||||
Application nowApplication = getApplicationByReflect();
|
||||
APISecurity.verifyApp(nowApplication);
|
||||
String trueApplicationName = "cn.android.sample.MyApplication";//getSimpleName()自己的Application类名 防止替换
|
||||
String nowApplicationName = nowApplication.getClass().getName();
|
||||
String trueApplicationName = APISecurity.getRealyAppName();
|
||||
//getSimpleName()自己的Application类名 防止替换
|
||||
String nowApplicationName = nowApplication.getClass().getName();//当前app类全名
|
||||
Log.e("mhyLogAppName", "反射获取:"+nowApplicationName);
|
||||
return trueApplicationName.equals(nowApplicationName);
|
||||
}
|
||||
@@ -326,7 +325,6 @@ public class AppSigning {
|
||||
return getSignatureString(info,AppSigning.SHA1);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
pkgParserCt = pkgParserCls.getConstructor(typeArgs);
|
||||
pkgParser = pkgParserCt.newInstance(apkPath);
|
||||
|
||||
@@ -12,15 +12,12 @@
|
||||
|
||||
package cn.android.security;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Application;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -39,9 +36,9 @@ public class InitProvider extends ContentProvider {
|
||||
}
|
||||
Log.e("mhyLog", "initContentProvider:");
|
||||
chekSignature(application);
|
||||
|
||||
Log.e("mhyLog检测Provider_APP", String.valueOf(AppSigning.checkApplication()));
|
||||
|
||||
Log.e("mhyLog验证APP", String.valueOf(AppSigning.sameApplication())+";apkmd5="+ AppSigning.apkMD5(application));
|
||||
APISecurity.verifyApp(AppSigning.getApplicationByReflect());
|
||||
APISecurity.verifyApplication();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BIN
app/androidkey.keystore
Normal file
BIN
app/androidkey.keystore
Normal file
Binary file not shown.
@@ -26,6 +26,12 @@ android {
|
||||
storeFile file("test.keystore")
|
||||
storePassword '123456'
|
||||
}
|
||||
debug {//非目标签名 用于验证
|
||||
keyAlias 'androidkey'
|
||||
keyPassword 'android'
|
||||
storeFile file("androidkey.keystore")
|
||||
storePassword 'android'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +45,7 @@ android {
|
||||
}
|
||||
debug{
|
||||
debuggable true
|
||||
signingConfig signingConfigs.release
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
app/libs/x86/libold.so
Normal file
BIN
app/libs/x86/libold.so
Normal file
Binary file not shown.
BIN
app/libs/x86_64/libold.so
Normal file
BIN
app/libs/x86_64/libold.so
Normal file
Binary file not shown.
@@ -24,10 +24,11 @@
|
||||
//#define SHA1 "04c1411b0662acd9e4aa300559677e5f106a5255"//区分da小写 55
|
||||
//此处改为你的APP包名
|
||||
#define APP_PKG "cn.android.sample"
|
||||
//此处改为你的application全名 没有就是android.app.Application
|
||||
//#define APPLICATION_NAME "android.app.Application"
|
||||
#define APPLICATION_NAME "cn.android.sample.MyApplication"
|
||||
//此处填写API盐值
|
||||
#define API_SECRET "ABC1234567"//设置api 密钥 MD5加盐
|
||||
|
||||
//此处填写API盐值 MD5加盐
|
||||
#define API_SECRET "ABC1234567"
|
||||
|
||||
static bool isInit = false;
|
||||
static char *secret;
|
||||
@@ -40,6 +41,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){
|
||||
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
LOGI("JNI_OnUnload");
|
||||
}
|
||||
|
||||
jint version() {
|
||||
// 1. 获取 SDK 版本号 , 存储于 C 字符串 sdk_verison_str 中
|
||||
char sdk[128] = "0";
|
||||
@@ -47,6 +49,7 @@ jint version() {
|
||||
__system_property_get("ro.build.version.sdk", sdk);
|
||||
//将版本号转为 int 值
|
||||
int sdk_verison = atoi(sdk);
|
||||
|
||||
return sdk_verison;
|
||||
}
|
||||
|
||||
@@ -124,7 +127,7 @@ jobject getPackageInfo(JNIEnv *env, jobject package_manager, jstring package_nam
|
||||
0x08000000);//安卓9 0x08000000
|
||||
} else {
|
||||
package_info = env->CallObjectMethod(package_manager, methodId, package_name,
|
||||
0x00000040);//安卓9 0x08000000
|
||||
0x00000040);
|
||||
}
|
||||
return package_info;
|
||||
}
|
||||
@@ -367,7 +370,7 @@ Java_cn_android_security_APISecurity_init(
|
||||
LOGE("非法调用2,Package: %s", pkgName);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/*********接着调用Java方法验证 安装目录apk文件de签名**/
|
||||
/*********接着调用Java方法验证 安装目录apk文件的签名**/
|
||||
jclass cls_util = env->FindClass(
|
||||
"cn/android/security/APISecurity");
|
||||
//注意,这里的使用的斜杠而不是点
|
||||
@@ -516,7 +519,7 @@ void checkTaskCount() {
|
||||
|
||||
}
|
||||
/**
|
||||
* Application.getClass().getName(); 验证application是否被替换
|
||||
* Application.getClass().getName(); 验证application是否被替换 【前提是不能用360加固那些 否则二次jiagu后无法察觉】
|
||||
*/
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
@@ -530,12 +533,53 @@ Java_cn_android_security_APISecurity_verifyApp(JNIEnv *env, jclass clazz,
|
||||
jmethodID getNameId = env->GetMethodID(mClazz, "getName", "()Ljava/lang/String;");
|
||||
jstring appname = (jstring) env->CallObjectMethod(clazz_object, getNameId);
|
||||
const char *ss = env->GetStringUTFChars(appname, nullptr);
|
||||
LOGE("调用5,NAME: %s", ss);
|
||||
if (strcmp(ss, APPLICATION_NAME) != 0) {
|
||||
LOGE("非法调用5,SHA1: %s", ss);
|
||||
LOGE("非法调用5,NAME: %s", ss);
|
||||
isInit = false;
|
||||
}
|
||||
}extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_cn_android_security_APISecurity_getRelayPackName(JNIEnv *env, jclass clazz) {
|
||||
// TODO: implement getRelayPackName()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_cn_android_security_APISecurity_getRealyAppName(JNIEnv *env, jclass clazz) {
|
||||
return env->NewStringUTF(APPLICATION_NAME);
|
||||
}
|
||||
/**
|
||||
* 在这里反射获取 application 对比applicationa是否被篡改 前提是不能用360加固那些 否则二次jiagu后无法察觉
|
||||
*/
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_cn_android_security_APISecurity_verifyApplication(JNIEnv *env, jclass clazz) {
|
||||
jclass activityThread_clazz = env->FindClass("android/app/ActivityThread");
|
||||
if (activityThread_clazz== nullptr){
|
||||
return JNI_FALSE;
|
||||
}
|
||||
//activityThread_clazz = static_cast<jclass>(env->NewGlobalRef(activityThread_clazz));//全局引用(自己来提升)
|
||||
jmethodID threadId = env->GetStaticMethodID(activityThread_clazz, "currentActivityThread",
|
||||
"()Landroid/app/ActivityThread;");
|
||||
jobject activityThread = env->CallStaticObjectMethod(activityThread_clazz, threadId);
|
||||
jmethodID getApplication = env->GetMethodID(activityThread_clazz, "getApplication",
|
||||
"()Landroid/app/Application;");
|
||||
env->DeleteLocalRef(activityThread_clazz);//删除引用
|
||||
jobject application = env->CallObjectMethod(activityThread, getApplication);
|
||||
if (application== nullptr){
|
||||
return JNI_FALSE;
|
||||
}
|
||||
jclass object_clazz = env->FindClass("java/lang/Object");
|
||||
jmethodID getClass = env->GetMethodID(object_clazz, "getClass", "()Ljava/lang/Class;");
|
||||
env->DeleteLocalRef(object_clazz);//删除引用
|
||||
jobject clazz_object = env->CallObjectMethod(application, getClass);
|
||||
jclass mClazz = env->FindClass("java/lang/Class");
|
||||
jmethodID getNameId = env->GetMethodID(mClazz, "getName", "()Ljava/lang/String;");
|
||||
env->DeleteLocalRef(mClazz);//删除引用
|
||||
jstring appname = (jstring) env->CallObjectMethod(clazz_object, getNameId);
|
||||
const char *ss = env->GetStringUTFChars(appname, nullptr);
|
||||
LOGE("调用6,NAME: %s", ss);
|
||||
// env->DeleteGlobalRef(activityThread_clazz);//对应手动释放全局引用
|
||||
if (strcmp(ss, APPLICATION_NAME) != 0) {
|
||||
LOGE("非法调用6,NAME: %s", ss);
|
||||
isInit = false;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ package cn.android.sample;
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
@@ -16,6 +17,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.SigningInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -68,12 +70,51 @@ public class MyApplication extends Application implements InvocationHandler {
|
||||
//在签名校验被hook 之后重置PackageManager
|
||||
/*在这里 重置PackageManager 只要在验证前重置即可*/
|
||||
AppSigning.resetPackageManager(getBaseContext());
|
||||
|
||||
lifeCallback();
|
||||
}
|
||||
|
||||
private void lifeCallback() {
|
||||
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局hook 签名校验
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
@SuppressLint("PrivateApi")
|
||||
private void hook(Context context) {
|
||||
@@ -191,6 +232,4 @@ public class MyApplication extends Application implements InvocationHandler {
|
||||
// IPackageManager接口中无getPackageArchiveInfo 方法无法代理
|
||||
return method.invoke(this.base, objArr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user