diff options
Diffstat (limited to 'src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java')
-rw-r--r-- | src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java b/src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java new file mode 100644 index 0000000..51425fc --- /dev/null +++ b/src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java @@ -0,0 +1,209 @@ +package gq.malwarefight.nosession.mixin; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ForwardingMultimap; +import com.google.gson.Gson; +import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +import net.minecraft.launchwrapper.ITweaker; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraft.launchwrapper.LogWrapper; +import org.apache.commons.io.ByteOrderMark; +import org.apache.commons.lang3.CharEncoding; +import org.apache.commons.lang3.Validate; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.mixin.MixinEnvironment; +import org.spongepowered.asm.mixin.Mixins; + +import java.io.File; +import java.io.IOException; +import java.net.Socket; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +@SuppressWarnings({"unused", "unchecked"}) +public class InitialTweaker implements ITweaker { + + // I'm creating my own allTweakers list + // with blackjack and hookers! + public final ArrayList<ITweaker> allTweakers = new ArrayList<>(); + + public InitialTweaker() {} + + public String getLibraryPath(Class<?> c) throws URISyntaxException { + return new File(c.getProtectionDomain().getCodeSource().getLocation().toURI()).getAbsolutePath(); + } + + public String getClasspath() throws URISyntaxException { + return String.join( + System.getProperty("path.separator"), + getLibraryPath(InitialTweaker.class), + getLibraryPath(YggdrasilAuthenticationService.class), + getLibraryPath(Gson.class), + getLibraryPath(LogManager.class), + getLibraryPath(Validate.class), + getLibraryPath(ForwardingMultimap.class), + getLibraryPath(Beta.class), + getLibraryPath(CharEncoding.class), + getLibraryPath(ByteOrderMark.class), + getLibraryPath(Logger.class), + getLibraryPath(Opcodes.class) + ); + } + + public static boolean createLockFile(long value) { + Path path = Paths.get(System.getProperty("java.io.tmpdir"), "NoSessionLock" + value); + try { + Files.createFile(path); + } catch (FileAlreadyExistsException e) { + System.out.println("You won the lottery! Two NoSession instances used the same ID. The chance that a new NoSession instance uses the same ID as an old one is (NoSession instances) / 2^64"); + return false; + } catch (IOException e) { + LogManager.getLogger().warn("Failed to create lockfile " + e.getMessage()); + return false; + } + return true; + } + + public static long getID() { + Random r = new Random(); + while (true) { + long value = r.nextLong(); + if (createLockFile(value)) { + Runtime.getRuntime().addShutdownHook( + new Thread(() -> { + try { + Files.delete(Paths.get(System.getProperty("java.io.tmpdir"), "NoSessionLock" + value)); + } catch (Exception ignored) {} + }) + ); + return value; + } + } + } + + public void setToken(String token) throws IOException, URISyntaxException { + long value = getID(); + Utils.ID = value; + File javaExecutable = Paths.get(System.getProperty("java.home"), "bin", "java").toFile(); + ProcessBuilder processBuilder = new ProcessBuilder( + javaExecutable.getAbsolutePath(), "-cp", getClasspath(), "gq.malwarefight.tokenapp.Main", Long.toString(value) + ); + processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT).redirectError(ProcessBuilder.Redirect.INHERIT); + Process c = processBuilder.start(); + c.getOutputStream().write((token + "\n").getBytes(StandardCharsets.UTF_8)); + c.getOutputStream().flush(); + Runtime.getRuntime().addShutdownHook( + new Thread(() -> { + try { + Socket socket = Utils.getProperSocket(); + socket.getOutputStream().write("fullquit\n".getBytes(StandardCharsets.UTF_8)); + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }) + ); + } + + /** + * This handles the launch arguments passed towards minecraft + * @param args The launch arguments + * @param gameDir The game directory (ie: .minecraft) + * @param assetsDir The assets directory + * @param profile The game profile + */ + @Override + @SuppressWarnings("unchecked") + public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) { + ArrayList<String> argsCopy = new ArrayList<>(args); + for (int i = 0; i < argsCopy.size(); i++) { + if (argsCopy.get(i).equals("--accessToken")) { + try { + setToken(args.get(i + 1)); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + argsCopy.set(i + 1, "<noSessionAccessToken>"); + } + } + boolean any = false; + // in order to prevent other mods from seeing the true list of args with the token + // we will just call all the other tweakers from here + ArrayList<ITweaker> tweakers = (ArrayList<ITweaker>) Launch.blackboard.get("Tweaks"); + for (final ITweaker tweaker : tweakers) { + if (tweaker == this) + continue; + + LogWrapper.log(Level.INFO, "Calling tweak class %s", tweaker.getClass().getName()); + tweaker.acceptOptions(argsCopy, gameDir, assetsDir, profile); + tweaker.injectIntoClassLoader(Launch.classLoader); + allTweakers.add(tweaker); + tweakers.set(tweakers.indexOf(tweaker), new BlankTweaker()); + any = true; + } + if (any) { + ((ArrayList<String>) Launch.blackboard.get("TweakClasses")).add(0, + Utils.getUniqueClassName() + ); + } + } + + /** + * Inject into the MC class loader + * @param classLoader The class loader + */ + @Override + public final void injectIntoClassLoader(LaunchClassLoader classLoader) { + MixinBootstrap.init(); + MixinEnvironment environment = MixinEnvironment.getDefaultEnvironment(); + Mixins.addConfiguration("mixins.nosession.json"); + // Check if the obfuscation context is null + if (environment.getObfuscationContext() == null) { + environment.setObfuscationContext("notch"); + } + // This is a client side, client :) + environment.setSide(MixinEnvironment.Side.CLIENT); + } + + @Override + public String getLaunchTarget() { + return MixinBootstrap.getPlatform().getLaunchTarget(); + } + + @Override + public String[] getLaunchArguments() { + + ArrayList<String> argsFromOurTweakers = new ArrayList<>(); + + for (ITweaker i: allTweakers) { + argsFromOurTweakers.addAll(Arrays.asList(i.getLaunchArguments())); + } + + //noinspection unchecked + ArrayList<String> launchArgs = (ArrayList<String>) Launch.blackboard.get("ArgumentList"); + for (int i = 0; i < launchArgs.size(); i++) { + if (launchArgs.get(i).equals("--accessToken")) { + launchArgs.set(i + 1, "<noSessionAccessToken>"); + } + } + if (!launchArgs.contains("--accessToken")) { + argsFromOurTweakers.add("--accessToken"); + argsFromOurTweakers.add("<noSessionAccessToken>"); + } + + return argsFromOurTweakers.toArray(new String[0]); + } +} |