[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:
Zaxar163 2019-10-17 16:37:05 +02:00 committed by Gravit
parent d897a692f7
commit cd1a9718de
7 changed files with 138 additions and 34 deletions

View file

@ -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()

View file

@ -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);

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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));
}
}
} }

View file

@ -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);
}
}

View file

@ -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);
}
}