Skip to content

Latest commit

 

History

History
50 lines (40 loc) · 3.57 KB

File metadata and controls

50 lines (40 loc) · 3.57 KB

将byte[]字节码转换为Js表达式字符串(JsConvert2)

  • 类别:common 别名:— 优先级:50
  • 作者:yzddmr6、小晨曦
  • 依赖8 <= jdk(description 标注「在 Rhino 下使用 theUnsafe 实现字节码加载」)

作用

把内层 gadget 产出的 byte[] 字节码,编码为一段 JavaScript 表达式字符串。与 JsConvert 同属「字节码 → JS 表达式」转换环,但字节码加载手法改用 sun.misc.Unsafe.defineClass(...)(而非 defineAnonymousClass),并固定使用 sun.misc.BASE64Decoder 解码,主打 Rhino 引擎兼容。

链接标签

  • 入口 tagsJs_ExprExpression —— 产物是可被 JS 引擎求值的表达式字符串。
  • 衔接 nextTagsBytecodeConvertTag —— 之后接产出原始 byte[] 字节码的转换环。
  • excludes:无。

源码剖析

public static String jsTemplate = "var s = '%s';var theUnsafeMethod = java.lang.Class.forName('sun.misc.Unsafe').getDeclaredField('theUnsafe');theUnsafeMethod.setAccessible(true);unsafe = theUnsafeMethod.get(null);var classBytes = java.lang.Class.forName('sun.misc.BASE64Decoder').newInstance().decodeBuffer(s);unsafe.defineClass(null, classBytes, 0, classBytes.length, null, null).newInstance();";

private String getObject(byte[] bytecode) {
    String bytecodeB64 = Base64.encodeBase64String((byte[])bytecode);
    return String.format(jsTemplate, bytecodeB64);
}

@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    return this.getObject((byte[])chain.doCreate(context));
}

逐段解释:

  • invokechain.doCreate(context) 取内层 byte[] 字节码,交由 getObject
  • getObjectBase64.encodeBase64String 编码字节码后填入 jsTemplate
  • 模板 JS 执行逻辑:反射取 sun.misc.Unsafe.theUnsafe 静态字段(setAccessible(true))得到 Unsafe 实例;用 sun.misc.BASE64Decoder.decodeBuffer(s) 把 Base64 字符串解回字节数组 classBytes
  • 关键点:调用 unsafe.defineClass(name, b, off, len, loader, protectionDomain) 的六参重载——这里 name=nullloader=nullprotectionDomain=null,即用系统上下文直接定义类,随后 newInstance() 触发恶意类初始化。
  • JsConvert 的差异:本类走 Unsafe.defineClass(该方法在 JDK 9 后逐步弱化/受限,但 description 声明 8 <= jdk 且面向 Rhino),且只用 BASE64Decoder(不含 java.util.Base64 回退分支)。

参数(@Param)

本类无 @Param。字节码内容由下游 nextTags=BytecodeConvertTag 的 gadget 决定。

适用版本与原理要点

  • 依赖 8 <= jdk,原理要点为「在 Rhino 下使用 theUnsafe 实现字节码加载」。Rhino 与 Nashorn 在语法细节(如反射调用、Class.forName 行为)上有差异,本模板针对 Rhino 环境编写。
  • Unsafe.defineClass 属于 Unsafe 系加载,绕过 ClassLoader 白名单;但该 API 在高版本 JDK 中被移除或限制,实战需结合目标 JDK 与引擎实际验证。
  • 由 yzddmr6、小晨曦贡献,是对 JsConvert 加载手法的变体补充。

所属预设链

自由构件,未直接出现在预设链(usedInChains 为空)。可在需要 JS 表达式载体的自定义链中替换 JsConvert 使用。

关联