美文网首页
Java 反射之Hook 实例

Java 反射之Hook 实例

作者: 行走中的3卡 | 来源:发表于2022-04-22 15:18 被阅读0次

Hook 机制主要是通过反射机制,在运行时改变某个对象的属性或者行为(很抽象!!!),
所以必须以实例作为学习的切入点。
或者可以参考:其实用高大上的Hook技术动态注入代码很简单,一看就会! - JavaShuo

这里仅做实例记录

1. 普通场景

直接上代码, 很容易看懂
(1) Weapon 类

package com.example.javalearnproject.reflectbasictest.hook;

public class Weapon {
    protected int damage = 10;

    public void attack(){
        System.out.println(String.format("对目标形成 %d 点伤害",damage));
    }
}

(2) Hero 类

package com.example.javalearnproject.reflectbasictest.hook;

public class Hero {
    private Weapon weaponMain;

    public Hero(Weapon weaponMain) {
        this.weaponMain = weaponMain;
    }

    public void attack(){
        weaponMain.attack();
    }
}

(3) Game 类

package com.example.javalearnproject.reflectbasictest.hook;

public class Game {
    public static void main(String[] args){
        Hero hero = new Hero(new Weapon());
        hero.attack();
    }
}

输出:

对目标形成 10 点伤害

2. Hook 场景(改变属性值)

(1) Hero 保存不变
(2) WeaponHook 继承Weapon, 并且在attack方法中设置回调

package com.example.javalearnproject.reflectbasictest.hook.dohook;

//对于上面这段程序,游戏对咱们隐藏了Weapon的伤害值,但如今咱们想要在每次攻击的时候知道这个伤害值是多少。
//下面看看使用Hook机制如何来实现。

import com.example.javalearnproject.reflectbasictest.hook.Weapon;

//首先咱们经过观察,发现切入点就是weaponMain,咱们要对它下手。
//建立一个Weapon的复制品WeaponHook,咱们须要用本身的人WeaponHook打入内部。
//WeaponHook一切看起来都和Weapon那么类似,可是咱们给它留了一个后门,使得咱们能够进行监控。
public class WeaponHook extends Weapon {
    private OnUseWeaponAttackListener onUseWeaponAttackListener;

    @Override
    public void attack(){
        super.attack();
        System.out.println("WeaponHook has called Weapon.attach");
        if (onUseWeaponAttackListener != null){
            onUseWeaponAttackListener.onUseWeaponAttack(damage);
        }
    }

    public void setOnUseWeaponAttackListener(OnUseWeaponAttackListener onUseWeaponAttackListener) {
        this.onUseWeaponAttackListener = onUseWeaponAttackListener;
    }

    //这就是咱们的后门
    public static interface OnUseWeaponAttackListener {
        int onUseWeaponAttack(int damage);
    }
}

(3) GameHook 反射注入 WeaponHook对象

package com.example.javalearnproject.reflectbasictest.hook.dohook;

import com.example.javalearnproject.reflectbasictest.hook.Hero;
import com.example.javalearnproject.reflectbasictest.hook.Weapon;

import java.lang.reflect.Field;

