【发布时间】:2021-05-17 09:45:25
【问题描述】:
private void orsc.ORSCApplet.draw() 绘制视频游戏的每一帧。目标是拦截draw()方法,这样我们就可以自己在当前绘制的帧上绘制,这样我们就可以显示用户通常不可见的信息。
下面我用ByteBuddy新建一个orsc.ORSCApplet的子类,然后拦截draw()函数,让它正常调用draw(),同时也调用public void PaintCallback.paint()。
ClassLoader myLoader = this.getClass().getClassLoader();
new ByteBuddy().subclass(orsc.ORSCApplet.class)
.method(ElementMatchers.named("draw"))
.intercept(SuperMethodCall.INSTANCE.andThen(MethodCall.invoke(PaintCallback.class.getMethod("paint"))))
.make()
.load(myLoader); //I have also tried fromInstalledAgent (BuddyByteAgent.install() ran) and INJECTION
视频游戏的main() 在orsc.OpenRSC 内。因此,我们将使用类加载器和拦截方法创建一个新的orsc.OpenRSC 对象:
Class loadedMyClass = myLoader.loadClass("orsc.OpenRSC");
Constructor constructor = loadedMyClass.getConstructor();
Object myClassObject = constructor.newInstance();
return myClassObject; //later on, we call orsc.OpenRSC.main() with this object.
但是,我没有收到任何致电 PaintCallback.paint() 的电话。为什么我的拦截不起作用?我有三个理论:
-
尽管使用了
myLoader类加载器,该类仍在其他地方加载。但是,我尝试使用ByteBuddyAgent.install()并在.load(myLoader, ClassLoadingStrategy.fromInstalledAgent())中指定了这一点。 -
我应该尝试做
redefine,而不是做subclass?如果是这样,如果我intercept和redefine,我可以调用原始函数吗?如果是这样,怎么做?我尝试了很多不同的方法,结果在泥泞中旋转我的轮子。 -
我应该使用
rebase,而不是subclass或redefine?我用下面的代码尝试了这个,并从检测库中收到了一个异常:new ByteBuddy().rebase(orsc.ORSCApplet.class) .method(ElementMatchers.named("draw")) .intercept(SuperMethodCall.INSTANCE.andThen(MethodCall.invoke(PaintCallback.class.getMethod("paint")))) .make() .load(myLoader, ClassReloadingStrategy.fromInstalledAgent()); java.lang.IllegalStateException: Error invoking java.lang.instrument.Instrumentation#retransformClasses at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:503) at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$2.apply(ClassReloadingStrategy.java:568) at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:225) at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:100) at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6292) at reflector.Reflector.injectCallbacksAndReturnClient(Reflector.java:319) at reflector.Reflector.createClient(Reflector.java:50) at bot.Main.main(Main.java:164) Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method) at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:495) ... 7 more
【问题讨论】:
标签: java hook byte-buddy