mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 09:01:08 +03:00
[FEATURE] Фикс ForgeSM через агент. (#342)
* [FEATURE] Фикс завершения работы через агент... Патчим класс форжового SM * [ANY] Обновлены модули. * [FIX] Возможность модулям определить, запущены ли они после старта клиента. * [FIX] Ошибка компиляции. * [FIX] Ещё 1 способ System.exit в обход SecurityManager. * [FIX] Фикс патча asm. * [FIX] FMLPatcher работает! * [ANY] Обновлены модули. * [FIX] Немного finalа... * [ANY] Обновлены модули. * [ANY] Обновлены модули
This commit is contained in:
parent
d897a692f7
commit
cd1a9718de
7 changed files with 138 additions and 34 deletions
|
@ -6,6 +6,8 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.patches.FMLPatcher;
|
||||||
|
import pro.gravit.launcher.utils.NativeJVMHalt;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -31,10 +33,8 @@ public static void premain(String agentArgument, Instrumentation instrumentation
|
||||||
System.out.println("Launcher Agent");
|
System.out.println("Launcher Agent");
|
||||||
checkAgentStacktrace();
|
checkAgentStacktrace();
|
||||||
inst = instrumentation;
|
inst = instrumentation;
|
||||||
//SafeExitJVMLegacy.class.getName();
|
NativeJVMHalt.initFunc();
|
||||||
//SafeExitJVM.class.getName();
|
FMLPatcher.apply();
|
||||||
//NativeJVMHalt.class.getName();
|
|
||||||
//NativeJVMHalt.initFunc();
|
|
||||||
isAgentStarted = true;
|
isAgentStarted = true;
|
||||||
}
|
}
|
||||||
public static void checkAgentStacktrace()
|
public static void checkAgentStacktrace()
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
|
||||||
public class LauncherEngine {
|
public class LauncherEngine {
|
||||||
|
public static final AtomicBoolean IS_CLIENT = new AtomicBoolean(false);
|
||||||
|
|
||||||
public static void main(String... args) throws Throwable {
|
public static void main(String... args) throws Throwable {
|
||||||
JVMHelper.checkStackTrace(LauncherEngine.class);
|
JVMHelper.checkStackTrace(LauncherEngine.class);
|
||||||
|
|
|
@ -442,13 +442,12 @@ public ClientLaunchContext(Params params, ClientProfile profile, HashedDir asset
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void main(String... args) throws Throwable {
|
public static void main(String... args) throws Throwable {
|
||||||
|
LauncherEngine.IS_CLIENT.set(true);
|
||||||
LauncherEngine engine = LauncherEngine.clientInstance();
|
LauncherEngine engine = LauncherEngine.clientInstance();
|
||||||
//Launcher.modulesManager = new ClientModuleManager(engine);
|
|
||||||
LauncherEngine.modulesManager = new ClientModuleManager();
|
LauncherEngine.modulesManager = new ClientModuleManager();
|
||||||
LauncherConfig.getAutogenConfig().initModules(); //INIT
|
LauncherConfig.getAutogenConfig().initModules(); //INIT
|
||||||
LauncherEngine.modulesManager.initModules(null);
|
LauncherEngine.modulesManager.initModules(null);
|
||||||
initGson(LauncherEngine.modulesManager);
|
initGson(LauncherEngine.modulesManager);
|
||||||
//Launcher.modulesManager.preInitModules();
|
|
||||||
if (!LauncherAgent.isStarted()) {
|
if (!LauncherAgent.isStarted()) {
|
||||||
NativeJVMHalt.haltA(100);
|
NativeJVMHalt.haltA(100);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -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<MethodHandle> 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, "<init>", "()V", null, null);
|
||||||
|
methodVisitor.visitCode();
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
|
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
package pro.gravit.launcher.utils;
|
package pro.gravit.launcher.utils;
|
||||||
|
|
||||||
import cpw.mods.fml.SafeExitJVMLegacy;
|
import java.awt.event.WindowEvent;
|
||||||
import net.minecraftforge.fml.SafeExitJVM;
|
|
||||||
|
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 final class NativeJVMHalt {
|
||||||
public NativeJVMHalt(int haltCode) {
|
public NativeJVMHalt(int haltCode) {
|
||||||
|
@ -21,19 +26,34 @@ private boolean aaabBooleanC_D() {
|
||||||
public static void haltA(int code) {
|
public static void haltA(int code) {
|
||||||
NativeJVMHalt halt = new NativeJVMHalt(code);
|
NativeJVMHalt halt = new NativeJVMHalt(code);
|
||||||
try {
|
try {
|
||||||
SafeExitJVMLegacy.exit(code);
|
JVMHelper.RUNTIME.exit(code);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
try {
|
||||||
|
new WindowShutdown();
|
||||||
|
} catch (Throwable ignored1) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SafeExitJVM.exit(code);
|
FMLPatcher.exit(code);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) { }
|
||||||
}
|
|
||||||
halt.aaabbb38C_D();
|
halt.aaabbb38C_D();
|
||||||
boolean a = halt.aaabBooleanC_D();
|
boolean a = halt.aaabBooleanC_D();
|
||||||
System.out.println(a);
|
System.out.println(a);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean initFunc() {
|
public static boolean initFunc() {
|
||||||
return true;
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue