安卓逆向-new-sec6-4 Java反射相关知识以及平头哥框架hook构造函数 | App发布测试版本感染

反射机制

安卓逆向-new-sec6-4 Java反射相关知识以及平头哥框架hook构造函数 | App发布测试版本感染_第1张图片

安卓逆向-new-sec6-4 Java反射相关知识以及平头哥框架hook构造函数 | App发布测试版本感染_第2张图片
安卓逆向-new-sec6-4 Java反射相关知识以及平头哥框架hook构造函数 | App发布测试版本感染_第3张图片

安卓逆向-new-sec6-4 Java反射相关知识以及平头哥框架hook构造函数 | App发布测试版本感染_第4张图片

app加上这个属性,也能发布测试版本,被成功感染,无需签名和发布那个release版本

安卓逆向-new-sec6-4 Java反射相关知识以及平头哥框架hook构造函数 | App发布测试版本感染_第5张图片

APP是E:\1A_androidstudio_project\course4

插件是E:\1A_androidstudio_project\project_save

// HookConstructorEntry.java
package com.sam.myapplicationcj;

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;

public class HookConstructorEntry implements IRposedHookLoadPackage {

    private static final String TAG = "yuanrenxue->";

    @Override
    public void handleLoadPackage(RC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("com.yuanrenxue.course4")){
            Log.d(TAG,"handleLoadPackage: hooked success");

            // findAndHookConstructor的第一种重载方法(需要传入class实例对象):public static RC_MethodHook.Unhook findAndHookConstructor(Class clazz, Object... parameterTypesAndCallback) {
            // 通过classLoader去拿class实例对象
            Class<?> MysteryBoxClass = lpparam.classLoader.loadClass("com.yuanrenxue.course4.MysteryBox");
            RposedHelpers.findAndHookConstructor(MysteryBoxClass, new RC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    Object[] objects = param.args;
                    Log.d(TAG, "beforeHookedMethod: objects length = " + objects.length);
                    super.beforeHookedMethod(param);
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                }
            });

            // findAndHookConstructor的第二种重载方法(需要传入全类名,):public static RC_MethodHook.Unhook findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback) {
            // 其实第二种方法内部也是先调用第一种方法的拿class对象的:先通过方法一classLoader去拿class实例对象->拿到构造器方法->hook
            // 这里hook带int参数的构造函数
            RposedHelpers.findAndHookConstructor("com.yuanrenxue.course4.MysteryBox", lpparam.classLoader, int.class, new RC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    Log.d(TAG, "beforeHookedMethod: price:" + param.args[0]);
                    // 修改参数的值
                    param.args[0] = 100000;
                    super.beforeHookedMethod(param);
                }
            });

            // hook传两个参数的那个构造函数
            RposedHelpers.findAndHookConstructor("com.yuanrenxue.course4.MysteryBox", lpparam.classLoader, int.class,String.class, new RC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    Log.d(TAG, "beforeHookedMethod: price:" + param.args[0]);
                    // 修改参数的值
                    param.args[0] = 100000;
                    param.args[1] = "一个被我暗中打开的盲盒";
                    super.beforeHookedMethod(param);
                }

                // 如何拿到构造成功返回的实例
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    // 打印一下param.thisObject和param.getResult()分别拿到的是什么>>>afterHookedMethod: com.yuanrenxue.course4.MysteryBox@d78a80e,null
                    // 构造函数返回值是空值,所以不能通过getResult去拿
                    Log.d(TAG, "afterHookedMethod: " + param.thisObject + "," + param.getResult());
                }
            });

        }
    }
}
// ExampleUnitTest.java(反射的代码)
package com.yuanrenxue.course4;

