hooK 1 2成功
This commit is contained in:
87
README.md
87
README.md
@@ -551,3 +551,90 @@ versionI() {
|
||||
net. bt. name=Android (系统名称)
|
||||
dalvik.vm.stack-trace-file=/data/anr/traces.txt
|
||||
```
|
||||
|
||||
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()方法。
|
||||
@@ -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了
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -53,7 +53,7 @@ android {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets.main.jniLibs.srcDirs = ['libs'] //为了直接读取 lib目录下 arm64-v8a/old.apk
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user