更新代码

This commit is contained in:
mahongyin
2021-03-03 18:02:36 +08:00
parent a8c51116b8
commit d0c4367180
22 changed files with 1040 additions and 268 deletions

View File

@@ -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"

View File

@@ -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("非法调用3SHA1: %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("非法调用3SHA1: %s", ss);
return JNI_FALSE;
}
/*******************调用Java方法结束***/
//加强验证
if (!getApkPathSignatures(env, context_object)) {

View File

@@ -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);
}
}

View File

@@ -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

View 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);
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB