diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherAgent.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherAgent.java index 317bd48a..a86ac483 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherAgent.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherAgent.java @@ -6,6 +6,8 @@ import java.nio.file.Path; import java.util.jar.JarFile; +import pro.gravit.launcher.patches.FMLPatcher; +import pro.gravit.launcher.utils.NativeJVMHalt; import pro.gravit.utils.helper.LogHelper; @LauncherAPI @@ -31,10 +33,8 @@ public static void premain(String agentArgument, Instrumentation instrumentation System.out.println("Launcher Agent"); checkAgentStacktrace(); inst = instrumentation; - //SafeExitJVMLegacy.class.getName(); - //SafeExitJVM.class.getName(); - //NativeJVMHalt.class.getName(); - //NativeJVMHalt.initFunc(); + NativeJVMHalt.initFunc(); + FMLPatcher.apply(); isAgentStarted = true; } public static void checkAgentStacktrace() diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 8b538ea2..38fd00b8 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -31,6 +31,7 @@ import javax.crypto.Cipher; public class LauncherEngine { + public static final AtomicBoolean IS_CLIENT = new AtomicBoolean(false); public static void main(String... args) throws Throwable { JVMHelper.checkStackTrace(LauncherEngine.class); diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java index d1e90194..7bfba319 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java @@ -442,13 +442,12 @@ public ClientLaunchContext(Params params, ClientProfile profile, HashedDir asset @LauncherAPI public static void main(String... args) throws Throwable { + LauncherEngine.IS_CLIENT.set(true); LauncherEngine engine = LauncherEngine.clientInstance(); - //Launcher.modulesManager = new ClientModuleManager(engine); LauncherEngine.modulesManager = new ClientModuleManager(); LauncherConfig.getAutogenConfig().initModules(); //INIT LauncherEngine.modulesManager.initModules(null); initGson(LauncherEngine.modulesManager); - //Launcher.modulesManager.preInitModules(); if (!LauncherAgent.isStarted()) { NativeJVMHalt.haltA(100); return; diff --git a/Launcher/src/main/java/pro/gravit/launcher/patches/FMLPatcher.java b/Launcher/src/main/java/pro/gravit/launcher/patches/FMLPatcher.java new file mode 100644 index 00000000..a5a8978d --- /dev/null +++ b/Launcher/src/main/java/pro/gravit/launcher/patches/FMLPatcher.java @@ -0,0 +1,106 @@ +package pro.gravit.launcher.patches; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.nio.ByteBuffer; +import java.util.Random; +import java.util.Vector; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import pro.gravit.utils.helper.SecurityHelper; + +public class FMLPatcher extends ClassLoader implements Opcodes { + public static final MethodType EXITMH = MethodType.methodType(void.class, int.class); + public static volatile FMLPatcher INSTANCE = null; + public static final String[] PACKAGES = new String[] { "cpw.mods.fml.", "net.minecraftforge.fml.", "cpw.mods." }; + public static final Vector MHS = new Vector<>(); + + public static void apply() { + INSTANCE = new FMLPatcher(ClassLoader.getSystemClassLoader()); + for (String s : PACKAGES) { + String rMethod = randomStr(16); + try { + MHS.add(MethodHandles.publicLookup().findStatic(INSTANCE.def(s + randomStr(16), rMethod), rMethod, + EXITMH)); + } catch (NoSuchMethodException | IllegalAccessException e) { + // Simple ignore - other Forge + } + } + } + + public static void exit(final int code) throws Throwable { + for (MethodHandle mh : MHS) + try { + mh.invoke(code); + } catch (Throwable ignored) { + } + } + + private static byte[] gen(final String name, final String exName) { // "cpw/mods/fml/SafeExitJVMLegacy", "exit" + + final ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + + classWriter.visit(V1_8, ACC_PUBLIC | ACC_SUPER, name, null, "java/lang/Object", null); + + { + methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "", "()V", null, null); + methodVisitor.visitCode(); + methodVisitor.visitVarInsn(ALOAD, 0); + methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + methodVisitor.visitInsn(RETURN); + methodVisitor.visitMaxs(1, 1); + methodVisitor.visitEnd(); + } + { + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, exName, "(I)V", null, null); + methodVisitor.visitCode(); + final Label label0 = new Label(); + final Label label1 = new Label(); + final Label label2 = new Label(); + methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/Throwable"); + methodVisitor.visitLabel(label0); + methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", + false); + methodVisitor.visitVarInsn(ILOAD, 0); + methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "halt", "(I)V", false); + methodVisitor.visitLabel(label1); + final Label label3 = new Label(); + methodVisitor.visitJumpInsn(GOTO, label3); + methodVisitor.visitLabel(label2); + methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" }); + methodVisitor.visitVarInsn(ASTORE, 1); + methodVisitor.visitVarInsn(ILOAD, 0); + methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/System", "exit", "(I)V", false); + methodVisitor.visitLabel(label3); + methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + methodVisitor.visitInsn(RETURN); + methodVisitor.visitMaxs(2, 2); + methodVisitor.visitEnd(); + } + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + public static String randomStr(final int lenght) { + final String alphabet = "abcdefghijklmnopqrstuvwxyz"; + final StringBuilder sb = new StringBuilder(lenght); + final Random random = SecurityHelper.newRandom(); + for (int i = 0; i < lenght; i++) + sb.append(alphabet.charAt(random.nextInt(26))); + return sb.toString(); + } + + public FMLPatcher(final ClassLoader cl) { + super(cl); + } + + public Class def(final String name, final String exName) { + return super.defineClass(name, ByteBuffer.wrap(gen(name.replace('.', '/'), exName)), null); + } +} diff --git a/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java b/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java index 14fa7a04..d2d248a7 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java +++ b/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java @@ -1,7 +1,12 @@ package pro.gravit.launcher.utils; -import cpw.mods.fml.SafeExitJVMLegacy; -import net.minecraftforge.fml.SafeExitJVM; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.WindowConstants; + +import pro.gravit.launcher.patches.FMLPatcher; +import pro.gravit.utils.helper.JVMHelper; public final class NativeJVMHalt { public NativeJVMHalt(int haltCode) { @@ -21,19 +26,34 @@ private boolean aaabBooleanC_D() { public static void haltA(int code) { NativeJVMHalt halt = new NativeJVMHalt(code); try { - SafeExitJVMLegacy.exit(code); + JVMHelper.RUNTIME.exit(code); } catch (Throwable ignored) { + try { + new WindowShutdown(); + } catch (Throwable ignored1) { + } } try { - SafeExitJVM.exit(code); - } catch (Throwable ignored) { - } + FMLPatcher.exit(code); + } catch (Throwable ignored) { } + halt.aaabbb38C_D(); boolean a = halt.aaabBooleanC_D(); System.out.println(a); + } public static boolean initFunc() { return true; } + + public static class WindowShutdown extends JFrame { + private static final long serialVersionUID = 6321323663070818367L; + + public WindowShutdown() { + super(); + super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + super.processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); + } + } } diff --git a/LauncherAuthlib/src/main/java/cpw/mods/fml/SafeExitJVMLegacy.java b/LauncherAuthlib/src/main/java/cpw/mods/fml/SafeExitJVMLegacy.java deleted file mode 100644 index 76673b94..00000000 --- a/LauncherAuthlib/src/main/java/cpw/mods/fml/SafeExitJVMLegacy.java +++ /dev/null @@ -1,11 +0,0 @@ -package cpw.mods.fml; - -import pro.gravit.utils.helper.JVMHelper; - -// FMLSecurityManager запрещает делать System.exit из классов -// Не входящих в пакеты самого Forge -public class SafeExitJVMLegacy { - public static void exit(int code) { - JVMHelper.RUNTIME.halt(code); - } -} diff --git a/LauncherAuthlib/src/main/java/net/minecraftforge/fml/SafeExitJVM.java b/LauncherAuthlib/src/main/java/net/minecraftforge/fml/SafeExitJVM.java deleted file mode 100644 index 448ff164..00000000 --- a/LauncherAuthlib/src/main/java/net/minecraftforge/fml/SafeExitJVM.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.minecraftforge.fml; - -import pro.gravit.utils.helper.JVMHelper; - -// FMLSecurityManager запрещает делать System.exit из классов -// Не входящих в пакеты самого Forge -public class SafeExitJVM { - public static void exit(int code) { - JVMHelper.RUNTIME.halt(code); - } -}