From c459689e385d9d79345422b02374bf8f913a05b1 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Tue, 23 Jul 2024 14:27:06 -0500 Subject: [PATCH 1/2] more docs update --- README.md | 3 +++ docs/Bytecode Manipulation.md | 1 + 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 8d5df588..673b6c01 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,9 @@ shadeDowngradedApi { The tasks have all the same flags as the extension, so you can change them separately, their default value is to use the global one from the extension. +If you are merging multiple downgraded jars, please merge from the downgradeJar tasks, and then shade on the resulting mono-jar. +otherwise some API stubs may be missing, due to how shade only includes what is used. + Optionally, you can also depend on the shadeDowngradedApi task when running build. ```gradle diff --git a/docs/Bytecode Manipulation.md b/docs/Bytecode Manipulation.md index d1ece635..3f052c82 100644 --- a/docs/Bytecode Manipulation.md +++ b/docs/Bytecode Manipulation.md @@ -38,6 +38,7 @@ Stubs have several other fields that change their behavior: mostly for things like reflection and runtime class definition. * `noSpecial` indicates that the stub should not be used for `INVOKESPECIAL` calls. * `downgradeVersion` adds an extra argument to the stub for the original version of the class, this is useful for multi-version stubs, such as reflection. +* `excludeChild` prevent a stub from being applied to a child-class of the target. for example, `String#isEmpty` is since java 6, but `CharSequence#isEmpty` is since java 15. ### Modify From 60b7456cedc2d19db770660e620bef8ea41dfdfb Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 27 Jul 2024 19:17:47 -0500 Subject: [PATCH 2/2] add classloader name stubs --- .../downgradetest/TestClassloader.java | 27 ++++++ .../j9/stub/java_base/J_L_ClassLoader.java | 47 +++++++++- .../j9/stub/java_base/J_N_URLClassLoader.java | 93 +++++++++++++++++++ .../jvmdg/providers/Java9Downgrader.java | 1 + 4 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 downgradetest/src/main/java/xyz/wagyourtail/downgradetest/TestClassloader.java create mode 100644 java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_N_URLClassLoader.java diff --git a/downgradetest/src/main/java/xyz/wagyourtail/downgradetest/TestClassloader.java b/downgradetest/src/main/java/xyz/wagyourtail/downgradetest/TestClassloader.java new file mode 100644 index 00000000..9a1104fc --- /dev/null +++ b/downgradetest/src/main/java/xyz/wagyourtail/downgradetest/TestClassloader.java @@ -0,0 +1,27 @@ +package xyz.wagyourtail.downgradetest; + +import java.net.URLClassLoader; + +public class TestClassloader { + + public static void main(String[] args) { + URLClassLoader cl = new URLClassLoader("name1", new java.net.URL[0], TestClassloader.class.getClassLoader()); + System.out.println(cl.getName()); + + URLClassLoader cl2 = new URLClassLoader("name2", new java.net.URL[0], TestClassloader.class.getClassLoader(), null); + System.out.println(cl2.getName()); + + CLExt cl3 = new CLExt(TestClassloader.class.getClassLoader()); + System.out.println(cl3.getName()); + + } + + private static class CLExt extends ClassLoader { + + public CLExt(ClassLoader parent) { + super("name3", parent); + } + + } + +} diff --git a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_ClassLoader.java b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_ClassLoader.java index 692c3ec8..81ac24d4 100644 --- a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_ClassLoader.java +++ b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_ClassLoader.java @@ -1,17 +1,60 @@ package xyz.wagyourtail.jvmdg.j9.stub.java_base; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; import xyz.wagyourtail.jvmdg.version.Stub; +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; + public class J_L_ClassLoader { + private static final Map nameMap = Collections.synchronizedMap(new WeakHashMap<>()); + + @Modify(ref = @Ref(value = "Ljava/lang/ClassLoader;", member = "", desc = "(Ljava/lang/String;Ljava/lang/ClassLoader;)V")) + public static void init(MethodNode mnode, int i) { + MethodInsnNode node = (MethodInsnNode) mnode.instructions.get(i); + InsnList list = new InsnList(); + // stack: ClassLoader (U), String, ClassLoader + list.add(new InsnNode(Opcodes.SWAP)); + // stack: ClassLoader (U), ClassLoader, String + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: String, ClassLoader (U), ClassLoader, String + list.add(new InsnNode(Opcodes.POP)); + // stack: String, ClassLoader (U), ClassLoader + list.add(new InsnNode(Opcodes.DUP2)); + // stack: String, ClassLoader (U), ClassLoader, ClassLoader (U), ClassLoader + // init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/ClassLoader", "", "(Ljava/lang/ClassLoader;)V", false)); + // stack: String, ClassLoader, ClassLoader + list.add(new InsnNode(Opcodes.POP)); + // stack: String, ClassLoader + // call setName + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(J_L_ClassLoader.class), "setClassloaderName", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", false)); + // stack: - // TODO: stub init's... + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); + } + + public static void setClassloaderName(String name, ClassLoader classLoader) { + if (name != null && name.isEmpty()) { + throw new IllegalArgumentException("name must be non-empty or null"); + } + nameMap.put(classLoader, name); + } @Stub public static String getName(ClassLoader classLoader) { // TODO: check if subclass actually overrides this method - return null; + return nameMap.get(classLoader); } @Stub diff --git a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_N_URLClassLoader.java b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_N_URLClassLoader.java new file mode 100644 index 00000000..206aa921 --- /dev/null +++ b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_N_URLClassLoader.java @@ -0,0 +1,93 @@ +package xyz.wagyourtail.jvmdg.j9.stub.java_base; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; +import xyz.wagyourtail.jvmdg.version.Modify; +import xyz.wagyourtail.jvmdg.version.Ref; + +public class J_N_URLClassLoader { + + @Modify(ref = @Ref(value = "java/net/URLClassLoader", member = "", desc = "(Ljava/lang/String;[Ljava/net/URL;Ljava/lang/ClassLoader;)V")) + public static void init1(MethodNode mnode, int i) { + MethodInsnNode node = (MethodInsnNode) mnode.instructions.get(i); + InsnList list = new InsnList(); + // stack: URLClassLoader (U), String, URL[], ClassLoader + list.add(new InsnNode(Opcodes.DUP2_X1)); + // stack: URLClassLoader (U), URL[], ClassLoader, String, URL[], ClassLoader + list.add(new InsnNode(Opcodes.POP2)); + // stack: URLClassLoader (U), URL[], ClassLoader, String + list.add(new InsnNode(Opcodes.DUP2_X2)); + // stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, String + list.add(new InsnNode(Opcodes.POP)); + // stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader + list.add(new InsnNode(Opcodes.DUP2_X1)); + // stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U), URL[], ClassLoader + list.add(new InsnNode(Opcodes.POP2)); + // stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U) + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U) + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U) + list.add(new InsnNode(Opcodes.POP)); + // stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader + // init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/net/URLClassLoader", "", "([Ljava/net/URL;Ljava/lang/ClassLoader;)V", false)); + // stack: ClassLoader, String, URLClassLoader + // call setName + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(J_L_ClassLoader.class), "setClassloaderName", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", false)); + // stack: ClassLoader + list.add(new InsnNode(Opcodes.POP)); + // stack: + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); + } + + @Modify(ref = @Ref(value = "java/net/URLClassLoader", member = "", desc = "(Ljava/lang/String;[Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/net/URLStreamHandlerFactory;)V")) + public static void init2(MethodNode mnode, int i) { + MethodInsnNode node = (MethodInsnNode) mnode.instructions.get(i); + InsnList list = new InsnList(); + // stack: URLClassLoader (U), String, URL[], ClassLoader, URLStreamHandlerFactory + + int var = mnode.maxLocals++; + list.add(new VarInsnNode(Opcodes.ASTORE, var)); + + // stack: URLClassLoader (U), String, URL[], ClassLoader + list.add(new InsnNode(Opcodes.DUP2_X1)); + // stack: URLClassLoader (U), URL[], ClassLoader, String, URL[], ClassLoader + list.add(new InsnNode(Opcodes.POP2)); + // stack: URLClassLoader (U), URL[], ClassLoader, String + list.add(new InsnNode(Opcodes.DUP2_X2)); + // stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, String + list.add(new InsnNode(Opcodes.POP)); + // stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader + list.add(new InsnNode(Opcodes.DUP2_X1)); + // stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U), URL[], ClassLoader + list.add(new InsnNode(Opcodes.POP2)); + // stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U) + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U) + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U) + list.add(new InsnNode(Opcodes.POP)); + // stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader + list.add(new VarInsnNode(Opcodes.ALOAD, var)); + // stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader, URLStreamHandlerFactory + // init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/net/URLClassLoader", "", "([Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/net/URLStreamHandlerFactory;)V", false)); + // stack: ClassLoader, String, URLClassLoader + // call setName + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(J_L_ClassLoader.class), "setClassloaderName", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", false)); + // stack: ClassLoader + list.add(new InsnNode(Opcodes.POP)); + // stack: + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); + } +} diff --git a/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java9Downgrader.java b/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java9Downgrader.java index 478f8a4b..0b51cdfe 100644 --- a/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java9Downgrader.java +++ b/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java9Downgrader.java @@ -106,6 +106,7 @@ public void init() { // URLStreamHandlerProvider stub(J_N_Buffer.class); stub(J_N_F_Path.class); + stub(J_N_URLClassLoader.class); // AuthProvider // DrbgParameters // KeyStore