public class GameHook {
    public static void main(String[] args){
        Hero hero = new Hero(new Weapon());
        try {
            //Field weapon = ReflectUtils.getVariable(hero.getClass(), "weaponMain");
            Class<?> heroClass = hero.getClass();
            //Field weapon = heroClass.getField("weaponMain");// 不包含私有属性
            Field weapon = heroClass.getDeclaredField("weaponMain");// 包含私有属性
            weapon.setAccessible(true);
            Weapon weaponHook = new WeaponHook();
            ((WeaponHook) weaponHook).setOnUseWeaponAttackListener(damage -> {
                //经过后门进行操做,这其实就是咱们注入的代码
                System.out.println("damage = " + damage);
                return damage;
            });
            weapon.set(hero, weaponHook); //偷天换日  >>> 关键操作,替换掉原来的成员变量  (属性.set(对象,新的成员变量的对象))
            hero.attack(); //最终调用的是 weaponHook
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

此时输出:

对目标形成 10 点伤害
WeaponHook has called Weapon.attach
damage = 10

3. 防止Hook入侵

(1) HeroPro 增加hashcode判断

package com.example.javalearnproject.reflectbasictest.hook.hookprotect;

import com.example.javalearnproject.reflectbasictest.hook.Weapon;

public class HeroPro {
    private Weapon weaponMain;
    private final int weaponMainId;

    public HeroPro(Weapon weaponMain) {
        this.weaponMain = weaponMain;
        weaponMainId = this.weaponMain.hashCode();//记录原始Weapon对象的Id,hashCode对于每一个对象而言都是惟一的。
    }

    public void attack() {
        if (this.weaponMain.hashCode() != weaponMainId) { //关键位置检查是否遭到替换
            throw new IllegalAccessError(String.format("警告!遭到入侵!入侵者身份:%d", this.weaponMain.hashCode()));
        }
        weaponMain.attack();
    }
}

(2) GamePro 确认是否还可以hook 入侵

package com.example.javalearnproject.reflectbasictest.hook.hookprotect;

import com.example.javalearnproject.reflectbasictest.hook.Weapon;
import com.example.javalearnproject.reflectbasictest.hook.dohook.WeaponHook;

import java.lang.reflect.Field;

public class GamePro {
    public static void main(String[] args){
        HeroPro hero = new HeroPro(new Weapon());
        try {
            //Field weapon = ReflectUtils.getVariable(hero.getClass(), "weaponMain");
            Class<?> heroClass = hero.getClass();
            //Field weapon = heroClass.getField("weaponMain");// 不包含私有属性
            Field weapon = heroClass.getDeclaredField("weaponMain");// 包含私有属性
            weapon.setAccessible(true);
            Weapon weaponHook = new WeaponHook();
            ((WeaponHook) weaponHook).setOnUseWeaponAttackListener(damage -> {
                //经过后门进行操做,这其实就是咱们注入的代码
                System.out.println("damage = " + damage);
                return damage;
            });
            weapon.set(hero, weaponHook); //偷天换日  >>> 关键操作,替换掉原来的成员变量  (属性.set(对象,新的成员变量的对象))
            hero.attack(); //最终调用的是 weaponHook
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

(3) WeaponHook保持不变

输出(Exception):

Exception in thread "main" java.lang.IllegalAccessError: 警告!遭到入侵!入侵者身份:1060830840
    at com.example.javalearnproject.reflectbasictest.hook.hookprotect.HeroPro.attack(HeroPro.java:16)
    at com.example.javalearnproject.reflectbasictest.hook.hookprotect.GamePro.main(GamePro.java:24)

-- End --

相关文章

  • Java 反射之Hook 实例

    Hook 机制主要是通过反射机制,在运行时改变某个对象的属性或者行为(很抽象!!!),所以必须以实例作为学习的切入...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • Java 反射

    Java反射Java反射API获取Class对象通过反射创建实例对象,调用公共方法通过反射调用私有方法 一.Jav...

  • 反射破坏单例模式(静态内部类)

    java反射,破坏单例模式 静态内部类 反射实例化单例

  • Java反射实例

    反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。在两个人...

  • java反射实例

    理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底...

  • Java 反射实例

    反射获取 Class类的对象有三种方式:Object类中的getClass()方法类.class通过Class类的...

  • Java高级-反射

    15.1.Java反射机制概述 15.2.理解Class类并获取Class实例(重点) 用反射实现类的实例化,调用...

  • 反射实例——JAVA反射机制

    一、Java反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为...

  • Java反射 - 构造函数

    Java反射——构造函数使用Java反射,您可以检查类的构造函数,并在运行时实例化对象。 这是通过Java类jav...

网友评论

      本文标题:Java 反射之Hook 实例

      本文链接:https://www.haomeiwen.com/subject/wdrnertx.html