文章目录
- 一、前言
- 二、实现方法
- 1、对静态函数的主动调用
- 2、ratel框架-对静态函数的主动调用
- 3、对实例方法进行主动调用(无参)
- 4、对实例方法进行主动调用(有参)
- 5、ratel框架-对实例方法进行主动调用(有参/无参)
- 6、内部类的方法主动调用(有参)
- 7、ratel框架-内部类函数主动调用(有参)
- 8、JNI函数主动调用
- 9、ratel框架-JNI函数主动调用
- 三、完整代码
一、前言
Java的反射机制是指在运行时动态地获取类的信息以及操作类的属性、方法、构造函数等的能力。通过反射机制,可以在程序运行时检查类的结构,获取类的字段、方法、注解等信息,调用类的方法,以及动态创建类的实例,而无需在编译时确定这些信息。
二、实现方法
1、对静态函数的主动调用
// 步骤一先通过这个app的classloader拿到类实例,(只有这个app的classloader才能加载这个app的类)
Class<?> ClassMysteryBox = lpparam.classLoader.loadClass("com.example.myapplication.MysteryBox");
// 步骤二通过实例拿到方法
Method staticMethod = ClassMysteryBox.getDeclaredMethod("staticMethod", String.class, int.class);
staticMethod.setAccessible(true);
// 步骤三通过方法进行调用
Object zhangsan = staticMethod.invoke(ClassMysteryBox, "张三", 1000);
Log.d(TAG, "handleLoadPackage: zhangsan = " + zhangsan);// 1.2 对实例方法进行主动调用 public String instanceMethod(String name,int price){
// 步骤一先调用目标方法的无参的默认的构造函数
Object instance = ClassMysteryBox.newInstance();
Method instanceMethod = ClassMysteryBox.getDeclaredMethod("instanceMethod", String.class, int.class);
Object lisi = instanceMethod.invoke(instance, "李四", 200);
Log.d(TAG, "handleLoadPackage: lisi = " + lisi);
2、ratel框架-对静态函数的主动调用
// 2.1 静态方法的调用 方法一:public static Object callStaticMethod(Class<?> clazz, String methodName, Object... args) {
Object o = RposedHelpers.callStaticMethod(ClassMysteryBox, "staticMethod", "张三", 200);
Log.d(TAG, "handleLoadPackage: o = " + o);
// 方法二(需要自己写参数类型):public static Object callStaticMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object... args) {
Object o1 = RposedHelpers.callStaticMethod(ClassMysteryBox, "staticMethod", new Class<?>[]{String.class, int.class}, "张三", 200);
Log.d(TAG, "handleLoadPackage: o1 = " + o1);
3、对实例方法进行主动调用(无参)
// 步骤一先调用目标方法的无参的默认的构造函数
Object instance = ClassMysteryBox.newInstance();
Method instanceMethod = ClassMysteryBox.getDeclaredMethod("instanceMethod", String.class, int.class);
Object lisi = instanceMethod.invoke(instance, "李四", 200);
Log.d(TAG, "handleLoadPackage: lisi = " + lisi);
4、对实例方法进行主动调用(有参)
// private MysteryBox(String brand){
Constructor<?> declaredConstructor = ClassMysteryBox.getDeclaredConstructor(int.class);
Object instance1 = declaredConstructor.newInstance(222222);
Log.d(TAG, "handleLoadPackage: instance1 = " + instance1);
Object wangwu = instanceMethod.invoke(instance1, "王五", 600);
Log.d(TAG, "handleLoadPackage: wangwu = " + wangwu);
5、ratel框架-对实例方法进行主动调用(有参/无参)
// public static Object newInstance(Class<?> clazz, Object... args) {
// public static Object newInstance(Class<?> clazz, Class<?>[] parameterTypes, Object... args) {
// 无参构造函数实例化
Object o2 = RposedHelpers.newInstance(ClassMysteryBox);
Log.d(TAG, "handleLoadPackage: o2 = " + o2);Object instance5 = RposedHelpers.newInstance(ClassMysteryBox, "测试");
Log.d(TAG, "handleLoadPackage: instance5 = " + instance5);
6、内部类的方法主动调用(有参)
// 通过类加载器加载目标类
Class<?> classInnerClass = lpparam.classLoader.loadClass("com.example.myapplication.MysteryBox$InnerClass");
// 获取构造函数进行类实例
Constructor<?> declaredConstructor1 = classInnerClass.getDeclaredConstructor();
declaredConstructor1.setAccessible(true);
Object instance2 = declaredConstructor1.newInstance();
// 获取类的方法
Method innerClassMethod = classInnerClass.getDeclaredMethod("innerClassMethod", String.class, int.class);
innerClassMethod.setAccessible(true);
// 进行方法调用
Object zhaoliu = innerClassMethod.invoke(instance2, "赵六", 300);
Log.d(TAG, "handleLoadPackage: zhaoliu = " + zhaoliu);
7、ratel框架-内部类函数主动调用(有参)
Class<?> aClass = RposedHelpers.findClass("com.example.myapplication.MysteryBox$InnerClass", lpparam.classLoader);
Object o3 = RposedHelpers.callMethod(RposedHelpers.newInstance(aClass), "innerClassMethod", "赵六", 200);
Log.d(TAG, "handleLoadPackage: o3 = " + o3);
8、JNI函数主动调用
// 1.4 对于JNI函数的处理(native)
Class<?> NativeLib = lpparam.classLoader.loadClass("com.example.myapplication.NativeLib");
Constructor<?> constructor = NativeLib.getConstructor();
constructor.setAccessible(true);
Object instance3 = constructor.newInstance();
Method nativeMethod = NativeLib.getDeclaredMethod("nativeMethod");
// native和private方法都要设true才能访问
nativeMethod.setAccessible(true);
Object result = nativeMethod.invoke(instance3);
Log.d(TAG, "handleLoadPackage: result = " + result);
9、ratel框架-JNI函数主动调用
// 2.4 JNI函数的处理
Object instance6 = RposedHelpers.newInstance(RposedHelpers.findClass("com.example.myapplication.NativeLib", lpparam.classLoader));
Object nativeMethod1 = RposedHelpers.callMethod(instance6, "nativeMethod");
// 这里打印出来的依然是没有经过生命周期处理后的值,因为这是直接new的activity的实例,不会经过oncreate的处理
Log.d(TAG, "handleLoadPackage: nativeMethod1 = " + nativeMethod1);
三、完整代码
package com.example.plugintest;import android.os.Bundle;
import android.util.Log;import com.virjar.ratel.api.rposed.IRposedHookLoadPackage;
import com.virjar.ratel.api.rposed.RC_MethodHook;
import com.virjar.ratel.api.rposed.RposedHelpers;
import com.virjar.ratel.api.rposed.callbacks.RC_LoadPackage;import java.lang.reflect.Constructor;
import java.lang.reflect.Method;public class InvokeEntry implements IRposedHookLoadPackage {private static final String TAG = "pluginTest->";@Overridepublic void handleLoadPackage(RC_LoadPackage.LoadPackageParam lpparam) throws Throwable {System.out.println(TAG + "包名是什么:" + lpparam.packageName);if (lpparam.packageName.equals("com.example.myapplication")){Log.d(TAG, "handleLoadPackage: hook success");// 1. 利用Java的反射机制完成对于类函数的主动调用// 1.1 对静态函数的主动调用 public static String staticMethod(String name,int price){// 步骤一先通过这个app的classloader拿到类实例,(只有这个app的classloader才能加载这个app的类)Class<?> ClassMysteryBox = lpparam.classLoader.loadClass("com.example.myapplication.MysteryBox");// 步骤二通过实例拿到方法Method staticMethod = ClassMysteryBox.getDeclaredMethod("staticMethod", String.class, int.class);staticMethod.setAccessible(true);// 步骤三通过方法进行调用Object zhangsan = staticMethod.invoke(ClassMysteryBox, "张三", 1000);Log.d(TAG, "handleLoadPackage: zhangsan = " + zhangsan);// 1.2 对实例方法进行主动调用 public String instanceMethod(String name,int price){// 步骤一先调用目标方法的无参的默认的构造函数Object instance = ClassMysteryBox.newInstance();Method instanceMethod = ClassMysteryBox.getDeclaredMethod("instanceMethod", String.class, int.class);Object lisi = instanceMethod.invoke(instance, "李四", 200);Log.d(TAG, "handleLoadPackage: lisi = " + lisi);// 如果采用有参的构造函数// private MysteryBox(String brand){Constructor<?> declaredConstructor = ClassMysteryBox.getDeclaredConstructor(int.class);Object instance1 = declaredConstructor.newInstance(222222);Log.d(TAG, "handleLoadPackage: instance1 = " + instance1);Object wangwu = instanceMethod.invoke(instance1, "王五", 600);Log.d(TAG, "handleLoadPackage: wangwu = " + wangwu);// 1.3 内部类的处理// 通过类加载器加载目标类Class<?> classInnerClass = lpparam.classLoader.loadClass("com.example.myapplication.MysteryBox$InnerClass");// 获取构造函数进行类实例Constructor<?> declaredConstructor1 = classInnerClass.getDeclaredConstructor();declaredConstructor1.setAccessible(true);Object instance2 = declaredConstructor1.newInstance();// 获取类的方法Method innerClassMethod = classInnerClass.getDeclaredMethod("innerClassMethod", String.class, int.class);innerClassMethod.setAccessible(true);// 进行方法调用Object zhaoliu = innerClassMethod.invoke(instance2, "赵六", 300);Log.d(TAG, "handleLoadPackage: zhaoliu = " + zhaoliu);// 1.4 对于JNI函数的处理(native)Class<?> NativeLib = lpparam.classLoader.loadClass("com.example.myapplication.NativeLib");Constructor<?> constructor = NativeLib.getConstructor();constructor.setAccessible(true);Object instance3 = constructor.newInstance();Method nativeMethod = NativeLib.getDeclaredMethod("nativeMethod");// native和private方法都要设true才能访问nativeMethod.setAccessible(true);Object result = nativeMethod.invoke(instance3);Log.d(TAG, "handleLoadPackage: result = " + result);// 1.5 处理1.4存在的问题:像1.4那样new MainActivity实例是不会走oncreate等等的生命周期,所以在各生命周期中做的赋值或修改操作将无法// 出现在新实例中。于是我们不需要自己new,而是hook它本来存在的那个//RposedHelpers.findAndHookMethod(NativeLib, "onCreate", Bundle.class, new RC_MethodHook() {// @Override// protected void afterHookedMethod(MethodHookParam param) throws Throwable {// super.afterHookedMethod(param);// // 获得真实运行在app中的实例// Object thisObject = param.thisObject;// Object invoke = nativeMethod.invoke(thisObject);// Log.d(TAG, "afterHookedMethod: 真实返回值为:" + invoke);// }//});// 通过平头哥框架完成函数的主动调用// 2.1 静态方法的调用 方法一:public static Object callStaticMethod(Class<?> clazz, String methodName, Object... args) {Object o = RposedHelpers.callStaticMethod(ClassMysteryBox, "staticMethod", "张三", 200);Log.d(TAG, "handleLoadPackage: o = " + o);// 方法二(需要自己写参数类型):public static Object callStaticMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object... args) {Object o1 = RposedHelpers.callStaticMethod(ClassMysteryBox, "staticMethod", new Class<?>[]{String.class, int.class}, "张三", 200);Log.d(TAG, "handleLoadPackage: o1 = " + o1);// 2.2 实例函数的调用// public static Object newInstance(Class<?> clazz, Object... args) {// public static Object newInstance(Class<?> clazz, Class<?>[] parameterTypes, Object... args) {// 无参构造函数实例化Object o2 = RposedHelpers.newInstance(ClassMysteryBox);Log.d(TAG, "handleLoadPackage: o2 = " + o2);Object instance5 = RposedHelpers.newInstance(ClassMysteryBox, "测试");Log.d(TAG, "handleLoadPackage: instance5 = " + instance5);// 2.3 内部类的处理Class<?> aClass = RposedHelpers.findClass("com.example.myapplication.MysteryBox$InnerClass", lpparam.classLoader);Object o3 = RposedHelpers.callMethod(RposedHelpers.newInstance(aClass), "innerClassMethod", "赵六", 200);Log.d(TAG, "handleLoadPackage: o3 = " + o3);// 2.4 JNI函数的处理Object instance6 = RposedHelpers.newInstance(RposedHelpers.findClass("com.example.myapplication.NativeLib", lpparam.classLoader));Object nativeMethod1 = RposedHelpers.callMethod(instance6, "nativeMethod");// 这里打印出来的依然是没有经过生命周期处理后的值,因为这是直接new的activity的实例,不会经过oncreate的处理Log.d(TAG, "handleLoadPackage: nativeMethod1 = " + nativeMethod1);}}
}