From 60b7456cedc2d19db770660e620bef8ea41dfdfb Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 27 Jul 2024 19:17:47 -0500 Subject: [PATCH] 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