diff --git a/README.md b/README.md index ea6f9b9..cc2e312 100644 --- a/README.md +++ b/README.md @@ -550,4 +550,91 @@ versionI() { ro.setupwizard.mode=OPTIONAL (安装向导模式) net. bt. name=Android (系统名称) dalvik.vm.stack-trace-file=/data/anr/traces.txt -``` \ No newline at end of file +``` + +Class.newInstance();只能反射无参的构造器,需要构造器可见; +Constructor.newInstance();可以反射任何构造器,可以反射私有构造器 + +``` +public class Student { + private String name; + private int age; + private double score; + + public Student() {} + private Student(String name, int age, double score) { + this.name = name; + this.age = age; + this.score = score; + } +} +``` +``` +public class Client { + public static void main(String[] args) throws Exception { + Class clazz = Student.class; + //利用Class.newInstance() + Object object1 = clazz.newInstance(); + System.out.println(object1); + //利用Constructor.newInstance()反射无参构造方法 + Constructor cons1 = clazz.getDeclaredConstructor(); + Object object2 = cons1.newInstance(); + //利用Constructor.newInstance()反射私有构造方法 + Constructor cons2 = clazz.getDeclaredConstructor(String.class,Integer.TYPE,Double.TYPE); + if(!cons2.isAccessible()) + cons2.setAccessible(true); + Object object3 = cons2.newInstance("张三",12,88.5); + } +} + +``` +Java除了这两这种方法创建对象外,还有三个方式,使用new 关键字,使用对象克隆clone()方法,以及使用反序列化(ObjectInputStream)的 readObject() 方法。 + +使用 clone()方法:类必须实现Cloneable接口,并重写其clone()方法 +使用反序列化ObjectInputStream 的readObject()方法:类必须实现 Serializable接口 +``` +public class Student implements Serializable,Cloneable{ + private static final long serialVersionUID = -2263090506226622866L; + + private String name; + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Student student = (Student) o; + + return name != null ? name.equals(student.name) : student.name == null; + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } +} + +public class Client { + public static void main(String[] args) throws Exception { + //使用new关键字创建对象 + Student student1 = new Student(); + + //使用clone()方法:类必须实现Cloneable接口,并重写其clone()方法 + Student student2 = (Student) student1.clone(); + + // 使用 反序列化ObjectInputStream的readObject()方法:类必须实现 Serializable接口 + // 序列化 + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.txt")); + objectOutputStream.writeObject(student1); + // 反序列化 + ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.txt")); + Student student3 = (Student) objectInputStream.readObject(); + } +} +``` +记得之前写过一篇 单例模式 的博客,其中最后就提到序列化也会破坏单例,就是因为反序列化会创建新的对象,所以我们在单例模式中要有readResolve()方法。 \ No newline at end of file diff --git a/apisecurity/src/main/java/cn/android/security/APISecurity.java b/apisecurity/src/main/java/cn/android/security/APISecurity.java index 77f532d..83810df 100644 --- a/apisecurity/src/main/java/cn/android/security/APISecurity.java +++ b/apisecurity/src/main/java/cn/android/security/APISecurity.java @@ -61,7 +61,7 @@ public class APISecurity { // Log.e("mhyLog", "hash:" + AppSigning.getSignatureHash(context)); // Log.e("mhyLog", "sha1:" + getSignSha1(context)); //runCommand(); - Log.e("mhyLog包文件", "签名:"+getApkSignatures(context, context.getPackageName())); + // Log.e("mhyLog包文件", "签名:"+getApkSignatures(context, context.getPackageName())); //Log.e("mhyLog已安装", "签名:"+getInstalledAPKSignature(context, context.getPackageName())); //通过获取其他应用的签名 如果一样那么被hook了 } diff --git a/apisecurity/src/main/java/cn/android/security/AppSigning.java b/apisecurity/src/main/java/cn/android/security/AppSigning.java index e612779..f4bfcdf 100644 --- a/apisecurity/src/main/java/cn/android/security/AppSigning.java +++ b/apisecurity/src/main/java/cn/android/security/AppSigning.java @@ -58,7 +58,8 @@ public class AppSigning { String fingerprint = "error!"; if (sigs.length > 0) { for (Signature sig : sigs) { - Log.e("mhyLog", "Signature64:" + Base64.encodeToString(sig.toCharsString().getBytes(), Base64.DEFAULT)); +// Log.e("mhyLog", "Signature64:" + Base64.encodeToString(sig.toCharsString().getBytes(), Base64.DEFAULT)); + Log.e("mhyLog", "SignatureHash:" + sig.toCharsString().hashCode()); } byte[] hexBytes = sigs[0].toByteArray(); try { diff --git a/app/.cxx/cmake/release/arm64-v8a/build_model.json b/app/.cxx/cmake/release/arm64-v8a/build_model.json index cbd80ff..2584bb7 100644 --- a/app/.cxx/cmake/release/arm64-v8a/build_model.json +++ b/app/.cxx/cmake/release/arm64-v8a/build_model.json @@ -165,7 +165,6 @@ "project": { "compilerSettingsCacheFolder": "G:\\AProject\\Mahy\\API-Security\\.cxx", "cxxFolder": "G:\\AProject\\Mahy\\API-Security\\.cxx", - "ideBuildTargetAbi": "arm64-v8a,armeabi-v7a,armeabi", "isBuildOnlyTargetAbiEnabled": true, "isCmakeBuildCohabitationEnabled": false, "isNativeCompilerSettingsCacheEnabled": false, @@ -188,8 +187,10 @@ "objFolder": "G:\\AProject\\Mahy\\API-Security\\app\\build\\intermediates\\cmake\\release\\obj", "variantName": "release", "validAbiList": [ + "ARMEABI_V7A", "ARM64_V8A", - "ARMEABI_V7A" + "X86", + "X86_64" ] } } \ No newline at end of file diff --git a/app/.cxx/cmake/release/armeabi-v7a/build_model.json b/app/.cxx/cmake/release/armeabi-v7a/build_model.json index b929f1e..860ab7d 100644 --- a/app/.cxx/cmake/release/armeabi-v7a/build_model.json +++ b/app/.cxx/cmake/release/armeabi-v7a/build_model.json @@ -165,7 +165,6 @@ "project": { "compilerSettingsCacheFolder": "G:\\AProject\\Mahy\\API-Security\\.cxx", "cxxFolder": "G:\\AProject\\Mahy\\API-Security\\.cxx", - "ideBuildTargetAbi": "arm64-v8a,armeabi-v7a,armeabi", "isBuildOnlyTargetAbiEnabled": true, "isCmakeBuildCohabitationEnabled": false, "isNativeCompilerSettingsCacheEnabled": false, @@ -188,8 +187,10 @@ "objFolder": "G:\\AProject\\Mahy\\API-Security\\app\\build\\intermediates\\cmake\\release\\obj", "variantName": "release", "validAbiList": [ + "ARMEABI_V7A", "ARM64_V8A", - "ARMEABI_V7A" + "X86", + "X86_64" ] } } \ No newline at end of file diff --git a/app/.cxx/cmake/release/armeabi-v7a/json_generation_record.json b/app/.cxx/cmake/release/armeabi-v7a/json_generation_record.json index d38f15e..11a4dde 100644 --- a/app/.cxx/cmake/release/armeabi-v7a/json_generation_record.json +++ b/app/.cxx/cmake/release/armeabi-v7a/json_generation_record.json @@ -11,6 +11,18 @@ "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", "tag": "release|armeabi-v7a" }, + { + "level": "INFO", + "message": "Trying to locate CMake in local SDK repository.", + "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", + "tag": "release|armeabi-v7a" + }, + { + "level": "INFO", + "message": "- CMake found in SDK at \u0027D:\\android-sdk-windows\\cmake\\3.10.2.4988404\u0027 had version \u00273.10.2\u0027", + "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", + "tag": "release|armeabi-v7a" + }, { "level": "INFO", "message": "JSON \u0027G:\\AProject\\Mahy\\API-Security\\app\\.cxx\\cmake\\release\\armeabi-v7a\\android_gradle_build.json\u0027 was up-to-date", diff --git a/app/.cxx/cmake/release/x86/json_generation_record.json b/app/.cxx/cmake/release/x86/json_generation_record.json index 35c1b4e..3fc3418 100644 --- a/app/.cxx/cmake/release/x86/json_generation_record.json +++ b/app/.cxx/cmake/release/x86/json_generation_record.json @@ -11,6 +11,18 @@ "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", "tag": "release|x86" }, + { + "level": "INFO", + "message": "Trying to locate CMake in local SDK repository.", + "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", + "tag": "release|x86" + }, + { + "level": "INFO", + "message": "- CMake found in SDK at \u0027D:\\android-sdk-windows\\cmake\\3.10.2.4988404\u0027 had version \u00273.10.2\u0027", + "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", + "tag": "release|x86" + }, { "level": "INFO", "message": "JSON \u0027G:\\AProject\\Mahy\\API-Security\\app\\.cxx\\cmake\\release\\x86\\android_gradle_build.json\u0027 was up-to-date", diff --git a/app/.cxx/cmake/release/x86_64/json_generation_record.json b/app/.cxx/cmake/release/x86_64/json_generation_record.json index d591440..e7a0556 100644 --- a/app/.cxx/cmake/release/x86_64/json_generation_record.json +++ b/app/.cxx/cmake/release/x86_64/json_generation_record.json @@ -11,6 +11,18 @@ "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", "tag": "release|x86_64" }, + { + "level": "INFO", + "message": "Trying to locate CMake in local SDK repository.", + "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", + "tag": "release|x86_64" + }, + { + "level": "INFO", + "message": "- CMake found in SDK at \u0027D:\\android-sdk-windows\\cmake\\3.10.2.4988404\u0027 had version \u00273.10.2\u0027", + "file": "G:\\AProject\\Mahy\\API-Security\\app\\CMakeLists.txt", + "tag": "release|x86_64" + }, { "level": "INFO", "message": "JSON \u0027G:\\AProject\\Mahy\\API-Security\\app\\.cxx\\cmake\\release\\x86_64\\android_gradle_build.json\u0027 was up-to-date", diff --git a/app/build.gradle b/app/build.gradle index 0c0be86..35f446d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,7 +53,7 @@ android { path "CMakeLists.txt" } } - + sourceSets.main.jniLibs.srcDirs = ['libs'] //为了直接读取 lib目录下 arm64-v8a/old.apk } diff --git a/app/src/main/cpp/apisecurity-lib.cpp b/app/src/main/cpp/apisecurity-lib.cpp index 06a378e..2470782 100644 --- a/app/src/main/cpp/apisecurity-lib.cpp +++ b/app/src/main/cpp/apisecurity-lib.cpp @@ -16,12 +16,12 @@ #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__) -//此处改为你的APP签名 -//#define SHA1 "a8e3d91a4f77dd7ccb8d43ee5046a4b6833f4785"//真实test.keystore -#define SHA1 "04c1411b0662acd9e4aa300559677e5f106a5255"//区分da小写 55 #define ALGORITHM_SHA1 "SHA1" #define ALGORITHM_MD5 "MD5" +//此处改为你的APP签名 +#define SHA1 "a8e3d91a4f77dd7ccb8d43ee5046a4b6833f4785"//真实test.keystore +//#define SHA1 "04c1411b0662acd9e4aa300559677e5f106a5255"//区分da小写 55 //此处改为你的APP包名 #define APP_PKG "cn.android.sample" #define APPLICATION_NAME "cn.android.sample.MyApplication" @@ -508,7 +508,7 @@ void checkTaskCount() { } /** - * Application.getClass().getName(); + * Application.getClass().getName(); 验证application是否被替换 */ extern "C" JNIEXPORT void JNICALL diff --git a/app/src/main/java/cn/android/sample/MainActivity.java b/app/src/main/java/cn/android/sample/MainActivity.java index 1aa08e1..4bcf324 100644 --- a/app/src/main/java/cn/android/sample/MainActivity.java +++ b/app/src/main/java/cn/android/sample/MainActivity.java @@ -21,19 +21,19 @@ public class MainActivity extends AppCompatActivity { tv = findViewById(R.id.sample_text); + APISecurity.verify(getApplicationContext()); + if(APISecurity.init(getApplicationContext())){ tv.setText("初始化ok"); }else { tv.setText("初始化fail"); } - APISecurity.verify(getApplicationContext()); + findViewById(R.id.btnTest).setOnClickListener(new View.OnClickListener() { @SuppressLint("SetTextI18n") @Override public void onClick(View v) { //API签名字符串 - String val = "POST https://www.xxx.com/login?id=1&pwd=xxx......"; - //计算签名 String aptStr="123456"; tv.setText("Sign:" + APISecurity.sign(aptStr)); } diff --git a/app/src/main/java/cn/android/sample/MyApplication.java b/app/src/main/java/cn/android/sample/MyApplication.java index 0d3feb4..8ff2e87 100644 --- a/app/src/main/java/cn/android/sample/MyApplication.java +++ b/app/src/main/java/cn/android/sample/MyApplication.java @@ -24,6 +24,9 @@ import android.util.Log; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; @@ -31,16 +34,18 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import cn.android.security.APISecurity; -//继承原application +import cn.android.security.AppSigning; + public class MyApplication extends Application implements InvocationHandler { private static final int GET_SIGNATURES = 64; + private static final int GET_SIGNING_CERTIFICATES = 134217728; private String appPkgName = ""; - private Object base; - private byte[][] sign; + private File apkPath;//源 apk目录 这样使读取源文件签名达到骗过验证 针对sdk28 新API + private Object base;//全局sPackageManager对象 + private byte[][] sign;//源 签名数组 static MyApplication app; - public MyApplication() { // 在构造函数里提早检测 // earlyCheckSign(); @@ -58,7 +63,15 @@ public class MyApplication extends Application implements InvocationHandler { } } - + private void copyFile(Context context, final String fileName) { + //data/app/packagename/lib/arm64/libold.so 将源文件搞到此目录 + String libPath = context.getApplicationInfo().nativeLibraryDir+File.separator+fileName; + apkPath=new File(libPath); + Log.e("mhyLog","File:"+libPath); + if (!apkPath.exists()){ + throw new RuntimeException("old.so未就位,libs/ABI对应目录/libold.so"); + } + } @Override protected void attachBaseContext(Context context) { //在这里hook 签名校验被 @@ -81,25 +94,26 @@ public class MyApplication extends Application implements InvocationHandler { * * @param context */ + @SuppressLint("PrivateApi") private void hook(Context context) { + copyFile(context, "libold.so");//源apk 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))); + 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"); +// 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"); + Class cls2 = Class.forName("android.content.pm.IPackageManager"); this.base = obj; this.sign = bArr; this.appPkgName = context.getPackageName(); @@ -120,59 +134,64 @@ public class MyApplication extends Application implements InvocationHandler { @Override public Object invoke(Object obj, Method method, Object[] objArr) throws Throwable { if ("getPackageInfo".equals(method.getName())) {//方法名对上 - Log.e("mhyLogHook","getPackageInfo"); + Log.e("mhyLogHook","getPackageInfo"+"_flag:"+(int)objArr[1]); String packageName = (String) objArr[0];//64 134217728 // int flag=((Integer) objArr[1]).intValue(); if (this.appPkgName.equals(packageName)) { PackageInfo packageInfo = (PackageInfo) method.invoke(this.base, objArr); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&(((Integer) objArr[1]).intValue() & 134217728) != 0) { -//packageInfo.signingInfo.getApkContentsSigners();//mSigningDetails.signatures -//mSigningDetails.signatures;//PackageParser.SigningDetails - SigningInfo signingInfo= packageInfo.signingInfo;//有坑空 -/*1*/ - Class sgInfo_clazz=Class.forName("android.content.pm.SigningInfo");//getClass()&Class.forName(“类完整的路径”)仅限于引用类型的对象 - Field mSigningDetails_f=sgInfo_clazz.getDeclaredField("mSigningDetails"); - mSigningDetails_f.setAccessible(true); - Object mSigningDetails = mSigningDetails_f.get(signingInfo);//PackageParser.SigningDetails -/*2*/ -// Class pkgParserCls = Class.forName("android.content.pm.PackageParser"); -// Constructor pkgParserCt = pkgParserCls.getConstructor(); -// Object pkgParser = pkgParserCt.newInstance(); -// 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, false); -// -//// 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); -/*end*/ - Class sd=Class.forName("android.content.pm.PackageParser$SigningDetails"); - //PackageParser.SigningDetails.signatures 这是一个final属性 只有在 new SigningDetails(...)时 - Field infoField = /*mSigningDetails.getClass()*/sd.getField("signatures"); - Signature[] info = new Signature[this.sign.length]; - for (int i = 0; i < this.sign.length; i++) { - info[i] = new Signature(this.sign[i]); - } - infoField.set(mSigningDetails, info); - Signature[] info2 = signingInfo.getApkContentsSigners();//获取属性值 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&((int) objArr[1] & GET_SIGNING_CERTIFICATES) != 0) {//a&b!=0 -> a=b + + Class pkgParserCls = Class.forName("android.content.pm.PackageParser"); + Constructor pkgParserCt = pkgParserCls.getConstructor();//可以反射任何构造器,可以反射私有构造器 + Object pkgParser = pkgParserCt.newInstance();//PackageParser() + //Package parsePackage(File packageFile, int flags) + Method parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, int.class); + Object pkgParserPkg = parsePackageMtd.invoke(pkgParser, apkPath, PackageManager.GET_SIGNING_CERTIFICATES);//Package + Method collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE); + if (!collectCertificatesMtd.isAccessible()){collectCertificatesMtd.setAccessible(true);} + //void collectCertificates(Package pkg, boolean skipVerify) + collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, true);//执行后 mSigningDetails就获取了值 到这里算是就给赋值了 +// collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, false);// Build.VERSION.SDK_INT > 28?: + + // PackageParser$Package里的属性 mSigningDetails public + Field mSigningDetailsField = pkgParserPkg.getClass().getDeclaredField("mSigningDetails"); + mSigningDetailsField.setAccessible(true); + //获取PackageParser$Package里mSigningDetails 对象 + Object mSigningDetails = mSigningDetailsField.get(pkgParserPkg); + + Class sigInfo_clazz=Class.forName("android.content.pm.SigningInfo"); +// Class mSigningDetails_clazz=Class.forName("android.content.pm.PackageParser$SigningDetails"); + /*clazz.newInstance();//只能反射()无参的构造器,需要构造器可见;*/ + //利用Constructor.newInstance()反射私有构造方法 @hide + Constructor sifInfoCt = sigInfo_clazz.getDeclaredConstructor(mSigningDetails.getClass()); + if(!sifInfoCt.isAccessible()) + sifInfoCt.setAccessible(true); + Object sifInfo_object = sifInfoCt.newInstance(mSigningDetails);//PackageParser() + +// Constructor sifInfoCt = sigInfo_clazz.getConstructor(mSigningDetails.getClass()); +// Object sifInfo_object = sifInfoCt.newInstance(mSigningDetails);//可以反射任何构造器,可以反射私有构造器 + + packageInfo.signingInfo= (SigningInfo) sifInfo_object; + + Field infoField = mSigningDetails.getClass().getDeclaredField("signatures");//final的 + infoField.setAccessible(true); + //验证 是否hook + Signature[] info2 = (Signature[]) infoField.get(mSigningDetails); if (info2.length>0){ - Log.e("mhyLogHook2",info2[0].toCharsString());} - } else { //双hook -// if ((((Integer) objArr[1]).intValue() & 64) != 0){ + Log.e("mhyLogHook2后",AppSigning.getSignatureString(info2,AppSigning.SHA1)); + } + } //else { //双hook + if ((((Integer) objArr[1]).intValue() & GET_SIGNATURES) != 0){ packageInfo.signatures = new Signature[this.sign.length]; for (int i = 0; i < packageInfo.signatures.length; i++) { packageInfo.signatures[i] = new Signature(this.sign[i]); } + Log.e("mhyLogHook1后",AppSigning.getSignatureString(packageInfo.signatures,AppSigning.SHA1)); } return packageInfo; } } - // IPackageManager 中无getPackageArchiveInfo 方法无法代理 + // IPackageManager接口中无getPackageArchiveInfo 方法无法代理 return method.invoke(this.base, objArr); }