从拦截器 bytebuddy 调用超类方法
Call superclass method from interceptor bytebuddy
我们有一个混淆的 class,我们需要使用 bytebuddy 来增强它。我们基本上需要重新定义一个方法。 Subclassing 似乎不起作用(代码未执行)。变基有效,但在我们拦截的方法中,我们需要调用 superclass (现在说 superclass 就像 "inheritance" )方法。
class Parent {
public void connect(){
...
};
}
class WeNeedToHackThis extends Parent {
public void connect(InetAddress addr){
//... this is what we want to hack
}
public void connect(){
this.connect(null);
// this is getting called from interceptor :( which delegates to our hacked method
// we need to call "real" superclass's (Parent) method instead
}
}
...
Class<?> dynamic = new ByteBuddy()
.with(TypeValidation.DISABLED)
.rebase(commandBase, locator)
.method(named("connect").and(takesArgument(0, InetAddress.class)))
.intercept(MethodDelegation.to(Session3270ConnectMethod.class))
.make()
.load(Thread.currentThread().getContextClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
//In our interceptor:
public static void connect(InetAddress paramInetAddress,
@Origin Method origin,
@This Object self) throws SessionException {
try {
System.out.println("hi from hijacked");
c.call();
//HOW DO WE CALL SOMETHING LIKE super.connect()
// we need to call Parent.connect();
// but I am stuck at how to access superclass code (new Parent().connect().
// I cant access the Parent class method calls on this object
// if I use @SuperCall or @This then I am getting already overriden version, I need to call the super (Parent's.class) version :(
} catch (Exception e) {
throw new RuntimeException(e);
}
}
如果我没理解错的话,您只想拦截从 class 外部而非内部调用的方法调用。
这是一件很难做到的事情。 Byte Buddy 允许您向任何 class 添加代码,但即使是手动,也很难将其编码出来。
你最好的机会可能是添加一个线程本地存储来标记这种自调用,并在拦截器再次被命中时检测它,你只需委托给超级方法而不应用拦截器逻辑。
public static void connect(InetAddress paramInetAddress,
@Super Object parentObj, @This Object myself, @SuperCall Callable<?> call) throws SessionException {
try {
System.out.println("hi from hijacked");
parentObj.getClass().getMethods();
Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
IMPL_LOOKUP.setAccessible(true);
MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
MethodHandle h1 = lkp.findSpecial(b.class, "connect", MethodType.methodType(void.class), Session3270.class);
h1.invoke(myself);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
我们有一个混淆的 class,我们需要使用 bytebuddy 来增强它。我们基本上需要重新定义一个方法。 Subclassing 似乎不起作用(代码未执行)。变基有效,但在我们拦截的方法中,我们需要调用 superclass (现在说 superclass 就像 "inheritance" )方法。
class Parent {
public void connect(){
...
};
}
class WeNeedToHackThis extends Parent {
public void connect(InetAddress addr){
//... this is what we want to hack
}
public void connect(){
this.connect(null);
// this is getting called from interceptor :( which delegates to our hacked method
// we need to call "real" superclass's (Parent) method instead
}
}
...
Class<?> dynamic = new ByteBuddy()
.with(TypeValidation.DISABLED)
.rebase(commandBase, locator)
.method(named("connect").and(takesArgument(0, InetAddress.class)))
.intercept(MethodDelegation.to(Session3270ConnectMethod.class))
.make()
.load(Thread.currentThread().getContextClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
//In our interceptor:
public static void connect(InetAddress paramInetAddress,
@Origin Method origin,
@This Object self) throws SessionException {
try {
System.out.println("hi from hijacked");
c.call();
//HOW DO WE CALL SOMETHING LIKE super.connect()
// we need to call Parent.connect();
// but I am stuck at how to access superclass code (new Parent().connect().
// I cant access the Parent class method calls on this object
// if I use @SuperCall or @This then I am getting already overriden version, I need to call the super (Parent's.class) version :(
} catch (Exception e) {
throw new RuntimeException(e);
}
}
如果我没理解错的话,您只想拦截从 class 外部而非内部调用的方法调用。
这是一件很难做到的事情。 Byte Buddy 允许您向任何 class 添加代码,但即使是手动,也很难将其编码出来。
你最好的机会可能是添加一个线程本地存储来标记这种自调用,并在拦截器再次被命中时检测它,你只需委托给超级方法而不应用拦截器逻辑。
public static void connect(InetAddress paramInetAddress,
@Super Object parentObj, @This Object myself, @SuperCall Callable<?> call) throws SessionException {
try {
System.out.println("hi from hijacked");
parentObj.getClass().getMethods();
Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
IMPL_LOOKUP.setAccessible(true);
MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
MethodHandle h1 = lkp.findSpecial(b.class, "connect", MethodType.methodType(void.class), Session3270.class);
h1.invoke(myself);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}