import org.junit.Test;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see Testing documentation
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() {
        assertEquals(4, 2 + 2);
    }

    // 获取Class对象的⽅法
    @Test
    public void getClassDemo() throws Exception{
        // 1. 通过类直接获取
        Class<?> class1 = MysteryBox.class;
        System.out.println(class1);
        // 2. 通过对象获取Class
        MysteryBox box = new MysteryBox();
        Class<?> aClass = box.getClass();
        System.out.println(aClass);
        // 3. 通过全类名获取--通过forName
        Class<?> aClass1 = Class.forName("com.yuanrenxue.course4.MysteryBox");
        System.out.println(aClass1);
        // 通过全类名获取--通过ClassLoader
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        Class<?> aClass2 = systemClassLoader.loadClass("com.yuanrenxue.course4.MysteryBox");
        System.out.println(aClass2);
    }

    // 如何判断是否为某个类的实例
    @Test
    public void checkInstanceOf(){
        MysteryBox box = new MysteryBox();
        // 通过instanceOf关键字来判断
        System.out.println(box instanceof MysteryBox);
        // class.isInstance--利用反射
        System.out.println(MysteryBox.class.isInstance(box));
        // isAssignableFrom--利用反射。
        System.out.println(box.getClass().isAssignableFrom(MysteryBox.class));
        // 我插入的两段,为了更好滴理解getClass()和.class
        System.out.println(box.getClass());
        System.out.println(MysteryBox.class);
    }

    // 如何通过反射的思路来创建对象
    @Test
    public void createInstance() throws Exception{
        Class<MysteryBox> mysteryBoxClass = MysteryBox.class;
        // 1. newInstance。使⽤Class对象的newInstance()⽅法来创建Class对象对应类的实例(默认走无参的构造函数)
        MysteryBox box1 = (MysteryBox) mysteryBoxClass.newInstance();
        System.out.println(box1.getContent());
        // 2. 首先获取到构造器,然后实例化类实例。先通过Class对象获取指定的Constructor对象,再调⽤Constructor对象的newInstance()⽅法来创建
        //实例。这种⽅法可以⽤指定的构造器构造类的实例
        Constructor<?> constructor = mysteryBoxClass.getConstructor();
        Object box2 = constructor.newInstance();
        System.out.println(box2);
    }

    // 通过指定不同的的构造器构造类的实例
    @Test
    public void getConstructor() throws Exception{
        // 1. getConstructor---只能获取public修饰的构造函数
        Constructor<?> constructor = MysteryBox.class.getConstructor(int.class);
        System.out.println(constructor);

        // 2. getConstructors 获取所有的构造函数---只能获取public修饰的构造函数
        Constructor<?>[] constructors = MysteryBox.class.getConstructors();
        System.out.println(Arrays.toString(constructors));

        // 3. getConstructor 获取private修饰的构造函数---会报错java.lang.NoSuchMethodException: com.yuanrenxue.course4.MysteryBox.(java.lang.String)
        // Constructor constructor1 = MysteryBox.class.getConstructor(String.class);

        // 如何获取private构造函数
        Constructor<MysteryBox> declaredConstructor = MysteryBox.class.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor);

        // 如何获取所有的构造函数,不论是public修饰还是private修饰
        Constructor<?>[] declaredConstructors = MysteryBox.class.getDeclaredConstructors();
        System.out.println(Arrays.toString(declaredConstructors));
    }

    // 如何获取成员变量
    @Test
    public void getFields() throws Exception{
        MysteryBox box = new MysteryBox();
        // 这里的getField()和上面的getConstructor()一样,只能获取public修饰的属性不能获取private修饰的
        Field priceField = MysteryBox.class.getField("price");
        System.out.println(priceField);

        // 获取所有的public修饰的属性
        Field[] fields = MysteryBox.class.getFields();
        for(Field field:fields){
            // field.get()取得对象的Field属性值,如果字段不是静态字段的话,要传入反射类的对象.如果传null是会报java.lang.NullPointerException,
            // 如果字段是静态字段的话,传入任何对象都是可以的,包括null
            System.out.println(field.getName() + "," + field.get(box));
        }

        // 获取private修饰的属性
        Field content = MysteryBox.class.getDeclaredField("content");
        content.setAccessible(true);
        System.out.println(box.getContent());
        System.out.println(content.get(box));
        box.open();
        System.out.println(box.getContent());

        // 获取不论private还是public修饰的属性
        Field[] declaredFields = MysteryBox.class.getDeclaredFields();
        for(Field field:declaredFields){
            field.setAccessible(true);
            System.out.println(field.getName() + "," + field.get(box));
        }
    }

    // 获取类的方法
    @Test
    public void getMethods() throws Exception{
        MysteryBox box = new MysteryBox();
        // 获取public修饰的方法
        Method getContent = MysteryBox.class.getMethod("getContent");
        Object content = getContent.invoke(box);
        System.out.println(content);

        // 获取所有public修饰的方法
        Method[] methods = MysteryBox.class.getMethods();
        for(Method method:methods){
            System.out.println(method);
        }


        box.open();
        System.out.println(box.getContent());
        // 获取private修饰的方法
        Method close = MysteryBox.class.getDeclaredMethod("close");
        close.setAccessible(true);
        close.invoke(box);
        System.out.println(box.getContent());

        // 获取不论是public还是private修饰的方法
        Method[] declaredMethods = MysteryBox.class.getDeclaredMethods();
        for(Method method:declaredMethods){
            System.out.println(method);
        }
    }
}

你可能感兴趣的:(java,android)