aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle83
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--src/main/cpp/libc.cpp31
-rw-r--r--src/main/cpp/libc.h29
-rw-r--r--src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java111
-rw-r--r--src/main/java/gq/malwarefight/nosession/linux/bwrap/BubblewrapBuilder.java401
-rw-r--r--src/main/java/gq/malwarefight/nosession/linux/libc/Libc.java31
-rw-r--r--src/main/java/gq/malwarefight/nosession/tweaks/cleanup/CleanupTweaker.java1
-rw-r--r--src/main/java/gq/malwarefight/nosession/utils/Utils.java55
9 files changed, 672 insertions, 72 deletions
diff --git a/build.gradle b/build.gradle
index 69efcb6..9d62ac3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,24 +1,31 @@
+import org.gradle.internal.jvm.Jvm
+
buildscript {
+ ext.kotlin_version = '1.8.21'
repositories {
//new forge repository
maven { url "https://maven.minecraftforge.net" }
- maven { url 'https://repo.spongepowered.org/maven'}
+ maven { url 'https://jitpack.io/' }
mavenCentral()
+ mavenLocal()
}
dependencies {
- classpath "net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT"
- classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT'
+ classpath 'com.github.thefightagainstmalware:ForgeGradle:5a1fcb9'
+ classpath 'com.github.thefightagainstmalware:MixinGradle:92e66fe'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id "java"
+ id 'cpp'
}
apply plugin: 'net.minecraftforge.gradle.forge'
+apply plugin: 'kotlin'
apply plugin: 'org.spongepowered.mixin'
-project.version = "1.1.1"
+project.version = "1.2.0"
group = "gq.malwarefight.nosession"
archivesBaseName = "nosession"
@@ -44,6 +51,7 @@ repositories {
}
dependencies {
+ compileOnly "net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9:universal"
shade('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
exclude module: 'launchwrapper'
exclude module: 'guava'
@@ -52,10 +60,13 @@ dependencies {
exclude module: 'log4j-core'
}
- compileOnly "net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9:universal"
+ compileOnly 'org.spongepowered:mixin:0.7.11-SNAPSHOT' // why gradle why why why
+ annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
processResources {
+ duplicatesStrategy = DuplicatesStrategy.WARN
//replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include "mcmod.info"
@@ -73,15 +84,64 @@ processResources {
}
+sourceSets {
+ main {
+ ext.refMap = "mixins.nosession.refmap.json"
+ }
+}
+
+model {
+ components {
+ linux(NativeLibrarySpec) {
+ sources {
+ cpp {
+ source {
+ srcDir 'src/main/cpp'
+ include "libc.cpp"
+ }
+ }
+ }
+ buildTypes {
+ release
+ }
+
+ binaries.all {
+ def jvmHome = Jvm.current().javaHome
+ if (targetPlatform.operatingSystem.macOsX) {
+ cppCompiler.args '-I', "${jvmHome}/include"
+ cppCompiler.args '-I', "${jvmHome}/include/darwin"
+ cppCompiler.args '-mmacosx-version-min=10.4'
+ linker.args '-mmacosx-version-min=10.4'
+ } else if (targetPlatform.operatingSystem.linux) {
+ cppCompiler.args '-I', "${jvmHome}/include"
+ cppCompiler.args '-I', "${jvmHome}/include/linux"
+ cppCompiler.args '-D_FILE_OFFSET_BITS=64'
+ } else if (targetPlatform.operatingSystem.windows) {
+ cppCompiler.args "-I${jvmHome}/include"
+ cppCompiler.args "-I${jvmHome}/include/win32"
+ } else if (targetPlatform.operatingSystem.freeBSD) {
+ cppCompiler.args '-I', "${jvmHome}/include"
+ cppCompiler.args '-I', "${jvmHome}/include/freebsd"
+ }
+ }
+ }
+ }
+}
+
+
jar {
- dependsOn configurations.compile
+ dependsOn project.configurations.compile
+ inputs.files {linuxSharedLibrary}
+ from("build/libs/linux/shared/" + System.mapLibraryName("linux")) {
+ into("native/" + System.getProperty("os.arch") + "/" + System.getProperty("os.name"))
+ }
+
from {
- configurations.compile.collect {
+ project.configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA', 'dummyThing'
-
manifest {
attributes "ForceLoadAsMod": true,
"TweakOrder": 0,
@@ -91,9 +151,6 @@ jar {
"FMLCorePlugin": "gq.malwarefight.nosession.NoSessionLoadingPlugin"
}
}
-
-sourceSets {
- main {
- ext.refMap = "mixins.nosession.refmap.json"
- }
+kotlin {
+ jvmToolchain(11)
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 16d2805..da1db5f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/src/main/cpp/libc.cpp b/src/main/cpp/libc.cpp
new file mode 100644
index 0000000..060e83e
--- /dev/null
+++ b/src/main/cpp/libc.cpp
@@ -0,0 +1,31 @@
+#include <jni.h>
+#include "unistd.h"
+#include <fcntl.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: gq_malwarefight_nosession_linux_libc_Libc
+ * Method: geteuid
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_gq_malwarefight_nosession_linux_libc_Libc_geteuid
+ (JNIEnv *, jclass) {
+ return (int) geteuid();
+}
+
+/*
+ * Class: gq_malwarefight_nosession_linux_libc_Libc
+ * Method: unlink
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT void JNICALL Java_gq_malwarefight_nosession_linux_libc_Libc_unlink
+ (JNIEnv* env, jclass, jstring string) {
+ const char* path = env->GetStringUTFChars(string, NULL);
+ unlink(path);
+ env->ReleaseStringUTFChars(string, path);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/main/cpp/libc.h b/src/main/cpp/libc.h
new file mode 100644
index 0000000..6aaa1a6
--- /dev/null
+++ b/src/main/cpp/libc.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class gq_malwarefight_nosession_linux_libc_Libc */
+
+#ifndef _Included_gq_malwarefight_nosession_linux_libc_Libc
+#define _Included_gq_malwarefight_nosession_linux_libc_Libc // NOLINT(bugprone-reserved-identifier)
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: gq_malwarefight_nosession_linux_libc_Libc
+ * Method: geteuid
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_gq_malwarefight_nosession_linux_libc_Libc_geteuid
+ (JNIEnv *, jclass);
+
+/*
+ * Class: gq_malwarefight_nosession_linux_libc_Libc
+ * Method: unlink
+ * Signature: (Ljava/lang/String;)
+ */
+JNIEXPORT void JNICALL Java_gq_malwarefight_nosession_linux_libc_Libc_unlink
+ (JNIEnv *, jclass, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java b/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java
index b61665f..9e0eb27 100644
--- a/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java
+++ b/src/main/java/gq/malwarefight/nosession/NoSessionLoadingPlugin.java
@@ -1,24 +1,28 @@
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.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import net.minecraft.launchwrapper.Launch;
-import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
+@SuppressWarnings("unused")
@IFMLLoadingPlugin.MCVersion("1.8.9")
@IFMLLoadingPlugin.Name("NoSession trolling")
@IFMLLoadingPlugin.SortingIndex(0)
@@ -39,20 +43,14 @@ public class NoSessionLoadingPlugin implements IFMLLoadingPlugin {
}
@Override
- public void injectData(Map<String, Object> map) {}
+ public void injectData(Map<String, Object> map) {
+ }
@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");
@@ -65,7 +63,7 @@ public class NoSessionLoadingPlugin implements IFMLLoadingPlugin {
public static ArrayList<String> constructLaunchArgs(HashMap<String, String> args) {
ArrayList<String> constructedArgs = new ArrayList<>();
- for (Entry<String, String> entry: args.entrySet()) {
+ for (Entry<String, String> entry : args.entrySet()) {
if (entry.getKey().equals("--accessToken")) {
constructedArgs.add(entry.getKey());
constructedArgs.add("<noSessionAccessToken>");
@@ -77,31 +75,75 @@ public class NoSessionLoadingPlugin implements IFMLLoadingPlugin {
return constructedArgs;
}
+ public static void relaunchProcess(Matcher m) throws Exception {
+ RuntimeMXBean rmb = ManagementFactory.getRuntimeMXBean();
+ if (!SystemUtils.IS_OS_LINUX) {
+ ArrayList<String> 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 <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);
+ }
+ } 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<String, String>
+ //noinspection unchecked
+ builder.addArgs(constructLaunchArgs((HashMap<String, String>) Launch.blackboard.get("launchArgs")));
+ builder.addArgs("--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker");
+ builder.build().start();
+ }
+ Utils.shutdown();
+ }
+
static {
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"));
+ Matcher m = mcJWT.matcher(System.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();
+ relaunchProcess(m);
} else {
// test if we can find the token in Launch.blackboard.get("launchArgs")
//noinspection unchecked
@@ -114,6 +156,9 @@ public class NoSessionLoadingPlugin implements IFMLLoadingPlugin {
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) {
diff --git a/src/main/java/gq/malwarefight/nosession/linux/bwrap/BubblewrapBuilder.java b/src/main/java/gq/malwarefight/nosession/linux/bwrap/BubblewrapBuilder.java
new file mode 100644
index 0000000..34542cd
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/linux/bwrap/BubblewrapBuilder.java
@@ -0,0 +1,401 @@
+package gq.malwarefight.nosession.linux.bwrap;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import gq.malwarefight.nosession.linux.libc.Libc;
+import gq.malwarefight.nosession.utils.Utils;
+import org.apache.logging.log4j.LogManager;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+@SuppressWarnings("unused") // library class
+public class BubblewrapBuilder {
+ final ArrayList<String> bubblewrapArgs = new ArrayList<>();
+ final ArrayList<String> programArgs = new ArrayList<>();
+ String command = "";
+
+ public BubblewrapBuilder addArgsFromFD(int fd) {
+ bubblewrapArgs.add("--args");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder unshareAll() {
+ bubblewrapArgs.add("--unshare-all");
+ return this;
+ }
+
+ public BubblewrapBuilder shareNet() {
+ bubblewrapArgs.add("--share-net");
+ return this;
+ }
+
+ public BubblewrapBuilder unshareUser() {
+ return unshareUser(false);
+ }
+
+ public BubblewrapBuilder unshareUser(boolean try_) {
+ bubblewrapArgs.add(try_ ? "--unshare-user-try" : "--unshare-user");
+ return this;
+ }
+
+ public BubblewrapBuilder unshareIPC() {
+ bubblewrapArgs.add("--unshare-ipc");
+ return this;
+ }
+
+ public BubblewrapBuilder unsharePID() {
+ bubblewrapArgs.add("--unshare-pid");
+ return this;
+ }
+
+ public BubblewrapBuilder unshareNet() {
+ bubblewrapArgs.add("--unshare-net");
+ return this;
+ }
+
+ public BubblewrapBuilder unshareUTS() {
+ bubblewrapArgs.add("--unshare-uts");
+ return this;
+ }
+
+ public BubblewrapBuilder unshareCGroup() {
+ return unshareCGroup(false);
+ }
+
+ public BubblewrapBuilder unshareCGroup(boolean try_) {
+ bubblewrapArgs.add(try_ ? "--unshare-cgroup-try" : "--unshare-cgroup");
+ return this;
+ }
+
+ public BubblewrapBuilder setUserNS(int fd) {
+ return setUserNS(fd, false);
+ }
+
+ public BubblewrapBuilder setUserNS(int fd, boolean afterSetup) {
+ bubblewrapArgs.add(afterSetup ? "--userns2" : "--userns");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder disableUserNS() {
+ bubblewrapArgs.add("--disable-userns");
+ return this;
+ }
+
+ public BubblewrapBuilder assertUserNSDisabled() {
+ bubblewrapArgs.add("--assert-userns-disabled");
+ return this;
+ }
+
+ public BubblewrapBuilder setPIDNS(int fd) {
+ bubblewrapArgs.add("--pidns");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder setUID(int uid) {
+ bubblewrapArgs.add("--uid");
+ bubblewrapArgs.add(String.valueOf(uid));
+ return this;
+ }
+
+ public BubblewrapBuilder setGID(int gid) {
+ bubblewrapArgs.add("--gid");
+ bubblewrapArgs.add(String.valueOf(gid));
+ return this;
+ }
+
+ public BubblewrapBuilder setHostname(String name) {
+ bubblewrapArgs.add("--hostname");
+ bubblewrapArgs.add(name);
+ return this;
+ }
+
+ public BubblewrapBuilder setChdir(String dir) {
+ bubblewrapArgs.add("--chdir");
+ bubblewrapArgs.add(dir);
+ return this;
+ }
+
+ public BubblewrapBuilder clearEnv() {
+ bubblewrapArgs.add("--clearenv");
+ return this;
+ }
+
+ public BubblewrapBuilder setEnv(String key, String value) {
+ bubblewrapArgs.add("--setenv");
+ bubblewrapArgs.add(key);
+ bubblewrapArgs.add(value);
+ return this;
+ }
+
+ public BubblewrapBuilder unSetEnv(String key) {
+ bubblewrapArgs.add("--unsetenv");
+ bubblewrapArgs.add(key);
+ return this;
+ }
+
+ public BubblewrapBuilder setLockFile(String file) {
+ bubblewrapArgs.add("--lock-file");
+ bubblewrapArgs.add(file);
+ return this;
+ }
+
+ public BubblewrapBuilder syncFD(int fd) {
+ bubblewrapArgs.add("--sync-fd");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder bind(String src, String dest) {
+ return bind(src, dest, false, false, false);
+ }
+
+ public BubblewrapBuilder bindTry(String src, String dest) {
+ return bind(src, dest, true, false, false);
+ }
+
+ public BubblewrapBuilder devBind(String src, String dest) {
+ return bind(src, dest, false, true, false);
+ }
+
+ public BubblewrapBuilder devBindTry(String src, String dest) {
+ return bind(src, dest, true, true, false);
+ }
+
+ public BubblewrapBuilder readOnlyBind(String src, String dest) {
+ return bind(src, dest, false, false, true);
+ }
+
+ public BubblewrapBuilder readOnlyBindTry(String src, String dest) {
+ return bind(src, dest, true, false, true);
+ }
+
+ private BubblewrapBuilder bind(String src, String dest, boolean try_, boolean dev, boolean ro) {
+ if (ro && dev) {
+ throw new IllegalArgumentException("Cannot bind both read-only and dev");
+ }
+ StringBuilder argument = new StringBuilder();
+ argument.append("--");
+ if (dev) {
+ argument.append("dev-");
+ } else if (ro) {
+ argument.append("ro-");
+ }
+ argument.append("bind");
+ if (try_) {
+ argument.append("-try");
+ }
+ bubblewrapArgs.add(argument.toString());
+ bubblewrapArgs.add(src);
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+ public BubblewrapBuilder readOnlyRemount(String dest) {
+ bubblewrapArgs.add("--remount-ro");
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+ public BubblewrapBuilder execLabel(String label) {
+ bubblewrapArgs.add("--exec-label");
+ bubblewrapArgs.add(label);
+ return this;
+ }
+
+ public BubblewrapBuilder fileLabel(String label) {
+ bubblewrapArgs.add("--file-label");
+ bubblewrapArgs.add(label);
+ return this;
+ }
+
+ public BubblewrapBuilder mountProc(String dest) {
+ bubblewrapArgs.add("--proc");
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+
+ public BubblewrapBuilder mountDev(String dest) {
+ bubblewrapArgs.add("--dev");
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+ public BubblewrapBuilder mountTmpfs(String dest) {
+ bubblewrapArgs.add("--tmpfs");
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+ public BubblewrapBuilder mountMqueue(String dest) {
+ bubblewrapArgs.add("--mqueue");
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+ public BubblewrapBuilder createDir(String dest) {
+ bubblewrapArgs.add("--dir");
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+
+ public BubblewrapBuilder copyFile(int fd, String dest) {
+ bubblewrapArgs.add("--file");
+ bubblewrapArgs.add(String.valueOf(fd));
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+
+ public BubblewrapBuilder bindData(int fd, String dest) {
+ return bindData(fd, dest, false);
+ }
+
+
+ public BubblewrapBuilder bindDataReadOnly(int fd, String dest) {
+ return bindData(fd, dest, true);
+ }
+
+ private BubblewrapBuilder bindData(int fd, String dest, boolean ro) {
+ bubblewrapArgs.add("--" + (ro ? "ro" : "") + "bind-data");
+ bubblewrapArgs.add(String.valueOf(fd));
+ bubblewrapArgs.add(dest);
+ return this;
+ }
+
+ public BubblewrapBuilder addSymlink(String src, String target) {
+ bubblewrapArgs.add("--symlink");
+ bubblewrapArgs.add(src);
+ bubblewrapArgs.add(target);
+ return this;
+ }
+
+ public BubblewrapBuilder loadSeccompFilters(int fd) {
+ bubblewrapArgs.add("--seccomp");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder addSeccompFilters(int fd) {
+ bubblewrapArgs.add("--add-seccomp-fd");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+
+ public BubblewrapBuilder blockOnFD(int fd) {
+ bubblewrapArgs.add("--block-fd");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder blockOnFdUntilUserNS(int fd) {
+ bubblewrapArgs.add("--userns-block-fd");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder infoFD(int fd) {
+ bubblewrapArgs.add("--info-fd");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder jsonStatusFD(int fd) {
+ bubblewrapArgs.add("--json-status-fd");
+ bubblewrapArgs.add(String.valueOf(fd));
+ return this;
+ }
+
+ public BubblewrapBuilder newSession() {
+ bubblewrapArgs.add("--new-session");
+ return this;
+ }
+
+ public BubblewrapBuilder dieWithParent() {
+ bubblewrapArgs.add("--die-with-parent");
+ return this;
+ }
+
+ public BubblewrapBuilder asPid1() {
+ bubblewrapArgs.add("--as-pid-1");
+ return this;
+ }
+
+ public BubblewrapBuilder capAdd(String capability) {
+ bubblewrapArgs.add("--cap-add");
+ bubblewrapArgs.add(capability);
+ return this;
+ }
+
+ public BubblewrapBuilder capDrop(String capability) {
+ bubblewrapArgs.add("--cap-drop");
+ bubblewrapArgs.add(capability);
+ return this;
+ }
+
+ public BubblewrapBuilder chmod(String octal, String path) {
+ bubblewrapArgs.add("--chmod");
+ bubblewrapArgs.add(octal);
+ bubblewrapArgs.add(path);
+ return this;
+ }
+
+ public BubblewrapBuilder addArgs(Iterable<String> args) {
+ args.forEach(programArgs::add);
+ return this;
+ }
+
+ public BubblewrapBuilder addArgs(String... args) {
+ programArgs.addAll(Arrays.asList(args));
+ return this;
+ }
+
+ public BubblewrapBuilder setCommand(String command) {
+ this.command = command;
+ return this;
+ }
+
+ private String downloadBubblewrap() throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ File f = Files.createTempFile("nosession_bwrap", "").toFile();
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ Libc.unlink(f.getAbsolutePath());
+ }));
+ URL url = new URL("https://api.github.com/repos/pandaninjas/bubblewrap-static/releases/latest");
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+ String result = Utils.readString(connection.getInputStream(), null);
+ JsonObject object = new JsonParser().parse(result).getAsJsonObject();
+ URL downloadURL = new URL(object.get("assets").getAsJsonArray().get(0).getAsJsonObject().get("browser_download_url").getAsString());
+ HttpsURLConnection download = (HttpsURLConnection) downloadURL.openConnection();
+ Utils.copy(download.getInputStream(), Files.newOutputStream(f.toPath()));
+ boolean success = f.setExecutable(true);
+ if (!success) {
+ LogManager.getLogger().error("Failed to mark file as executable. Quitting");
+ Utils.shutdown();
+ }
+ return f.getAbsolutePath();
+ }
+
+ public ProcessBuilder build() throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ ProcessBuilder pb = new ProcessBuilder();
+ String bubbleWrapPath = downloadBubblewrap();
+ ArrayList<String> finalArgs = new ArrayList<>();
+ finalArgs.add(bubbleWrapPath);
+ finalArgs.addAll(bubblewrapArgs);
+ finalArgs.add(command);
+ finalArgs.addAll(programArgs);
+ pb.command(finalArgs).redirectOutput(new File("/home/pandaninjas/log")).redirectError(new File("/home/pandaninjas/log1"));
+ return pb;
+ }
+}
diff --git a/src/main/java/gq/malwarefight/nosession/linux/libc/Libc.java b/src/main/java/gq/malwarefight/nosession/linux/libc/Libc.java
new file mode 100644
index 0000000..670f83d
--- /dev/null
+++ b/src/main/java/gq/malwarefight/nosession/linux/libc/Libc.java
@@ -0,0 +1,31 @@
+package gq.malwarefight.nosession.linux.libc;
+
+import gq.malwarefight.nosession.utils.Utils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+public class Libc {
+ private static final Logger log = LogManager.getLogger();
+ public static native int geteuid();
+ public static native void unlink(String pathname);
+
+ static {
+ try {
+ File tempFile = Files.createTempFile("nosession_libc", ".so").toFile();
+ try (InputStream is = Libc.class.getResourceAsStream("/native/" + System.getProperty("os.arch") + "/" + System.getProperty("os.name") + "/" + System.mapLibraryName("linux"))) {
+ assert is != null: "Native library not compiled";
+ Utils.copy(is, Files.newOutputStream(tempFile.toPath()));
+ }
+ System.load(tempFile.getAbsolutePath());
+ Runtime.getRuntime().addShutdownHook(
+ new Thread(() -> Libc.unlink(tempFile.getAbsolutePath()))
+ );
+ } catch (Exception e) {
+ log.error("Failed to load the native Linux modules, native libraries may fail", e);
+ }
+ }
+}
diff --git a/src/main/java/gq/malwarefight/nosession/tweaks/cleanup/CleanupTweaker.java b/src/main/java/gq/malwarefight/nosession/tweaks/cleanup/CleanupTweaker.java
index a0d458b..9a5997b 100644
--- a/src/main/java/gq/malwarefight/nosession/tweaks/cleanup/CleanupTweaker.java
+++ b/src/main/java/gq/malwarefight/nosession/tweaks/cleanup/CleanupTweaker.java
@@ -39,6 +39,7 @@ public class CleanupTweaker implements ITweaker {
Utils.setStaticValue(cls, "wrapperParentMap", new HashMap<String, String>());
//noinspection UnstableApiUsage
Utils.setStaticValue(cls, "wrapperCache", CacheBuilder.newBuilder().maximumSize(30L).weakValues().build(new CacheLoader<String, byte[]>() {
+ @SuppressWarnings("NullableProblems")
public byte[] load(String file) throws Exception {
return (byte[]) makeWrapper.invoke(null, file);
}
diff --git a/src/main/java/gq/malwarefight/nosession/utils/Utils.java b/src/main/java/gq/malwarefight/nosession/utils/Utils.java
index ab2f9c0..7f65b2a 100644
--- a/src/main/java/gq/malwarefight/nosession/utils/Utils.java
+++ b/src/main/java/gq/malwarefight/nosession/utils/Utils.java
@@ -4,6 +4,7 @@ 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.linux.libc.Libc;
import gq.malwarefight.tokenapp.Main;
import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.lang3.CharEncoding;
@@ -13,27 +14,33 @@ 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.io.*;
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.net.*;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
-import java.util.Properties;
+import java.util.Scanner;
import java.util.UUID;
public class Utils {
public static int PORT = -1;
private static final int BASE_PORT = 47777;
+ public static void copy(InputStream i, OutputStream o) throws IOException {
+ byte[] buffer = new byte[16384];
+ int read;
+ while ((read = i.read(buffer)) > 0) {
+ o.write(buffer, 0, read);
+ }
+ i.close();
+ o.close();
+ }
+
public static byte[] read(InputStream i, Character delimiter) throws IOException {
byte[] buffer = new byte[512];
int index = 0;
@@ -112,7 +119,7 @@ public class Utils {
public static String processString(String uri) {
try {
- return uri.substring(uri.indexOf('/'), uri.lastIndexOf('!'));
+ return uri.substring(uri.indexOf(":") + 1, uri.lastIndexOf('!'));
} catch (Exception e) {
e.printStackTrace();
return uri;
@@ -124,16 +131,16 @@ public class Utils {
if (uri.endsWith(".class")) {
uri = processString(uri); // stupid reference to a class within a jar
}
- return new File(uri);
+ return new File(new URI(uri));
}
public static String getLibraryPath(Class<?> c) throws URISyntaxException {
return getLibraryPathAsFile(c).getAbsolutePath();
}
- private static String getClasspath(Properties p) throws URISyntaxException {
+ private static String getClasspath() throws URISyntaxException {
return String.join(
- p.getProperty("path.separator"),
+ System.getProperty("path.separator"),
getLibraryPath(Main.class),
getLibraryPath(YggdrasilAuthenticationService.class),
getLibraryPath(Gson.class),
@@ -148,23 +155,15 @@ public class Utils {
);
}
- 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) {
+ public static String getJavaExe() {
try {
return Paths.get(String.join(
- p.getProperty("file.separator"),
- p.getProperty("java.home"),
+ System.getProperty("file.separator"),
+ System.getProperty("java.home"),
"bin",
"java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")
)).toFile().getAbsolutePath();
@@ -173,8 +172,7 @@ public class Utils {
}
}
- public static void setToken(String token) throws IOException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, URISyntaxException {
- Properties p = getJavaProperties();
+ public static void setToken(String token) throws IOException, URISyntaxException {
ProcessBuilder processBuilder = new ProcessBuilder(
getJavaExe(p), "-XX:+DisableAttachMechanism", "-cp", getClasspath(p), Main.class.getName()
);
@@ -183,4 +181,11 @@ public class Utils {
c.getOutputStream().write((token + "\n").getBytes(StandardCharsets.UTF_8));
c.getOutputStream().flush();
}
+ 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);
+ }
+
}