更新代码
@@ -5,7 +5,7 @@
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:name=".HookApplication"
|
||||
android:name=".MyApplication"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include <android/log.h>
|
||||
#include <cstring>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
//系统信息
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
//log定义
|
||||
#define LOG "APISECURITY" // 这个是自定义的LOG的TAG
|
||||
#define LOG "mhyLog_APISECURITY" // 这个是自定义的LOG的TAG
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__)
|
||||
@@ -14,8 +17,8 @@
|
||||
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__)
|
||||
|
||||
//此处改为你的APP签名
|
||||
//#define SHA1 "a8e3d91a4f77dd7ccb8d43ee5046a4b6833f4785"//真实test.keystore
|
||||
#define SHA1 "04c1411b0662acd9e4aa300559677e5f106a5255"//区分da小写
|
||||
#define SHA1 "a8e3d91a4f77dd7ccb8d43ee5046a4b6833f4785"//真实test.keystore
|
||||
//#define SHA1 "04c1411b0662acd9e4aa300559677e5f106a5255"//区分da小写
|
||||
#define ALGORITHM_SHA1 "SHA1"
|
||||
#define ALGORITHM_MD5 "MD5"
|
||||
|
||||
@@ -28,19 +31,34 @@
|
||||
static bool isInit = false;
|
||||
static char *secret;
|
||||
|
||||
|
||||
void printByte(JNIEnv *env, jbyteArray jbytes) {
|
||||
//转换成char
|
||||
jsize array_size = env->GetArrayLength(jbytes);
|
||||
jbyte *sha1 = env->GetByteArrayElements(jbytes, nullptr);
|
||||
|
||||
char *hexA = new char[array_size * 2 + 1]();
|
||||
for (int i = 0; i < array_size; ++i) {
|
||||
sprintf(hexA + 2 * i, "%02x", (u_char) sha1[i]);
|
||||
}
|
||||
LOGD("printByte:%s", hexA);
|
||||
jint version() {
|
||||
// 1. 获取 SDK 版本号 , 存储于 C 字符串 sdk_verison_str 中
|
||||
char sdk[128] = "0";
|
||||
// 获取版本号方法
|
||||
__system_property_get("ro.build.version.sdk", sdk);
|
||||
//将版本号转为 int 值
|
||||
int sdk_verison = atoi(sdk);
|
||||
return sdk_verison;
|
||||
}
|
||||
|
||||
jint getDeviceVersion(JNIEnv *env) {
|
||||
jclass build_claz = env->FindClass("android/os/Build$VERSION");
|
||||
jfieldID sdk_int = env->GetStaticFieldID(build_claz, "SDK_INT", "I");
|
||||
return env->GetStaticIntField(build_claz, sdk_int);
|
||||
}
|
||||
|
||||
//void printByte(JNIEnv *env, jbyteArray jbytes) {
|
||||
// //转换成char
|
||||
// jsize array_size = env->GetArrayLength(jbytes);
|
||||
// jbyte *sha1 = env->GetByteArrayElements(jbytes, nullptr);
|
||||
//
|
||||
// char *hexA = new char[array_size * 2 + 1]();
|
||||
// for (int i = 0; i < array_size; ++i) {
|
||||
// sprintf(hexA + 2 * i, "%02x", (u_char) sha1[i]);
|
||||
// }
|
||||
// LOGD("printByte:%s", hexA);
|
||||
//}
|
||||
|
||||
char *digest(JNIEnv *env, const char *algorithm, jbyteArray cert_byte) {
|
||||
jclass message_digest_class = env->FindClass("java/security/MessageDigest");
|
||||
jmethodID methodId = env->GetStaticMethodID(message_digest_class, "getInstance",
|
||||
@@ -130,19 +148,23 @@ jstring getApkPath(JNIEnv *env, jobject applicationInfo_object) {
|
||||
jstring apkPath = (jstring) env->GetObjectField(applicationInfo_object, sourceDir);
|
||||
return apkPath;
|
||||
}
|
||||
|
||||
//context.getPackageResourcePath()
|
||||
jstring getApkResPath(JNIEnv *env, jclass context_class, jobject context_object) {
|
||||
jmethodID methodId = env->GetMethodID(context_class, "getPackageResourcePath", "()Ljava/lang/String;");
|
||||
jmethodID methodId = env->GetMethodID(context_class, "getPackageResourcePath",
|
||||
"()Ljava/lang/String;");
|
||||
jstring apkPath = (jstring) env->CallObjectMethod(context_object, methodId);
|
||||
return apkPath;
|
||||
}
|
||||
|
||||
//弃用 安装路径 package_info= pm.getPackageInfo(packname, 0x80).applicationInfo
|
||||
jstring getAbsolutePath(JNIEnv *env, jobject package_info) {
|
||||
jclass package_info_class = env->GetObjectClass(package_info);//packageInfo
|
||||
jfieldID field = env->GetFieldID(package_info_class, "applicationInfo",
|
||||
"Landroid/content/pm/ApplicationInfo;");//applicationInfo获取类对象 以获取方法
|
||||
env->DeleteLocalRef(package_info_class);
|
||||
jobject apppack_info_object = (jstring) env->GetObjectField(package_info,field);//applicationInfo
|
||||
jobject apppack_info_object = (jstring) env->GetObjectField(package_info,
|
||||
field);//applicationInfo
|
||||
jclass apppack_info_class = env->GetObjectClass(apppack_info_object);//ApplicationInfo
|
||||
jfieldID appfield = env->GetFieldID(apppack_info_class, "sourceDir",
|
||||
"Ljava/lang/String;");//获取此类中的sourceDir成员id P->publicSourceDir
|
||||
@@ -156,7 +178,36 @@ jstring getAbsolutePath(JNIEnv *env, jobject package_info) {
|
||||
/**
|
||||
* 获取签名信息
|
||||
*/
|
||||
//需要sdk28 新API
|
||||
jobject getSignature28(JNIEnv *env, jobject package_info) {
|
||||
jclass package_info_class = env->GetObjectClass(package_info);
|
||||
jfieldID signingInfo = env->GetFieldID(package_info_class, "signingInfo",
|
||||
"Landroid/content/pm/SigningInfo;");
|
||||
env->DeleteLocalRef(package_info_class);
|
||||
jobject signingInfo_object = env->GetObjectField(package_info, signingInfo);
|
||||
LOGE("%s", "fieldId:signingInfo");
|
||||
if (signingInfo_object == nullptr) {
|
||||
return nullptr;//为空咋回事?
|
||||
}
|
||||
// jclass signingInfo_class = env->GetObjectClass(signingInfo_object);
|
||||
jclass signingInfo_class = env->FindClass("android/content/pm/SigningInfo");
|
||||
jmethodID methodId = env->GetMethodID(signingInfo_class, "getApkContentsSigners",
|
||||
"()[Landroid/content/pm/Signature;");
|
||||
env->DeleteLocalRef(signingInfo_class);
|
||||
jobjectArray signature_object_array = (jobjectArray) env->CallObjectMethod(signingInfo_object,
|
||||
methodId);
|
||||
LOGE("%s", "methodId:getApkContentsSigners");
|
||||
if (signature_object_array == nullptr)
|
||||
return nullptr;
|
||||
return env->GetObjectArrayElement(signature_object_array, 0);
|
||||
}
|
||||
|
||||
jobject getSignature(JNIEnv *env, jobject package_info) {
|
||||
// jint sdk = getDeviceVersion(env);
|
||||
// if (sdk >= 28) {
|
||||
// LOGE("sdk版本%d", sdk);
|
||||
// return getSignature28(env, package_info);
|
||||
// }
|
||||
jclass package_info_class = env->GetObjectClass(package_info);
|
||||
jfieldID fieldId = env->GetFieldID(package_info_class, "signatures",
|
||||
"[Landroid/content/pm/Signature;");
|
||||
@@ -240,7 +291,7 @@ jboolean getApkPathSignatures(JNIEnv *env, jobject context_object) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用
|
||||
* 调用 init
|
||||
*/
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_cn_android_security_APISecurity_init(
|
||||
@@ -290,32 +341,32 @@ Java_cn_android_security_APISecurity_init(
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/*********接着调用Java方法验证 安装目录apk文件de签名**/
|
||||
// jclass cls_util = env->FindClass(
|
||||
// "cn/android/security/APISecurity");
|
||||
// //注意,这里的使用的斜杠而不是点
|
||||
// if (cls_util == nullptr) {
|
||||
// return JNI_FALSE;
|
||||
// }
|
||||
// jobject j_obj = env->AllocObject(cls_util);
|
||||
// //**这里是关键**类,方法,(参数类型)返回类型
|
||||
// jmethodID mtd_static_method = env->GetStaticMethodID(cls_util,
|
||||
// "getApkSignatures",
|
||||
// "(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;");
|
||||
// if (mtd_static_method == nullptr) {
|
||||
// return JNI_FALSE;
|
||||
// }
|
||||
// //调用Java方法
|
||||
// jstring sigin = static_cast<jstring>(env->CallStaticObjectMethod(cls_util, mtd_static_method,
|
||||
// context_object, package_name));
|
||||
// const char *ss = env->GetStringUTFChars(sigin, nullptr);
|
||||
// //删除引用
|
||||
// env->DeleteLocalRef(cls_util);
|
||||
// env->DeleteLocalRef(j_obj);
|
||||
////调用Java方法结束
|
||||
// if (strcmp(ss, SHA1) != 0) {
|
||||
// LOGE("非法调用3,SHA1: %s", ss);
|
||||
// return JNI_FALSE;
|
||||
// }
|
||||
jclass cls_util = env->FindClass(
|
||||
"cn/android/security/APISecurity");
|
||||
//注意,这里的使用的斜杠而不是点
|
||||
if (cls_util == nullptr) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
jobject j_obj = env->AllocObject(cls_util);
|
||||
//**这里是关键**类,方法,(参数类型)返回类型
|
||||
jmethodID mtd_static_method = env->GetStaticMethodID(cls_util,
|
||||
"getApkSignatures",
|
||||
"(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;");
|
||||
if (mtd_static_method == nullptr) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
//调用Java方法
|
||||
jstring sigin = static_cast<jstring>(env->CallStaticObjectMethod(cls_util, mtd_static_method,
|
||||
context_object, package_name));
|
||||
const char *ss = env->GetStringUTFChars(sigin, nullptr);
|
||||
//删除引用
|
||||
env->DeleteLocalRef(cls_util);
|
||||
env->DeleteLocalRef(j_obj);
|
||||
//调用Java方法结束
|
||||
if (strcmp(ss, SHA1) != 0) {
|
||||
LOGE("非法调用3,SHA1: %s", ss);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/*******************调用Java方法结束***/
|
||||
//加强验证
|
||||
if (!getApkPathSignatures(env, context_object)) {
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
package cn.android.sample;
|
||||
|
||||
/**
|
||||
* 项目名 FileTransfer
|
||||
* 所在包 bin.mt.apksignaturekillerplus
|
||||
* 作者 mahongyin
|
||||
* 时间 2020-03-16 10:55
|
||||
* 邮箱 mhy.work@qq.com
|
||||
* 描述 说明: 将application替换到AndroidMainfest.xml 代码里改放APPlication
|
||||
* 代码里替换要hook的签名值 始终返回原始签名,达到欺骗
|
||||
*/
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.util.Base64;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import cn.android.security.AppSigning;
|
||||
//继承原application
|
||||
|
||||
public class HookApplication extends Application implements InvocationHandler {
|
||||
private static final int GET_SIGNATURES = 64;
|
||||
private String appPkgName = "";
|
||||
private Object base;
|
||||
private byte[][] sign;
|
||||
static HookApplication app;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
app = this;
|
||||
//在签名校验被hook 之后重置PackageManager
|
||||
/*在这里 重置PackageManager 只要在验证前重置即可*/
|
||||
AppSigning.resetPackageManager(getBaseContext());
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
if (app == null) {
|
||||
app = new HookApplication();
|
||||
app.onCreate();
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context context) {
|
||||
//在这里hook 签名校验被
|
||||
hook(context);
|
||||
super.attachBaseContext(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局hook 签名校验
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void hook(Context context) {
|
||||
try {
|
||||
String relay="308203273082020fa003020102020477d6d1f6300d06092a864886f70d01010b05003044310c300a06035504061303303231310e300c060355040813056368696e613111300f060355040713087368616e676861693111300f0603550403130877757a6f6e67626f301e170d3139303330353032343132345a170d3434303232373032343132345a3044310c300a06035504061303303231310e300c060355040813056368696e613111300f060355040713087368616e676861693111300f0603550403130877757a6f6e67626f30820122300d06092a864886f70d01010105000382010f003082010a0282010100a3ac52268a32e8420a20a727c184c133d513998a207e198f5a535d628a436ba5e095e7ba3f92535234a83fb6272e70ed6113d8f6facc3dee2cfc076a3bd93dad3520fd5d9d9ae4c48afe56e7b421f5de2adfbc23e450f7a5f71e0afdec047b1ce8d7be62ef754a9d43bf36d9b9e0728fc268cb845b464cce1370573dfafd6c40b2efb98ba1f20c5a63c417264b69d86adb839241dc37d1a7113295a9c51623e51e9408f9623ed49a63a3ba6269172872088213332f38370af530d5be56e54115b0884ace6813911bfc6873bea28207741f4b2471b797bab156e4c6ead91659076553cee1db82c0cebdd17b64802a20c7ee6a3414f959133e6c435efe9241ab7d0203010001a321301f301d0603551d0e041604143806aea351c74f2a8b83fa26c0a9e3d3820b6699300d06092a864886f70d01010b050003820101006ebcc664b996f15c1e03d041eebbdf74a0976d117d68f34d21ef67855b614f5a2bfede66c9d4ea78fe3b50e3673890dfa2eb9eaf4321b30eb76be6f5944004b6501b2629ae4f2c6750f784ea2f9be6c26318258f98772fd3ff0c6ea817fb76d9ae02daa1fa1b91653d531db345f52aa4e7b21e8f92387a2d15d1afd5556213b0c32aadd529bac330516536948bcf85398fb86a65dbae95ef0e5582a87e26b1dbcceeaf77e6e93c63042acdf49c74927561df508020547426ad37776e360feb219523ef4e2a6f5f41a43cd0c0514c53f8644c71014080cfbe036f120a6daad6e12d6b1a07939ca840af2b3373388c0ed6b18594dd838122174304d5eb720f1cef";
|
||||
String singnStr = "AQAAAjAwggIsMIIBlaADAgECAgMY2gowDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQ04xCzAJ\nBgNVBAgTAmhlMQwwCgYDVQQHEwNzanoxDDAKBgNVBAoTA2VkdTEPMA0GA1UECxMGc2Nob29sMRIw\nEAYDVQQDEwltYWhvbmd5aW4wHhcNMTgxMDExMDcwMjE1WhcNNDMxMDA1MDcwMjE1WjBbMQswCQYD\nVQQGEwJDTjELMAkGA1UECBMCaGUxDDAKBgNVBAcTA3NqejEMMAoGA1UEChMDZWR1MQ8wDQYDVQQL\nEwZzY2hvb2wxEjAQBgNVBAMTCW1haG9uZ3lpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\nr0aFNvrxBnBEEbAANDcsrmBlcQBGJKsvT5onXngek2ZbkWZx8/1o8nbgCBSjAZvnXEYYjjkC5k+A\nIne1PJUF5bPKTjIQepNmtK+KVHsAJLjn6rG4fQ3oaeu0vvNBehuzt54bACbzkXZj9nV5rs8OllD9\nRronLsOb3DVJ95DyLIMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCpF6kB++zR0FW4eZaJCEAnQNP0\nGtwAnrXEpvP7ePcakk/JT/e56uTS/OAbpmM/tWETvPtx9hOB4RoPwRl3Q0G1ieCMeVyIABmGAeOk\ntARqtiExfHvorrmk4mxVIiPTwUJSWzAKuhLV93pMxTFZSZK0iTJFVVM/l8Wh3CTdFtpW+w==\n";
|
||||
DataInputStream dataInputStream = new DataInputStream(
|
||||
new ByteArrayInputStream(Base64.decode(singnStr, 0)));
|
||||
byte[][] bArr = new byte[(dataInputStream.read() & 255)][];
|
||||
for (int i = 0; i < bArr.length; i++) {
|
||||
bArr[i] = new byte[dataInputStream.readInt()];
|
||||
dataInputStream.readFully(bArr[i]);
|
||||
}
|
||||
Class cls = Class.forName("android.app.ActivityThread");
|
||||
Object invoke = cls.getDeclaredMethod("currentActivityThread", new Class[0]).invoke(null, new Object[0]);
|
||||
Field declaredField = cls.getDeclaredField("sPackageManager");
|
||||
declaredField.setAccessible(true);
|
||||
Object obj = declaredField.get(invoke);
|
||||
Class cls2 = Class.forName("android.content.pm.IPackageManager");
|
||||
this.base = obj;
|
||||
this.sign = bArr;
|
||||
this.appPkgName = context.getPackageName();
|
||||
Object newProxyInstance = Proxy.newProxyInstance(cls2.getClassLoader(), new Class[]{cls2}, this);
|
||||
declaredField.set(invoke, newProxyInstance);
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
Field declaredField2 = packageManager.getClass().getDeclaredField("mPM");
|
||||
declaredField2.setAccessible(true);
|
||||
declaredField2.set(packageManager, newProxyInstance);
|
||||
System.out.println("PmsHook success.");
|
||||
} catch (Exception e) {
|
||||
System.err.println("PmsHook failed.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(Object obj, Method method, Object[] objArr) throws Throwable {
|
||||
if ("getPackageInfo".equals(method.getName())) {//方法名对上
|
||||
String str = (String) objArr[0];
|
||||
if ((((Integer) objArr[1]).intValue() & 64) != 0 && this.appPkgName.equals(str)) {
|
||||
PackageInfo packageInfo = (PackageInfo) method.invoke(this.base, objArr);
|
||||
packageInfo.signatures = new Signature[this.sign.length];
|
||||
for (int i = 0; i < packageInfo.signatures.length; i++) {
|
||||
packageInfo.signatures[i] = new Signature(this.sign[i]);
|
||||
}
|
||||
return packageInfo;
|
||||
}
|
||||
}
|
||||
return method.invoke(this.base, objArr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -21,12 +21,12 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
tv = findViewById(R.id.sample_text);
|
||||
|
||||
if(APISecurity.init(this)){
|
||||
if(APISecurity.init(getApplicationContext())){
|
||||
tv.setText("初始化ok");
|
||||
}else {
|
||||
tv.setText("初始化fail");
|
||||
}
|
||||
APISecurity.verify(this);
|
||||
APISecurity.verify(getApplicationContext());
|
||||
findViewById(R.id.btnTest).setOnClickListener(new View.OnClickListener() {
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
|
||||
229
app/src/main/java/cn/android/sample/MyApplication.java
Normal file
@@ -0,0 +1,229 @@
|
||||
package cn.android.sample;
|
||||
|
||||
/**
|
||||
* 项目名 FileTransfer
|
||||
* 所在包 bin.mt.apksignaturekillerplus
|
||||
* 作者 mahongyin
|
||||
* 时间 2020-03-16 10:55
|
||||
* 邮箱 mhy.work@qq.com
|
||||
* 描述 说明: 将application替换到AndroidMainfest.xml 代码里改放APPlication
|
||||
* 代码里替换要hook的签名值 始终返回原始签名,达到欺骗
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.SigningInfo;
|
||||
import android.os.Build;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import cn.android.security.APISecurity;
|
||||
//继承原application
|
||||
|
||||
public class MyApplication extends Application implements InvocationHandler {
|
||||
private static final int GET_SIGNATURES = 64;
|
||||
private String appPkgName = "";
|
||||
private String appPath = "";
|
||||
private Object base;
|
||||
private byte[][] sign;
|
||||
static MyApplication app;
|
||||
|
||||
|
||||
public MyApplication() {
|
||||
// 在构造函数里提早检测
|
||||
// earlyCheckSign();
|
||||
}
|
||||
|
||||
void earlyCheckSign() {
|
||||
// 手动构造 context
|
||||
try {
|
||||
Context context = APISecurity.createContext();
|
||||
//用新 context 校验签名的过程(正常的检测一样)
|
||||
String sing = APISecurity.getInstalledAPKSignature(context, context.getPackageName());
|
||||
Log.e("mhyLog手动构造", sing);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context context) {
|
||||
//在这里hook 签名校验被
|
||||
// hook(context);
|
||||
super.attachBaseContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
app = this;
|
||||
Application nowApplication = app;
|
||||
// SystemProperties.getInt("ro.build.version.sdk", 0);
|
||||
//再这看 不一定靠谱
|
||||
Log.e("mhyLog","检查App名:"+nowApplication.getClass().getSimpleName());
|
||||
//在签名校验被hook 之后重置PackageManager
|
||||
/*在这里 重置PackageManager 只要在验证前重置即可*/
|
||||
// AppSigning.resetPackageManager(getBaseContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局hook 签名校验
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void hook(Context context) {
|
||||
try {
|
||||
// String realy = "308203273082020fa003020102020477d6d1f6300d06092a864886f70d01010b05003044310c300a06035504061303303231310e300c060355040813056368696e613111300f060355040713087368616e676861693111300f0603550403130877757a6f6e67626f301e170d3139303330353032343132345a170d3434303232373032343132345a3044310c300a06035504061303303231310e300c060355040813056368696e613111300f060355040713087368616e676861693111300f0603550403130877757a6f6e67626f30820122300d06092a864886f70d01010105000382010f003082010a0282010100a3ac52268a32e8420a20a727c184c133d513998a207e198f5a535d628a436ba5e095e7ba3f92535234a83fb6272e70ed6113d8f6facc3dee2cfc076a3bd93dad3520fd5d9d9ae4c48afe56e7b421f5de2adfbc23e450f7a5f71e0afdec047b1ce8d7be62ef754a9d43bf36d9b9e0728fc268cb845b464cce1370573dfafd6c40b2efb98ba1f20c5a63c417264b69d86adb839241dc37d1a7113295a9c51623e51e9408f9623ed49a63a3ba6269172872088213332f38370af530d5be56e54115b0884ace6813911bfc6873bea28207741f4b2471b797bab156e4c6ead91659076553cee1db82c0cebdd17b64802a20c7ee6a3414f959133e6c435efe9241ab7d0203010001a321301f301d0603551d0e041604143806aea351c74f2a8b83fa26c0a9e3d3820b6699300d06092a864886f70d01010b050003820101006ebcc664b996f15c1e03d041eebbdf74a0976d117d68f34d21ef67855b614f5a2bfede66c9d4ea78fe3b50e3673890dfa2eb9eaf4321b30eb76be6f5944004b6501b2629ae4f2c6750f784ea2f9be6c26318258f98772fd3ff0c6ea817fb76d9ae02daa1fa1b91653d531db345f52aa4e7b21e8f92387a2d15d1afd5556213b0c32aadd529bac330516536948bcf85398fb86a65dbae95ef0e5582a87e26b1dbcceeaf77e6e93c63042acdf49c74927561df508020547426ad37776e360feb219523ef4e2a6f5f41a43cd0c0514c53f8644c71014080cfbe036f120a6daad6e12d6b1a07939ca840af2b3373388c0ed6b18594dd838122174304d5eb720f1cef";
|
||||
// realy= Base64.encodeToString(realy.getBytes(),Base64.DEFAULT);
|
||||
String singnStr = "AQAAAjAwggIsMIIBlaADAgECAgMY2gowDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAmhlMQwwCgYDVQQHEwNzanoxDDAKBgNVBAoTA2VkdTEPMA0GA1UECxMGc2Nob29sMRIwEAYDVQQDEwltYWhvbmd5aW4wHhcNMTgxMDExMDcwMjE1WhcNNDMxMDA1MDcwMjE1WjBbMQswCQYDVQQGEwJDTjELMAkGA1UECBMCaGUxDDAKBgNVBAcTA3NqejEMMAoGA1UEChMDZWR1MQ8wDQYDVQQLEwZzY2hvb2wxEjAQBgNVBAMTCW1haG9uZ3lpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr0aFNvrxBnBEEbAANDcsrmBlcQBGJKsvT5onXngek2ZbkWZx8/1o8nbgCBSjAZvnXEYYjjkC5k+AIne1PJUF5bPKTjIQepNmtK+KVHsAJLjn6rG4fQ3oaeu0vvNBehuzt54bACbzkXZj9nV5rs8OllD9RronLsOb3DVJ95DyLIMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCpF6kB++zR0FW4eZaJCEAnQNP0GtwAnrXEpvP7ePcakk/JT/e56uTS/OAbpmM/tWETvPtx9hOB4RoPwRl3Q0G1ieCMeVyIABmGAeOktARqtiExfHvorrmk4mxVIiPTwUJSWzAKuhLV93pMxTFZSZK0iTJFVVM/l8Wh3CTdFtpW+w==";
|
||||
DataInputStream dataInputStream = new DataInputStream(
|
||||
new ByteArrayInputStream(Base64.decode(singnStr, Base64.DEFAULT)));
|
||||
byte[][] bArr = new byte[(dataInputStream.read() & 255)][];
|
||||
for (int i = 0; i < bArr.length; i++) {
|
||||
bArr[i] = new byte[dataInputStream.readInt()];
|
||||
dataInputStream.readFully(bArr[i]);
|
||||
}
|
||||
//hook全局sPackageManager对象
|
||||
Class cls = Class.forName("android.app.ActivityThread");
|
||||
Object invoke = cls.getDeclaredMethod("currentActivityThread", new Class[0]).invoke(null, new Object[0]);
|
||||
Field declaredField = cls.getDeclaredField("sPackageManager");
|
||||
declaredField.setAccessible(true);
|
||||
Object obj = declaredField.get(invoke);
|
||||
Class cls2 = Class.forName("android.content.pm.IPackageManager");
|
||||
this.base = obj;
|
||||
this.sign = bArr;
|
||||
this.appPkgName = context.getPackageName();
|
||||
this.appPath = context.getPackageResourcePath();
|
||||
Object newProxyInstance = Proxy.newProxyInstance(cls2.getClassLoader(), new Class[]{cls2}, this);
|
||||
declaredField.set(invoke, newProxyInstance);
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
Field declaredField2 = packageManager.getClass().getDeclaredField("mPM");
|
||||
declaredField2.setAccessible(true);
|
||||
declaredField2.set(packageManager, newProxyInstance);
|
||||
System.out.println("PmsHook success.");
|
||||
} catch (Exception e) {
|
||||
System.err.println("PmsHook failed.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint({"PrivateApi","DiscouragedPrivateApi"})
|
||||
@Override
|
||||
public Object invoke(Object obj, Method method, Object[] objArr) throws Throwable {
|
||||
if ("getPackageInfo".equals(method.getName())) {//方法名对上
|
||||
Log.e("mhyLogHook","getPackageInfo");
|
||||
String str = (String) objArr[0];
|
||||
if ((((Integer) objArr[1]).intValue() & 64) != 0 && this.appPkgName.equals(str)) {
|
||||
PackageInfo packageInfo = (PackageInfo) method.invoke(this.base, objArr);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
//packageInfo.signingInfo.getApkContentsSigners();//mSigningDetails.signatures
|
||||
//mSigningDetails.signatures;//PackageParser.SigningDetails
|
||||
SigningInfo signingInfo= packageInfo.signingInfo;
|
||||
// Class<?> sgInfo_clazz=SigningInfo.class;//getClass()&Class.forName(“类完整的路径”)仅限于引用类型的对象
|
||||
// Field mSigningDetails_f=sgInfo_clazz.getDeclaredField("mSigningDetails");
|
||||
// mSigningDetails_f.setAccessible(true);
|
||||
// Object mSigningDetails = mSigningDetails_f.get(signingInfo);//PackageParser.SigningDetails
|
||||
|
||||
Class<?> pkgParserCls = Class.forName("android.content.pm.PackageParser");
|
||||
Constructor<?> pkgParserCt = pkgParserCls.getConstructor();//null;
|
||||
Object pkgParser = pkgParserCt.newInstance();//null;
|
||||
// pkgParserCt =
|
||||
// pkgParser =
|
||||
Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, int.class);
|
||||
Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, new File(getPackageResourcePath()), PackageManager.GET_SIGNING_CERTIFICATES);
|
||||
|
||||
Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
|
||||
pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, true);
|
||||
|
||||
// Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
|
||||
// pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, false);
|
||||
|
||||
Field mSigningDetailsField = pkgParserPkg.getClass().getDeclaredField("mSigningDetails"); // SigningDetails
|
||||
mSigningDetailsField.setAccessible(true);
|
||||
Object mSigningDetails = mSigningDetailsField.get(pkgParserPkg);
|
||||
|
||||
Field infoField = mSigningDetails.getClass().getDeclaredField("signatures");
|
||||
infoField.setAccessible(true);
|
||||
Signature[] info = new Signature[this.sign.length];
|
||||
for (int i = 0; i < this.sign.length; i++) {
|
||||
info[i] = new Signature(this.sign[i]);
|
||||
}
|
||||
// Signature[] info = (Signature[]) infoField.get(mSigningDetails);//获取属性值
|
||||
infoField.set(mSigningDetails, info);
|
||||
}// else { //双hook
|
||||
packageInfo.signatures = new Signature[this.sign.length];
|
||||
for (int i = 0; i < packageInfo.signatures.length; i++) {
|
||||
packageInfo.signatures[i] = new Signature(this.sign[i]);
|
||||
// }
|
||||
}
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
}
|
||||
if ("getPackageArchiveInfo".equals(method.getName())) {//从安装路径获取apk签名方法
|
||||
Log.e("mhyLogHook","getPackageArchiveInfo");
|
||||
// getPackageArchiveInfo(String archiveFilePath, @PackageInfoFlags int flags)
|
||||
String str = (String) objArr[0];//第一个参数
|
||||
if ((((Integer) objArr[1]).intValue() & 64) != 0 && this.appPath.equals(str)) {
|
||||
PackageInfo packageInfo = (PackageInfo) method.invoke(this.base, objArr);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
SigningInfo signingInfo= packageInfo.signingInfo;
|
||||
// Class<?> sgInfo_clazz=SigningInfo.class;
|
||||
// Field mSigningDetails_f=sgInfo_clazz.getDeclaredField("mSigningDetails");
|
||||
// mSigningDetails_f.setAccessible(true);
|
||||
// Object mSigningDetails = mSigningDetails_f.get(signingInfo);
|
||||
|
||||
Class<?> pkgParserCls = Class.forName("android.content.pm.PackageParser");
|
||||
Constructor<?> pkgParserCt = pkgParserCls.getConstructor();//null;
|
||||
Object pkgParser = pkgParserCt.newInstance();//null;
|
||||
// pkgParserCt =
|
||||
// pkgParser =
|
||||
Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, int.class);
|
||||
Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, new File(getPackageResourcePath()), PackageManager.GET_SIGNING_CERTIFICATES);
|
||||
|
||||
Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
|
||||
pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, true);
|
||||
|
||||
// Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
|
||||
// pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, false);
|
||||
|
||||
Field mSigningDetailsField = pkgParserPkg.getClass().getDeclaredField("mSigningDetails"); // SigningDetails
|
||||
mSigningDetailsField.setAccessible(true);
|
||||
Object mSigningDetails = mSigningDetailsField.get(pkgParserPkg);
|
||||
|
||||
Field infoField = mSigningDetails.getClass().getDeclaredField("signatures");
|
||||
infoField.setAccessible(true);
|
||||
Signature[] info = new Signature[this.sign.length];
|
||||
for (int i = 0; i < this.sign.length; i++) {
|
||||
info[i] = new Signature(this.sign[i]);
|
||||
}
|
||||
// Signature[] info = (Signature[]) infoField.get(mSigningDetails);//获取属性值
|
||||
infoField.set(mSigningDetails, info);
|
||||
} //else { //双hook
|
||||
packageInfo.signatures = new Signature[this.sign.length];
|
||||
for (int i = 0; i < packageInfo.signatures.length; i++) {
|
||||
packageInfo.signatures[i] = new Signature(this.sign[i]);
|
||||
// }
|
||||
}
|
||||
return packageInfo;
|
||||
}
|
||||
}
|
||||
return method.invoke(this.base, objArr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |