BCEL ClassLoader去哪了?

本文探讨了BCEL(Apache Commons BCEL)在Java中的作用,特别是其在Fastjson漏洞利用中的角色。BCEL由于与Xalan的依赖关系被包含在JDK中,用于动态生成Java字节码。然而,从Java 8u251开始,BCEL的ClassLoader不见了。文章分析了可能的原因,包括BCEL的版本升级和相关源码的变更历史,揭示了Java更新中可能的疏漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

com.sun.org.apache.bcel.internal.util.ClassLoader是常常在构造漏洞利用POC时用到的类。但是,我前几天在写《Java安全漫谈》的时候,偶然发现我环境中的com.sun.org.apache.bcel.internal.util.ClassLoader类找不到了,本文就带大家来找找BCEL ClassLoader。

0x01 BCEL从哪里来

首先,BCEL究竟是什么?它为什么会出现在JDK中?

BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一个子项目。Apache Commons大家应该不陌生,反序列化最著名的利用链就是出自于其另一个子项目——Apache Commons Collections。

BCEL库提供了一系列用于分析、创建、修改Java Class文件的API。

就这个库的功能来看,其使用面远不及同胞兄弟们,但是他比Commons Collections特殊的一点是,它被包含在了原生的JDK中,位于com.sun.org.apache.bcel

据我(不严谨)的考证,JDK会将BCEL放到自己的代码中,主要原因是为了支撑Java XML相关的功能。准确的来说,Java XML功能包含了JAXP规范,而Java中自带的JAXP实现使用了Apache Xerces和Apache Xalan,Apache Xalan又依赖了BCEL,所以BCEL也被放入了标准库中。

JAXP全名是Java API for XML Processing,他是Java定义的一系列接口,用于处理XML相关的逻辑,包括DOM、SAX、StAX、XSLT等。Apache Xalan实现了其中XSLT相关的部分,其中包括xsltc compiler。

XSLT(扩展样式表转换语言)是一种为可扩展置标语言提供表达形式而设计的计算机语言,主要用于将XML转换成其他格式的数据。既然是一门动态“语言”,在Java中必然会先被编译成Java,才能够执行。

XSLTC Compiler就是一个命令行编译器,可以将一个xsl文件编译成一个class文件或jar文件,编译后的class被称为translet,可以在后续用于对XML文件的转换。其实就将XSLT的功能转化成了Java代码,优化执行的速度,如果我们不使用这个命令行编译器进行编译,Java内部也会在运行过程中存在编译的过程。

我们尝试用本地的Java(注意需要用Java7或6,使用8将会出现异常)来编译一下hello.xsl:

java com.sun.org.apache.xalan.internal.xsltc.cmdline.Compile hello.xsl

可见,从hello.xsl生成了hello.class,反编译这个class即可看到源代码。

不知道大家看到这个代码里的AbstractTranslet会不会有点眼熟?我们在反序列化时常用的另一个类com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl,它在defineClass中需要的字节码所对应的基类,就是这里的com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet

其实Java里很多东西是有因果的,TemplatesImpl是对JAXP标准中javax.xml.transform.Templates接口的实现,前文说了,XSLT在使用时会先编译成Java字节码,这也就是为什么TemplatesImpl会使用defineClass的原因。

关于XSLT这块的内容比较多,不是本文的重点,我就不细说了。那么这部分内容和BCEL有什么关系呢?

你应该也能猜到了,因为需要“编译”XSL文件,实际上核心是动态生成Java字节码,而BCEL正是一个处理字节码的库,所以Apache Xalan是依赖BCEL的。

0x02 BCEL ClassLoader如何使用

BCEL这个包中有个有趣的类com.sun.org.apache.bcel.internal.util.ClassLoader,他是一个ClassLoader,但是他重写了Java内置的ClassLoader#loadClass()方法。

ClassLoader#loadClass()中,其会判断类名是否是$$BCEL$$开头,如果是的话,将会对这个字符串进行decode。具体算法在这里:

  private static class JavaWriter extends FilterWriter {
&nbs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值