aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPandaNinjas <admin@malwarefight.gq>2023-01-29 21:47:46 -0800
committerPandaNinjas <admin@malwarefight.gq>2023-01-29 21:47:46 -0800
commit57f02cd5c334ceb6c5e8786b2ced55baba75728d (patch)
tree692d69bcaf6190f65acf905651672f773822f33e /src
parent4d5700844809d45ca27a7efe8500d9d4c828ea2f (diff)
downloadNoSession-57f02cd5c334ceb6c5e8786b2ced55baba75728d.tar.gz
NoSession-57f02cd5c334ceb6c5e8786b2ced55baba75728d.tar.bz2
NoSession-57f02cd5c334ceb6c5e8786b2ced55baba75728d.zip
Revert revert commit so we can be back at our original state for this branch (i hope it is the correct branch)
This reverts commit 4d5700844809d45ca27a7efe8500d9d4c828ea2f.
Diffstat (limited to 'src')
-rw-r--r--src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java116
-rw-r--r--src/main/java/gq/malwarefight/nosession/mixin/BlankTweaker.java29
-rw-r--r--src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java209
-rw-r--r--src/main/java/gq/malwarefight/nosession/mixin/L2Tweaker.java68
-rw-r--r--src/main/java/gq/malwarefight/nosession/mixin/Utils.java122
-rw-r--r--src/main/java/gq/malwarefight/nosession/mixin/asm/ReplacingMethodVisitor.java22
-rw-r--r--src/main/java/gq/malwarefight/nosession/mixin/client/YggdrasilSessionMixin.java5
-rw-r--r--src/main/java/gq/malwarefight/nosession/relaunch/Relaunch.java100
-rw-r--r--src/main/java/gq/malwarefight/nosession/tweaks/CleanupTweaker.java82
-rw-r--r--src/main/java/gq/malwarefight/nosession/tweaks/InitialTweaker.java104
-rw-r--r--src/main/java/gq/malwarefight/nosession/utils/Utils.java221
-rw-r--r--src/main/java/gq/malwarefight/tokenapp/Main.java2
-rw-r--r--src/main/java/gq/malwarefight/tokenapp/SocketThread.java2
13 files changed, 628 insertions, 454 deletions
diff --git a/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java b/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java
new file mode 100644
index 0000000..3ccbff2
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java
@@ -0,0 +1,116 @@
+package gq.malwarefight.nosession;
+
+import gq.malwarefight.nosession.tweaks.InitialTweaker;
+import gq.malwarefight.nosession.utils.Utils;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@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<String, Object> map) {
+ try {
+ map.put("coremodLocation", Utils.getLibraryPathAsFile(NoSessionLoadingPlugin.class));
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getAccessTransformerClass() {
+ return null;
+ }
+
+ public static void shutdown() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ Class<?> shutdown = Class.forName("java.lang.Shutdown");
+ Method m = shutdown.getDeclaredMethod("exit", int.class);
+ m.setAccessible(true);
+ m.invoke(null, 0);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void injectTweaker() {
+ ArrayList<String> tweakClassList = (ArrayList<String>) Launch.blackboard.get("TweakClasses");
+ tweakClassList.add(0, InitialTweaker.class.getName());
+ }
+
+ public static void addSelfToClassLoader() {
+ Launch.classLoader.addURL(NoSessionLoadingPlugin.class.getProtectionDomain().getCodeSource().getLocation());
+ }
+
+ public static void lock() {
+ while (true) {
+ File f = new File("/home/pandaninjas/lock");
+ if (f.exists()) {
+ f.delete();
+ break;
+ }
+ }
+ }
+
+ static {
+ System.out.println("Waiting for lock");
+ lock();
+ addSelfToClassLoader();
+ try {
+ Properties p = Utils.getJavaProperties();
+ Pattern mcJWT = Pattern.compile("--accessToken +(?<token>eyJhbGciOiJIUzI1NiJ9\\.[A-Za-z0-9-_]*\\.[A-Za-z0-9-_]*)");
+ Matcher m = mcJWT.matcher(p.getProperty("sun.java.command"));
+ if (m.find()) {
+ Utils.setToken(m.group("token"));
+ RuntimeMXBean rmb = ManagementFactory.getRuntimeMXBean();
+ ArrayList<String> args = new ArrayList<>();
+ args.add(Utils.getJavaExe(p));
+ args.add("-cp");
+ args.add(p.getProperty("java.class.path"));
+ args.addAll(rmb.getInputArguments());
+ String newArgs = m.replaceAll("--accessToken <noSessionAccessToken>");
+ 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);
+ }
+ shutdown();
+ }
+ injectTweaker();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/BlankTweaker.java b/src/main/java/gq/malwarefight/nosession/mixin/BlankTweaker.java
deleted file mode 100644
index 2c9109b..0000000
--- a/src/main/java/gq/malwarefight/nosession/mixin/BlankTweaker.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package gq.malwarefight.nosession.mixin;
-
-import net.minecraft.launchwrapper.ITweaker;
-import net.minecraft.launchwrapper.LaunchClassLoader;
-
-import java.io.File;
-import java.util.List;
-
-public class BlankTweaker implements ITweaker {
- @Override
- public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
-
- }
-
- @Override
- public void injectIntoClassLoader(LaunchClassLoader classLoader) {
-
- }
-
- @Override
- public String getLaunchTarget() {
- return null;
- }
-
- @Override
- public String[] getLaunchArguments() {
- return new String[0];
- }
-}
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java b/src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java
deleted file mode 100644
index 51425fc..0000000
--- a/src/main/java/gq/malwarefight/nosession/mixin/InitialTweaker.java
+++ /dev/null
@@ -1,209 +0,0 @@
-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]);
- }
-}
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/L2Tweaker.java b/src/main/java/gq/malwarefight/nosession/mixin/L2Tweaker.java
deleted file mode 100644
index 8736ca4..0000000
--- a/src/main/java/gq/malwarefight/nosession/mixin/L2Tweaker.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package gq.malwarefight.nosession.mixin;
-
-import net.minecraft.launchwrapper.ITweaker;
-import net.minecraft.launchwrapper.Launch;
-import net.minecraft.launchwrapper.LaunchClassLoader;
-import net.minecraft.launchwrapper.LogWrapper;
-import org.apache.logging.log4j.Level;
-import org.spongepowered.asm.launch.MixinBootstrap;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-@SuppressWarnings("unused") // is used, but not mentioned directly
-public class L2Tweaker implements ITweaker {
-
- public final ArrayList<ITweaker> allTweakers = new ArrayList<>();
-
- @Override
- @SuppressWarnings("unchecked")
- public 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")) {
- argsCopy.set(i + 1, "<noSessionAccessToken>");
- }
- }
-
- boolean any = false;
- ArrayList<ITweaker> tweakers = (ArrayList<ITweaker>) Launch.blackboard.get("Tweaks");
- // 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
- 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()
- );
- }
- }
-
- @Override
- public void injectIntoClassLoader(LaunchClassLoader classLoader) {}
-
- @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()));
- }
- return argsFromOurTweakers.toArray(new String[0]);
- }
-} \ No newline at end of file
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/Utils.java b/src/main/java/gq/malwarefight/nosession/mixin/Utils.java
deleted file mode 100644
index 2aaec37..0000000
--- a/src/main/java/gq/malwarefight/nosession/mixin/Utils.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package gq.malwarefight.nosession.mixin;
-
-import gq.malwarefight.nosession.mixin.asm.ReplacingMethodVisitor;
-import net.minecraft.launchwrapper.Launch;
-import org.objectweb.asm.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-
-public class Utils {
- static int num = 0;
- static int PORT = -1;
- static long ID = -1;
- private static final int BASE_PORT = 47777;
-
- public static byte[] read(InputStream i, Character delimiter) throws IOException {
- byte[] buffer = new byte[512];
- int index = 0;
- while (true) {
- int in = i.read();
- if (in == -1 || (delimiter != null && delimiter == in)) {
- return Arrays.copyOfRange(buffer, 0, index);
- }
- if (index == buffer.length) {
- // grow the buffer
- byte[] newBuffer = new byte[buffer.length * 2];
- System.arraycopy(
- buffer, 0, newBuffer, 0, buffer.length
- );
- buffer = newBuffer;
- }
- buffer[index] = (byte) in;
- index++;
- }
- }
-
- public static String readString(InputStream i, Character delimiter) throws IOException {
- return new String(read(i, delimiter), StandardCharsets.UTF_8);
- }
-
- public static void createClass(byte[] classArray, String name) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
- Method m = ClassLoader.class.getDeclaredMethod(
- "defineClass", String.class, byte[].class, int.class, int.class);
- m.setAccessible(true);
- m.invoke(Launch.classLoader, name, classArray, 0, classArray.length);
- }
-
- public static String getUniqueClassName() {
-
- String className = "gq.malwarefight.nosession.mixin.L2TweakerClone" + num;
-
- byte[] L2TweakerBytes;
- try {
- //noinspection ConstantConditions
- L2TweakerBytes = read(Utils.class.getResourceAsStream("/gq/malwarefight/nosession/mixin/L2Tweaker.class"), null);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- ClassReader cr = new ClassReader(L2TweakerBytes);
- ClassWriter cw = new ClassWriter(cr, 0);
- cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
- @Override
- public void visit(int version, int access, String name,
- String signature, String superName, String[] interfaces) {
- super.visit(version, access, className.replace(".", "/"), signature, superName, interfaces);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- return new ReplacingMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), L2Tweaker.class.getName().replace(".", "/"), className.replace(".", "/"));
- }
- }, 0);
-
- byte[] code = cw.toByteArray();
- try {
- createClass(code, className);
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- num++;
- return className;
- }
-
- public static Socket getProperSocket() {
- if (PORT == -1) {
- Socket socket = null;
- int port = 0;
- for (int i = BASE_PORT; i < BASE_PORT + 10; i++) {
- try {
- socket = new Socket();
- socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), i));
- socket.getOutputStream().write("id\n".getBytes(StandardCharsets.UTF_8));
- String value = readString(socket.getInputStream(), '\n');
- if (value.equals(Long.toString(ID))) {
- port = i;
- break;
- }
- } catch (Exception ignored) {}
- }
- PORT = port;
- return socket;
- } else {
- try {
- Socket socket = new Socket();
- socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), PORT));
- return socket;
- } catch (IOException e) {
- PORT = -1;
- return getProperSocket();
- }
- }
- }
-}
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/asm/ReplacingMethodVisitor.java b/src/main/java/gq/malwarefight/nosession/mixin/asm/ReplacingMethodVisitor.java
deleted file mode 100644
index d8c3005..0000000
--- a/src/main/java/gq/malwarefight/nosession/mixin/asm/ReplacingMethodVisitor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package gq.malwarefight.nosession.mixin.asm;
-
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-public class ReplacingMethodVisitor extends MethodVisitor implements Opcodes {
-
- final String newName;
- final String oldName;
- public ReplacingMethodVisitor(MethodVisitor mv, String oldName, String newName) {
- super(ASM5, mv);
- this.oldName = oldName;
- this.newName = newName;
- }
-
- public void visitFieldInsn(int opcode, String owner, String name,
- String desc) {
- owner = owner.replace(oldName, newName);
- super.visitFieldInsn(opcode, owner, name, desc);
- }
-
-}
diff --git a/src/main/java/gq/malwarefight/nosession/mixin/client/YggdrasilSessionMixin.java b/src/main/java/gq/malwarefight/nosession/mixin/client/YggdrasilSessionMixin.java
index 48327fe..5451c26 100644
--- a/src/main/java/gq/malwarefight/nosession/mixin/client/YggdrasilSessionMixin.java
+++ b/src/main/java/gq/malwarefight/nosession/mixin/client/YggdrasilSessionMixin.java
@@ -1,9 +1,10 @@
package gq.malwarefight.nosession.mixin.client;
+import com.google.common.primitives.Booleans;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
-import gq.malwarefight.nosession.mixin.Utils;
+import gq.malwarefight.nosession.utils.Utils;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -46,4 +47,4 @@ public class YggdrasilSessionMixin {
} catch (IOException ignored) {}
}
}
-}
+} \ No newline at end of file
diff --git a/src/main/java/gq/malwarefight/nosession/relaunch/Relaunch.java b/src/main/java/gq/malwarefight/nosession/relaunch/Relaunch.java
new file mode 100644
index 0000000..55e907c
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/relaunch/Relaunch.java
@@ -0,0 +1,100 @@
+package gq.malwarefight.nosession.relaunch;
+
+import gq.malwarefight.nosession.tweaks.CleanupTweaker;
+import gq.malwarefight.nosession.utils.Utils;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraftforge.fml.client.FMLClientHandler;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.ModAPIManager;
+import net.minecraftforge.fml.common.asm.ASMTransformerWrapper;
+import net.minecraftforge.fml.common.registry.ItemStackHolderInjector;
+import net.minecraftforge.fml.common.registry.ObjectHolderRegistry;
+import net.minecraftforge.fml.relauncher.FMLInjectionData;
+import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+
+public class Relaunch {
+ public static void relaunch(ArrayList<String> args, File gameDir, File assetsDir, String version) throws Exception {
+ resetSecurityManager();
+ setToNull(FMLLaunchHandler.class, "INSTANCE");
+ setToNull(Loader.class, "instance");
+ setToNull(ModAPIManager.class, "INSTANCE");
+ setToNull(ObjectHolderRegistry.class, "INSTANCE");
+ setToNull(ItemStackHolderInjector.class, "INSTANCE");
+ setToNull(FMLClientHandler.class, "INSTANCE");
+ setToNull(Loader.class, "injectedContainers");
+ Utils.setStaticValue(FMLInjectionData.class, "containers", new ArrayList<String>());
+ resetClass(ASMTransformerWrapper.class);
+ URLClassLoader originalClassLoader = (URLClassLoader) Launch.class.getClassLoader();
+ URL[] newURLS = new URL[originalClassLoader.getURLs().length + 1];
+ URLClassLoader lcl = new URLClassLoader(newURLS, originalClassLoader);
+ //noinspection unchecked
+ Class<Launch> innerLaunch = (Class<Launch>) Class.forName("net.minecraft.launchwrapper.Launch", false, lcl);
+ Method launch = innerLaunch.getDeclaredMethod("main", String[].class);
+ launch.invoke(null, (Object) constructArgs(args, gameDir, assetsDir, version));
+ }
+
+ public static String[] constructArgs(ArrayList<String> initial, File gameDir, File assetDir, String version) {
+ initial.add("--version");
+ initial.add(version);
+ initial.add("--gameDir");
+ initial.add(gameDir.getAbsolutePath());
+ initial.add("--assetsDir");
+ initial.add(assetDir.getAbsolutePath());
+ initial.add("--tweakClass");
+ initial.add("gq.malwarefight.nosession.tweaks.CleanupTweaker");
+ return initial.toArray(new String[0]);
+ }
+
+ public static void resetSecurityManager() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+ Method m = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
+ m.setAccessible(true);
+ Field[] fields = (Field[]) m.invoke(System.class, false);
+ for (Field field: fields) {
+ if (field.getType().equals(SecurityManager.class)) {
+ field.setAccessible(true);
+ field.set(null, null);
+ }
+ }
+ }
+
+
+ public static void resetClass(Class<?> cls) throws IllegalAccessException, NoSuchFieldException {
+ Field[] fields = cls.getDeclaredFields();
+ for (Field field: fields) {
+ if ((field.getModifiers() & Modifier.STATIC) != 0) {
+ setToNull(field);
+ }
+ }
+ }
+
+ public static void setToNull(Class<?> cls, String fieldname) throws NoSuchFieldException, IllegalAccessException {
+ Field f = cls.getDeclaredField(fieldname);
+ setToNull(f);
+ }
+
+ public static void setToNull(Field f) throws IllegalAccessException, NoSuchFieldException {
+ f.setAccessible(true);
+ if ((f.getModifiers() & Modifier.FINAL) != 0) { // if it is final
+ Field modifiers = Field.class.getDeclaredField("modifiers");
+ modifiers.setAccessible(true);
+ int value = modifiers.getInt(f);
+ value &= ~Modifier.FINAL;
+ modifiers.setInt(f, value);
+ }
+ if (f.getGenericType().equals(Boolean.TYPE)) {
+ f.set(null, false);
+ } else {
+ f.set(null, null);
+ }
+ }
+
+}
diff --git a/src/main/java/gq/malwarefight/nosession/tweaks/CleanupTweaker.java b/src/main/java/gq/malwarefight/nosession/tweaks/CleanupTweaker.java
new file mode 100644
index 0000000..6deeeb0
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/tweaks/CleanupTweaker.java
@@ -0,0 +1,82 @@
+package gq.malwarefight.nosession.tweaks;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import net.minecraft.launchwrapper.ITweaker;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+import net.minecraftforge.fml.common.asm.ASMTransformerWrapper;
+
+import java.io.File;
+import java.lang.reflect.*;
+import java.net.URL;
+import java.net.URLStreamHandler;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import gq.malwarefight.nosession.utils.Utils;
+
+public class CleanupTweaker implements ITweaker {
+ /**
+ * Cached to avoid expensive reflection operations
+ */
+ public Method makeWrapper;
+
+ public CleanupTweaker() throws NoSuchMethodException {
+ makeWrapper = ASMTransformerWrapper.class.getDeclaredMethod("makeWrapper", String.class);
+ makeWrapper.setAccessible(true);
+ }
+ @Override
+ @SuppressWarnings("unchecked")
+ public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+ // add the FMLTweaker
+ ArrayList<String> tweakerList = (ArrayList<String>) Launch.blackboard.get("TweakClasses");
+ tweakerList.add("net.minecraftforge.fml.common.launcher.FMLTweaker");
+ // reset ASMTransformerWrapper
+ Class<ASMTransformerWrapper> cls = ASMTransformerWrapper.class;
+ try {
+ Utils.setStaticValue(cls, "wrapperModMap", new HashMap<String, String>());
+ Utils.setStaticValue(cls, "wrapperParentMap", new HashMap<String, String>());
+ Utils.setStaticValue(cls, "wrapperCache", CacheBuilder.newBuilder().maximumSize(30L).weakValues().build(new CacheLoader<String, byte[]>() {
+ public byte[] load(String file) throws Exception {
+ return (byte[]) makeWrapper.invoke(null, file);
+ }
+ }));
+ Utils.setStaticValue(cls, "asmGenRoot", new URL("asmgen", null, -1, "/", getAsmGenHandler()));
+ Utils.setStaticValue(cls, "injected", false);
+ } catch (Exception e) {
+ System.err.println("NoSession: Fixing ASMTransformerWrapper failed. Things may break.");
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void injectIntoClassLoader(LaunchClassLoader classLoader) {}
+
+ @Override
+ public String getLaunchTarget() {
+ return "net.minecraft.client.main.Main";
+ }
+
+ @Override
+ public String[] getLaunchArguments() {
+ return new String[0];
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ private URLStreamHandler getAsmGenHandler() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+ Class<ASMTransformerWrapper> cls = ASMTransformerWrapper.class;
+ for (Class<?> candidate: cls.getDeclaredClasses()) {
+ if (candidate.getSimpleName().equals("ASMGenHandler")) {
+ Method pgdc = Class.class.getDeclaredMethod("privateGetDeclaredConstructors", boolean.class);
+ pgdc.setAccessible(true);
+ Constructor<? extends URLStreamHandler> constructor = ((Constructor<? extends URLStreamHandler>[]) pgdc.invoke(candidate, false))[0];
+ constructor.setAccessible(true);
+ return constructor.newInstance();
+ }
+ }
+ throw new RuntimeException("NoSession: unable to get the ASMGenHandler");
+ }
+}
diff --git a/src/main/java/gq/malwarefight/nosession/tweaks/InitialTweaker.java b/src/main/java/gq/malwarefight/nosession/tweaks/InitialTweaker.java
new file mode 100644
index 0000000..74d05f5
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/tweaks/InitialTweaker.java
@@ -0,0 +1,104 @@
+package gq.malwarefight.nosession.tweaks;
+
+import gq.malwarefight.nosession.relaunch.Relaunch;
+import gq.malwarefight.nosession.utils.Utils;
+import net.minecraft.launchwrapper.ITweaker;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+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.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.Socket;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class InitialTweaker implements ITweaker {
+
+ public InitialTweaker() {
+ System.gc(); // try to garbage collect the earlier launch data
+ }
+
+ /**
+ * 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 version The game version
+ */
+ @Override
+ public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String version) {
+ ArrayList<String> argsCopy = new ArrayList<>(args);
+ for (int i = 0; i < argsCopy.size(); i++) {
+ if (argsCopy.get(i).equals("--accessToken")) {
+ if (argsCopy.get(i + 1).equals("<noSessionAccessToken>")) {
+ 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();
+ }
+ })
+ );
+ return; // don't do anything, the change has already been made
+ }
+ try {
+ Utils.setToken(args.get(i + 1));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ argsCopy.set(i + 1, "<noSessionAccessToken>");
+ }
+ }
+ System.out.println("=======================");
+ System.out.println("NoSession: relaunching without the token");
+ System.out.println("=======================");
+ try {
+ Relaunch.relaunch(argsCopy, gameDir, assetsDir, version);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ /**
+ * 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() {
+ return new String[0];
+ }
+
+}
diff --git a/src/main/java/gq/malwarefight/nosession/utils/Utils.java b/src/main/java/gq/malwarefight/nosession/utils/Utils.java
new file mode 100644
index 0000000..fbacb8f
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/utils/Utils.java
@@ -0,0 +1,221 @@
+package gq.malwarefight.nosession.utils;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingMultimap;
+import com.google.gson.Gson;
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
+import gq.malwarefight.nosession.tweaks.InitialTweaker;
+import gq.malwarefight.tokenapp.Main;
+import org.apache.commons.io.ByteOrderMark;
+import org.apache.commons.lang3.CharEncoding;
+import org.apache.commons.lang3.SystemUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.objectweb.asm.Opcodes;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+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.Arrays;
+import java.util.Properties;
+import java.util.Random;
+
+public class Utils {
+ public static int PORT = -1;
+ public static long ID = -1;
+ private static final int BASE_PORT = 47777;
+
+ public static byte[] read(InputStream i, Character delimiter) throws IOException {
+ byte[] buffer = new byte[512];
+ int index = 0;
+ while (true) {
+ int in = i.read();
+ if (in == -1 || (delimiter != null && delimiter == in)) {
+ return Arrays.copyOfRange(buffer, 0, index);
+ }
+ if (index == buffer.length) {
+ // grow the buffer
+ byte[] newBuffer = new byte[buffer.length * 2];
+ System.arraycopy(
+ buffer, 0, newBuffer, 0, buffer.length
+ );
+ buffer = newBuffer;
+ }
+ buffer[index] = (byte) in;
+ index++;
+ }
+ }
+
+ public static String readString(InputStream i, Character delimiter) throws IOException {
+ return new String(read(i, delimiter), StandardCharsets.UTF_8);
+ }
+
+ public static Socket getProperSocket() {
+ if (PORT == -1) {
+ Socket socket = null;
+ int port = 0;
+ for (int i = BASE_PORT; i < BASE_PORT + 10; i++) {
+ try {
+ socket = new Socket();
+ socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), i));
+ socket.getOutputStream().write("id\n".getBytes(StandardCharsets.UTF_8));
+ String value = readString(socket.getInputStream(), '\n');
+ if (value.equals(Long.toString(ID))) {
+ port = i;
+ break;
+ }
+ } catch (Exception ignored) {}
+ }
+ PORT = port;
+ return socket;
+ } else {
+ try {
+ Socket socket = new Socket();
+ socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), PORT));
+ return socket;
+ } catch (IOException e) {
+ PORT = -1;
+ return getProperSocket();
+ }
+ }
+ }
+
+ public static void setStaticValue(Class<?> cls, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
+ Field f = cls.getDeclaredField(fieldName);
+ f.setAccessible(true);
+ if ((f.getModifiers() & Modifier.FINAL) != 0) { // if it is final
+ Field modifiers = Field.class.getDeclaredField("modifiers");
+ modifiers.setAccessible(true);
+ int modifiersValue = modifiers.getInt(f);
+ modifiersValue &= ~Modifier.FINAL;
+ modifiers.setInt(f, modifiersValue);
+ }
+ f.set(null, value);
+ }
+
+// public static String processString(String s) {
+// if (s.lastIndexOf("!") == -1) {
+// return s;
+// }
+// }
+
+ public static File getLibraryPathAsFile(Class<?> c) throws URISyntaxException {
+ return new File(c.getProtectionDomain().getCodeSource().getLocation().getPath());
+ }
+
+ public static String getLibraryPath(Class<?> c) throws URISyntaxException {
+
+ return getLibraryPathAsFile(c).getAbsolutePath();
+ }
+
+ public static String getClasspath(Properties p) throws URISyntaxException {
+ try {
+ // try to be smart
+ return String.join(
+ p.getProperty("path.separator"),
+ getLibraryPath(Utils.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)
+ );
+ } catch (URISyntaxException | IllegalArgumentException e) {
+ e.printStackTrace();
+ // fallback to "dumb" method
+ RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
+ return runtimeMXBean.getClassPath() + p.getProperty("path.separator") + getLibraryPath(Utils.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) {
+ LogManager.getLogger().info("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 static Properties getJavaProperties() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ Properties p = new Properties();
+ Method m = System.class.getDeclaredMethod("initProperties", Properties.class);
+ m.setAccessible(true);
+ m.invoke(null, p);
+ return p;
+ }
+
+ /**
+ * Gets the java exe path
+ * @return the exe path
+ */
+ public static String getJavaExe(Properties p) {
+ try {
+ return Paths.get(String.join(
+ p.getProperty("file.separator"),
+ p.getProperty("java.home"),
+ "bin",
+ "java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")
+ )).toFile().getAbsolutePath();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void setToken(String token) throws IOException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, URISyntaxException {
+ long value = getID();
+ ID = value;
+ Properties p = getJavaProperties();
+ System.out.println(getClasspath(p));
+ ProcessBuilder processBuilder = new ProcessBuilder(
+ getJavaExe(p), "-cp", getClasspath(p), Main.class.getName(), 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();
+ }
+}
diff --git a/src/main/java/gq/malwarefight/tokenapp/Main.java b/src/main/java/gq/malwarefight/tokenapp/Main.java
index 66afad1..62a4da3 100644
--- a/src/main/java/gq/malwarefight/tokenapp/Main.java
+++ b/src/main/java/gq/malwarefight/tokenapp/Main.java
@@ -5,7 +5,7 @@ import com.google.gson.JsonParser;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
-import gq.malwarefight.nosession.mixin.Utils;
+import gq.malwarefight.nosession.utils.Utils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import javax.net.ssl.HttpsURLConnection;
diff --git a/src/main/java/gq/malwarefight/tokenapp/SocketThread.java b/src/main/java/gq/malwarefight/tokenapp/SocketThread.java
index 05db6f0..de029c1 100644
--- a/src/main/java/gq/malwarefight/tokenapp/SocketThread.java
+++ b/src/main/java/gq/malwarefight/tokenapp/SocketThread.java
@@ -1,7 +1,7 @@
package gq.malwarefight.tokenapp;
import com.mojang.authlib.exceptions.AuthenticationException;
-import gq.malwarefight.nosession.mixin.Utils;
+import gq.malwarefight.nosession.utils.Utils;
import java.io.IOException;
import java.io.InputStream;