package gq.malwarefight.nosession; import gq.malwarefight.nosession.linux.bwrap.BubblewrapBuilder; import gq.malwarefight.nosession.linux.libc.Libc; import gq.malwarefight.nosession.relaunch.Relaunch; import gq.malwarefight.nosession.tweaks.initial.InitialTweaker; import gq.malwarefight.nosession.utils.Utils; import net.minecraft.launchwrapper.Launch; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import org.apache.commons.lang3.SystemUtils; import org.apache.logging.log4j.LogManager; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @SuppressWarnings("unused") @IFMLLoadingPlugin.MCVersion("1.8.9") @IFMLLoadingPlugin.Name("NoSession trolling") @IFMLLoadingPlugin.SortingIndex(0) public class NoSessionLoadingPlugin implements IFMLLoadingPlugin { @Override public String[] getASMTransformerClass() { return new String[0]; } @Override public String getModContainerClass() { return null; } @Override public String getSetupClass() { return null; } @Override public void injectData(Map map) { } @Override public String getAccessTransformerClass() { return null; } @SuppressWarnings("unchecked") public static void injectTweaker() { ArrayList tweakClassList = (ArrayList) Launch.blackboard.get("TweakClasses"); tweakClassList.add(0, InitialTweaker.class.getName()); } public static void addSelfToClassLoader() { Launch.classLoader.addURL(NoSessionLoadingPlugin.class.getProtectionDomain().getCodeSource().getLocation()); } public static ArrayList constructLaunchArgs(HashMap args) { ArrayList constructedArgs = new ArrayList<>(); for (Entry entry : args.entrySet()) { if (entry.getKey().equals("--accessToken")) { constructedArgs.add(entry.getKey()); constructedArgs.add(""); continue; } constructedArgs.add(entry.getKey()); constructedArgs.add(entry.getValue()); } return constructedArgs; } public static void relaunchProcess(Matcher m) throws Exception { RuntimeMXBean rmb = ManagementFactory.getRuntimeMXBean(); if (!SystemUtils.IS_OS_LINUX) { ArrayList args = new ArrayList<>(); args.add(Utils.getJavaExe()); args.add("-cp"); args.add(System.getProperty("java.class.path")); args.addAll(rmb.getInputArguments()); String newArgs = m.replaceAll("--accessToken "); args.addAll(Arrays.asList(newArgs.split(" "))); ProcessBuilder processBuilder = new ProcessBuilder( args.toArray(new String[0]) ).inheritIO(); try { processBuilder.start(); } catch (IOException e) { throw new RuntimeException(e); } } else { BubblewrapBuilder builder = new BubblewrapBuilder() .setCommand(Utils.getJavaExe()) .unshareAll() .shareNet() .setHostname("nosession-on-top") .readOnlyBind("/usr", "/usr") .mountTmpfs("/tmp") .mountTmpfs("/var") .mountProc("/proc") .mountDev("/dev") .readOnlyBind("/etc/resolv.conf", "/etc/resolv.conf") .addSymlink("usr/lib", "/lib") .addSymlink("usr/lib64", "/lib64") .addSymlink("usr/bin", "/bin") .addSymlink("usr/sbin", "/sbin") .createDir("/run/user/" + Libc.geteuid()) .setEnv("XDG_RUNTIME_DIR", "/run/user/" + Libc.geteuid()) .readOnlyBind(System.getProperty("java.home"), System.getProperty("java.home")) .bind(Launch.minecraftHome.getAbsolutePath(), Launch.minecraftHome.getAbsolutePath()) .bind(Launch.assetsDir.getAbsolutePath(), Launch.assetsDir.getAbsolutePath()) .readOnlyBind(Utils.getLibraryPathAsFile(NoSessionLoadingPlugin.class).getAbsolutePath(), Utils.getLibraryPathAsFile(NoSessionLoadingPlugin.class).getAbsolutePath()); if (System.getenv("XDG_SESSION_TYPE").equals("x11")) { LogManager.getLogger().warn("X11 detected, enabling X11 passthrough, which could allow keyloggers to work"); } builder.bind("/tmp/.X11-unix/X" + System.getenv("DISPLAY").substring(1), "/tmp/.X11-unix/X0") .setEnv("DISPLAY", ":0"); // add all the entries on the classpath read only String classPath = rmb.getClassPath(); for (String path : classPath.split(System.getProperty("path.separator"))) { File lib = new File(path); builder.readOnlyBind(lib.getAbsolutePath(), lib.getAbsolutePath()); } builder.addArgs("-cp", rmb.getClassPath(), "net.minecraft.launchwrapper.Launch"); // blackboard erases the type, but we are sure that launchArgs will always be a HashMap //noinspection unchecked builder.addArgs(constructLaunchArgs((HashMap) Launch.blackboard.get("launchArgs"))); builder.addArgs("--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker"); builder.build().start(); } Utils.shutdown(); } static { addSelfToClassLoader(); try { Pattern mcJWT = Pattern.compile("--accessToken +(?eyJhbGciOiJIUzI1NiJ9\\.[A-Za-z0-9-_]*\\.[A-Za-z0-9-_]*)"); Matcher m = mcJWT.matcher(System.getProperty("sun.java.command")); if (m.find()) { Utils.setToken(m.group("token")); relaunchProcess(m); } else { // test if we can find the token in Launch.blackboard.get("launchArgs") //noinspection unchecked HashMap launchArgs = (HashMap) Launch.blackboard.get("launchArgs"); Pattern pattern = Pattern.compile("(?ey[A-Za-z0-9-_]*\\.[A-Za-z0-9-_]*\\.[A-Za-z0-9-_]*)"); Matcher match = pattern.matcher(launchArgs.get("--accessToken")); if (match.find()) { Utils.setToken(match.group("token")); // relaunch now ! System.out.println("======================="); System.out.println("NoSession: relaunching without the token"); System.out.println("======================="); if (SystemUtils.IS_OS_LINUX) { relaunchProcess(m); } try { Relaunch.relaunch(constructLaunchArgs(launchArgs)); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } } injectTweaker(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } }