app逆向-ratel框架-通过Java的反射机制主动调用Java类函数

一、前言

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

    @Override
    public 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);
        }
    }
}
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是花臂不花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值