- 类别:bytecode 别名:— 优先级:200
- 作者:Ar3h
- 依赖:无(仅需 JVM 与 Javassist 工具类)
从磁盘上的一个 .class 文件读取原始字节码,作为链尾的「字节码源」交给上游的字节码加载器(如 TemplatesImpl)去 defineClass 并实例化。用于让使用者投递完全自定义的恶意类,而不局限于工具内置的 Exec/DNSLog 等模板。
- 入口
tags:Bytecode—— 声明本 gadget 产出「原始字节码byte[]」,可被nextTags=Bytecode的加载器(BytecodeConvert)承接。BytecodeConvertTag—— 同时声明自己可占据「字节码转换器」这一槽位,因此也能被nextTags=BytecodeConvertTag的加载型 gadget(如TemplatesImpl段)直接承接,省去中间的BytecodeConvert处理环节。END—— 链终止标签,本 gadget 是最内层 sink,之后不再有内层对象。
- 衔接
nextTags:空 —— 它自身就是字节码源头,不再向内包裹。 excludes:无。
核心逻辑集中在 getObject:
public byte[] getObject(GadgetContext context) throws Exception {
byte[] bytecode = FileHelper.fileGetContent(this.path); // 从本地路径读原始 .class 字节
JavassistHelper javassistHelper = new JavassistHelper(bytecode);
context.put(ContextTag.CLASS_NAME_KEY, javassistHelper.getClassName()); // 把类名写入上下文
return javassistHelper.getBytecode(); // 返回(经 Javassist 归一化的)字节码
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
chain.doCreate(context); // 触发内层(通常为空/END),保持接口约定
return this.getObject(context);
}关键点:
FileHelper.fileGetContent(this.path)直接把攻击者机器上的.class文件读成byte[],内容不做任何加工,因此使用者可以放入任意逻辑(内存马、回显、自定义命令执行等)。new JavassistHelper(bytecode)仅用于解析类名——javassistHelper.getClassName()取出该字节码里声明的真实类名,并通过context.put(ContextTag.CLASS_NAME_KEY, ...)写入GadgetContext。上游加载器(TemplatesImpl的_name、或 XSLT/BCEL 装载点)需要这个类名才能正确newInstance(),这一步是本 gadget 能被「即插即用」的关键。invoke里chain.doCreate(context)的返回值被丢弃——因为本类携带END标签,理论上没有内层对象;该调用仅为遵守Gadget接口的「由内向外」构建约定。
与 BytecodeConvert 的分工:BytecodeConvert 会对内层字节码做改类名、实现 AbstractTranslet 接口、插桩、混淆等加工;而本 gadget 不加工,原样返回,依赖使用者自行保证 .class 已满足目标加载点的接口要求(例如若配合 TemplatesImpl,字节码需已继承 AbstractTranslet)。正因如此它同时挂了 BytecodeConvertTag,可直接顶替转换器位置。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
path |
本地.class字节码文件路径 | 攻击者本地待读取的 .class 文件绝对/相对路径 |
无 | 任意路径字符串 |
- 从 description:「从文件中读取字节码,适用于自定义字节码场合,增加了工具拓展性」。
- 不依赖任何第三方库,只要 JVM 能加载该字节码即可;字节码本身的版本/接口约束由使用者负责。
- 常见坑:若目标加载点是
TemplatesImpl,自定义类必须继承com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet,否则newTransformer()阶段会抛异常——此时应改走 BytecodeConvert 让其自动补接口。
自由构件,未直接出现在 51 条预设链中。作为「自定义字节码」入口,供使用者在需要投递专属 payload 类时手动替换掉内置的 Exec/DNSLog sink。
- 同族(自定义字节码源):BytecodeFromUploadFile(改为从上传的 Base64 读取)。
- 上游加载器(承接
Bytecode/BytecodeConvertTag):BytecodeConvert、TemplatesImpl。 - 功能对位的内置 sink:
Exec、DNSLog 等(它们产出模板字节码,本 gadget 产出使用者自带字节码)。