- 类别:bytecode 别名:— 优先级:200
- 作者:Ar3h
- 依赖:
org.apache.shiro:shiro-lang(仅借其Base64工具解码,无额外运行时依赖)
与 BytecodeFromLocalFile 同源,区别在于字节码来源改为 UI 上传的文件(以 Base64 字符串承载):把上传内容 Base64 解码为原始 .class 字节,作为链尾字节码源交给上游加载器(如 TemplatesImpl)去 defineClass 并实例化。用于投递完全自定义的恶意类。
- 入口
tags:Bytecode—— 声明本 gadget 产出原始字节码byte[],可被nextTags=Bytecode的加载器(BytecodeConvert)承接。BytecodeConvertTag—— 同时占据「字节码转换器」槽位,可被nextTags=BytecodeConvertTag的加载点直接承接,省去中间转换环节。END—— 链终止标签,本 gadget 是最内层 sink。
- 衔接
nextTags:空 —— 自身即字节码源头,不再向内包裹。 excludes:无。
@Param(name=".class bytecode file", type=ParamType.File)
public String base64String;
public byte[] getObject(GadgetContext context) throws Exception {
byte[] bytecode = Base64.decode(this.base64String); // 上传内容按 Base64 解码
JavassistHelper javassistHelper = new JavassistHelper(bytecode);
context.put(ContextTag.CLASS_NAME_KEY, javassistHelper.getClassName()); // 解析并登记类名
return javassistHelper.getBytecode(); // 返回字节码
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
chain.doCreate(context); // 遵守接口约定;本类为 END,内层通常为空
return this.getObject(context);
}关键点:
@Param标注type=ParamType.File,因此在 UI 上呈现为文件上传控件;上传的二进制被框架转成 Base64 字符串填入base64String。Base64.decode(this.base64String)使用的是org.apache.shiro.lang.codec.Base64(工具内已引入 Shiro),把字符串还原为原始.class字节,不做任何加工。- 与 BytecodeFromLocalFile 完全一致地,用
new JavassistHelper(bytecode)仅为提取类名并context.put(ContextTag.CLASS_NAME_KEY, ...),供上游加载器newInstance()时定位类。 - 同样携带
BytecodeConvertTag,可直接顶替 BytecodeConvert 的位置;但也因此不会自动补AbstractTranslet等接口,需使用者自行保证上传的类满足目标加载点要求。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
base64String |
.class bytecode file | 上传的 .class 文件内容(框架以 Base64 字符串传入),ParamType.File |
无 | 上传的字节码文件 |
- 唯一区别于本地文件版:源自远程/浏览器上传,适合无法直接访问攻击者磁盘、或在 Web 前端操作的场景。
- 不依赖任何反序列化库;字节码接口/版本约束由使用者保证。
- 若目标加载点是
TemplatesImpl,上传类需已继承AbstractTranslet,否则应改用 BytecodeConvert 自动补接口。
自由构件,未直接出现在 51 条预设链中。作为「自定义字节码」入口,供使用者手动替换内置 sink。
- 同族:BytecodeFromLocalFile(改从本地路径读取)。
- 上游加载器:BytecodeConvert、
TemplatesImpl。 - 功能对位的内置 sink:
Exec、DNSLog 等。