ohmygod
:3
This commit is contained in:
parent
227c76bfff
commit
2bb0d88e64
11 changed files with 414 additions and 125 deletions
|
@ -6,9 +6,7 @@ import com.baseband.client.event.EventBus;
|
|||
import com.baseband.client.event.FMLEventProcessor;
|
||||
import com.baseband.client.module.Module;
|
||||
import com.baseband.client.module.modules.*;
|
||||
import de.tudbut.mcregistry.MCRegistry;
|
||||
import de.tudbut.tools.Registry;
|
||||
import de.tudbut.tools.Tools;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
@ -31,11 +29,11 @@ import java.util.ArrayList;
|
|||
@Mod(modid = "baseband")
|
||||
public class BaseBand {
|
||||
public static int majorVersion = 1;
|
||||
public static int buildNumber = 189;
|
||||
public static String hash = "19a91abc85a04461";
|
||||
public static int buildNumber = 195;
|
||||
public static String hash = "996032a4408f699a";
|
||||
|
||||
public static String name = "BaseBand";
|
||||
public long timeOfCompile = 1695669761860L;
|
||||
public long timeOfCompile = 1695766816016L;
|
||||
public CommandManager commandRegistry;
|
||||
public EventBus eventBus;
|
||||
public ArrayList<Module> modules = new ArrayList<>();
|
||||
|
@ -73,27 +71,7 @@ public class BaseBand {
|
|||
|
||||
downloadMCRegistry();
|
||||
|
||||
try {
|
||||
Registry = MCRegistry.registerMod("baseband");
|
||||
registryData = Registry.register("*");
|
||||
} catch (Exception e) {
|
||||
// tamper detected
|
||||
Utils.crash();
|
||||
}
|
||||
// cant be a normal if statement because it might be null
|
||||
if (registryData.get("LoaderPresent") == Boolean.TRUE) {
|
||||
String key = registryData.getString("Key");
|
||||
TCN data = TCN.readMap(Tools.stringToMap(new Key(key).decryptString(registryData.getString("Data"))));
|
||||
registryData.set("Key", null);
|
||||
registryData.set("Data", null);
|
||||
|
||||
this.level = data.getInteger("level");
|
||||
} else {
|
||||
// do other stuff here later?
|
||||
log.info("No loader present, but able to start anyway ==> Debug environment detected.");
|
||||
}
|
||||
// unset so this won't be discovered and manipulated
|
||||
registryData.set("LoaderPresent", null);
|
||||
|
||||
commandRegistry = new CommandManager();
|
||||
eventBus = new EventBus();
|
||||
|
@ -162,7 +140,7 @@ public class BaseBand {
|
|||
}
|
||||
|
||||
public void addModule(Module m) {
|
||||
Restrict annotation = m.getClass().getDeclaredAnnotation(Restrict.class)
|
||||
Restrict annotation = m.getClass().getDeclaredAnnotation(Restrict.class);
|
||||
if (annotation != null) {
|
||||
if(level < annotation.value().level)
|
||||
return;
|
||||
|
|
|
@ -71,8 +71,8 @@ dependencies {
|
|||
}
|
||||
|
||||
// this is a tweaker, so it can go into the jar
|
||||
jarLibs files('libs/mcregistry-1.0.jar')
|
||||
|
||||
//jarLibs files('libs/mcregistry-1.0.jar')
|
||||
//No
|
||||
|
||||
annotationProcessor('org.spongepowered:mixin:0.8.5:processor') {
|
||||
exclude module: 'gson'
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher;
|
||||
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
package org.baseband.launcher.util;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher.classloader;
|
||||
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.baseband.launcher.launch.Loader;
|
||||
import org.baseband.launcher.util.security.SecureContainer;
|
||||
import org.spongepowered.asm.service.MixinService;
|
||||
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -12,8 +21,7 @@ import java.util.HashMap;
|
|||
|
||||
|
||||
public class CustomClassloader extends ClassLoader {
|
||||
public CustomClassloader INSTANCE;
|
||||
private static final DataKeeper<HashMap<String, byte[]>> encryptedClasses = new DataKeeper<>(new HashMap<>(), true);
|
||||
private static SecureContainer<Object> encryptedClasses;
|
||||
|
||||
|
||||
|
||||
|
@ -21,9 +29,9 @@ public class CustomClassloader extends ClassLoader {
|
|||
initClasses(obj);
|
||||
}
|
||||
|
||||
public CustomClassloader() {}
|
||||
|
||||
public void initClasses(Object classes){
|
||||
encryptedClasses = new SecureContainer<>(new HashMap<>(), true);
|
||||
try {
|
||||
CustomMixinServer customService = new CustomMixinServer();
|
||||
Class<?> mixinServiceClass = Class.forName("org.spongepowered.asm.service.MixinService");
|
||||
|
@ -41,17 +49,13 @@ public class CustomClassloader extends ClassLoader {
|
|||
Loader.exit();
|
||||
}
|
||||
|
||||
INSTANCE = new CustomClassloader();
|
||||
//CustomClassloader.classes = classes;
|
||||
|
||||
encryptedClasses.access(accessor -> accessor.setValue((HashMap<String, byte[]>) classes));
|
||||
|
||||
encryptedClasses.access(accessor -> accessor.setValue(classes));
|
||||
|
||||
try {
|
||||
Field parent = ClassLoader.class.getDeclaredField("parent");
|
||||
parent.setAccessible(true);
|
||||
parent.set(INSTANCE, parent.get(Launch.classLoader));
|
||||
parent.set(Launch.classLoader, INSTANCE);
|
||||
parent.set(this, parent.get(Launch.classLoader));
|
||||
parent.set(Launch.classLoader, this);
|
||||
} catch (IllegalAccessException | NoSuchFieldException var6) {
|
||||
var6.printStackTrace();
|
||||
}
|
||||
|
@ -62,13 +66,20 @@ public class CustomClassloader extends ClassLoader {
|
|||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
final byte[][] data = {null};
|
||||
encryptedClasses.access(accessor -> data[0] = Loader.classKey.decryptByte(accessor.getValue().get(name)));
|
||||
encryptedClasses.access(accessor -> data[0] = Loader.classKey.decryptByte(((HashMap<String, byte[]>)accessor.getValue()).get(name)));
|
||||
if(data[0] != null) {
|
||||
Class<?> clazz = defineClass(name, data[0], 0, data[0].length);
|
||||
if (clazz == null) {
|
||||
try {
|
||||
Field b = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
Unsafe unsafe = (Unsafe)b.get(null);
|
||||
Class<?> definedClass = unsafe.defineClass(name, data[0], 0, data[0].length, this, null);
|
||||
|
||||
if (definedClass == null) {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
return clazz;
|
||||
return definedClass;
|
||||
}catch (Exception e){
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return Launch.classLoader.findClass(name);
|
||||
|
@ -79,12 +90,12 @@ public class CustomClassloader extends ClassLoader {
|
|||
}
|
||||
|
||||
|
||||
static class CustomMixinServer extends MixinServiceLaunchWrapper {
|
||||
public static class CustomMixinServer extends MixinServiceLaunchWrapper {
|
||||
@Override
|
||||
public byte[] getClassBytes(String name, String transformedName) throws IOException {
|
||||
if(name.startsWith("com.baseband")) {
|
||||
final byte[][] bytes = {null};
|
||||
encryptedClasses.access(accessor -> bytes[0] = Loader.classKey.decryptByte(accessor.getValue().get(name)));
|
||||
encryptedClasses.access(accessor -> bytes[0] = Loader.classKey.decryptByte(((HashMap<String, byte[]>)accessor.getValue()).get(name)));
|
||||
if (bytes[0] != null) {
|
||||
return bytes[0];
|
||||
}
|
||||
|
@ -96,7 +107,7 @@ public class CustomClassloader extends ClassLoader {
|
|||
public byte[] getClassBytes(String name, boolean runTransformers) throws ClassNotFoundException, IOException {
|
||||
if(name.startsWith("com.baseband")) {
|
||||
final byte[][] bytes = {null};
|
||||
encryptedClasses.access(accessor -> bytes[0] = Loader.classKey.decryptByte(accessor.getValue().get(name)));
|
||||
encryptedClasses.access(accessor -> bytes[0] = Loader.classKey.decryptByte(((HashMap<String, byte[]>)accessor.getValue()).get(name)));
|
||||
if (bytes[0] != null) {
|
||||
return bytes[0];
|
||||
}
|
|
@ -1,26 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher.launch;
|
||||
|
||||
import de.tudbut.mcregistry.MCRegistry;
|
||||
import de.tudbut.tools.Registry;
|
||||
import de.tudbut.tools.Tools;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.baseband.launcher.Tweaker;
|
||||
import org.baseband.launcher.util.CustomClassloader;
|
||||
import org.baseband.launcher.util.security.BaseBandSecurityManager;
|
||||
import org.baseband.launcher.classloader.CustomClassloader;
|
||||
import org.baseband.launcher.util.Key;
|
||||
import sun.misc.Unsafe;
|
||||
import tudbut.io.StreamRedirect;
|
||||
import tudbut.parsing.TCN;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
@ -80,16 +79,7 @@ public class Loader {
|
|||
objectKey = new Key();
|
||||
|
||||
|
||||
if (System.getProperty("com.bb.debugKey") != null) {
|
||||
if (System.getProperty("com.bb.debugKey").equalsIgnoreCase("true")) {
|
||||
Tweaker.log("!!Warning!!\nEncryption Debug set to enabled.");
|
||||
communicationKey.setDebug(true);
|
||||
classKey.setDebug(true);
|
||||
objectKey.setDebug(true);
|
||||
}
|
||||
}
|
||||
|
||||
outputF.writeUTF("loader")
|
||||
outputF.writeUTF("loader");
|
||||
outputF.writeUTF(communicationKey.encryptString(username));
|
||||
outputF.writeUTF(communicationKey.encryptString(password));
|
||||
outputF.writeUTF(communicationKey.encryptString(generate()));
|
||||
|
@ -144,8 +134,7 @@ public class Loader {
|
|||
}
|
||||
|
||||
|
||||
String key = getRandomTicket();
|
||||
|
||||
/*
|
||||
Registry baseBandRegistry = MCRegistry.registerMod("baseband");
|
||||
TCN tcn = baseBandRegistry.register("*");
|
||||
tcn.set("LoaderPresent", true);
|
||||
|
@ -158,6 +147,7 @@ public class Loader {
|
|||
baseBandRegistry.unregister("*", tcn);
|
||||
MCRegistry.unregisterMod("baseband", baseBandRegistry);
|
||||
MCRegistry.GlobalRegistry.save();
|
||||
*/
|
||||
|
||||
|
||||
Map<String, byte[]> classCache = new HashMap<>();
|
||||
|
@ -180,6 +170,7 @@ public class Loader {
|
|||
//Yep!
|
||||
|
||||
|
||||
|
||||
try (ZipInputStream zipStream = new ZipInputStream(input)) {
|
||||
ZipEntry zipEntry;
|
||||
while ((zipEntry = zipStream.getNextEntry()) != null) {
|
||||
|
@ -311,9 +302,46 @@ public class Loader {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
SecurityManager currentSecurityManager = System.getSecurityManager();
|
||||
|
||||
if (currentSecurityManager != null) {
|
||||
Field b = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
boolean a = b.isAccessible();
|
||||
b.setAccessible(true);
|
||||
Unsafe unsafe = (Unsafe)b.get(null);
|
||||
b.setAccessible(a);
|
||||
Object base = null;
|
||||
Field[] fields = System.class.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
base = unsafe.staticFieldBase(field);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
long offset = 0L;
|
||||
|
||||
while (true) {
|
||||
Object object = unsafe.getObject(base, offset);
|
||||
if (object == currentSecurityManager) {
|
||||
unsafe.putObject(base, offset, new BaseBandSecurityManager());
|
||||
return false;
|
||||
}
|
||||
|
||||
offset += 4L;
|
||||
}
|
||||
} else {
|
||||
System.setSecurityManager(new BaseBandSecurityManager());
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
//return false if it's fine, return true if it broke
|
||||
}
|
||||
|
||||
|
||||
private static Unsafe getUnsafe() {
|
||||
try {
|
||||
|
@ -350,8 +378,6 @@ public class Loader {
|
|||
Method exitMethod = shutdownClass.getDeclaredMethod("exit", int.class);
|
||||
exitMethod.setAccessible(true);
|
||||
exitMethod.invoke(null, 1);
|
||||
} catch (Exception b) {
|
||||
while (true) ;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher.tweaker;
|
||||
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Key {
|
||||
//Daniella made the actual encryption,
|
||||
//Jess made the serialization/byte handling/randomTicket
|
||||
|
||||
protected final String string;
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
|
||||
public Key() {
|
||||
string = getRandomTicket();
|
||||
}
|
||||
|
@ -25,9 +25,6 @@ public class Key {
|
|||
string = new String(key);
|
||||
}
|
||||
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
private static String getRandomTicket() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
@ -37,39 +34,6 @@ public class Key {
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
public byte[] serializeObject(Object obj) {
|
||||
try {
|
||||
if(debug) {
|
||||
System.out.println(obj + " serialize + encrypt");
|
||||
}
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
ObjectOutputStream objectOut = new ObjectOutputStream(byteArrayOutputStream);
|
||||
objectOut.writeObject(obj);
|
||||
objectOut.close();
|
||||
return encryptByte(byteArrayOutputStream.toByteArray());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null; // Return null in case of an error
|
||||
}
|
||||
}
|
||||
|
||||
public Object deserializeObject(byte[] bytes) {
|
||||
try {
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decryptByte(bytes));
|
||||
ObjectInputStream objectIn = new ObjectInputStream(byteArrayInputStream);
|
||||
Object obj = objectIn.readObject();
|
||||
objectIn.close();
|
||||
if(debug) {
|
||||
System.out.println(obj + " deserialize + decrypt");
|
||||
}
|
||||
return obj;
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null; // Return null in case of an error
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] encryptByte(byte[] bytes) {
|
||||
if(bytes == null) {
|
||||
return null;
|
||||
|
|
217
Loader/src/main/java/org/baseband/launcher/util/Lock.java
Normal file
217
Loader/src/main/java/org/baseband/launcher/util/Lock.java
Normal file
|
@ -0,0 +1,217 @@
|
|||
package org.baseband.launcher.util;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Helper for synchronization and timing
|
||||
* {@code @Author} TudbuT
|
||||
*/
|
||||
public class Lock {
|
||||
|
||||
private final Locker locker = new Locker();
|
||||
private boolean locked = false;
|
||||
private int t = 0;
|
||||
private long ts = 0;
|
||||
private final AtomicInteger waiting = new AtomicInteger();
|
||||
private volatile boolean[] waiterLocker = null;
|
||||
|
||||
/**
|
||||
* Object to handle thread locking
|
||||
*/
|
||||
private static class Locker {
|
||||
|
||||
/**
|
||||
* Make the thread wait until {@link Locker#unlock()} is called
|
||||
* @throws InterruptedException Inherited from {@link Object#wait}
|
||||
*/
|
||||
public synchronized void lockHere() throws InterruptedException {
|
||||
wait();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the thread wait until {@link Locker#unlock()} is called or the timeout runs out
|
||||
* @throws InterruptedException Inherited from {@link Object#wait}
|
||||
* @param timeout Maximal wait time
|
||||
*/
|
||||
public synchronized void lockHere(long timeout) throws InterruptedException {
|
||||
wait(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop locking
|
||||
*/
|
||||
public synchronized void unlock() {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Lock without default state
|
||||
*/
|
||||
public Lock() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Lock with default state
|
||||
* @param locked Default state
|
||||
*/
|
||||
public Lock(boolean locked) {
|
||||
this.locked = locked;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The time left
|
||||
*/
|
||||
public long timeLeft() {
|
||||
updateLocked();
|
||||
return locked ? (ts + t) - new Date().getTime() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate timeout
|
||||
* @param timeout Timeout to override time
|
||||
* @return Time left
|
||||
*/
|
||||
protected int checkTime(int timeout) {
|
||||
return locked ? checkNegative(Math.min((int) (t - (new Date().getTime() - ts ) ), timeout <= 0 ? Integer.MAX_VALUE : timeout), timeout) : timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns alt if i is negative, otherwise i
|
||||
* @param i The integer to check
|
||||
* @param alt The alternative for if its negative
|
||||
* @return The checked or overridden value
|
||||
*/
|
||||
protected int checkNegative(int i, int alt) {
|
||||
if(i <= 0)
|
||||
return alt;
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is still locked?
|
||||
*/
|
||||
protected void updateLocked() {
|
||||
if(new Date().getTime() - ts >= t && ts != 0)
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until unlocked, either by a timer or manually
|
||||
*/
|
||||
public void waitHere() {
|
||||
updateLocked();
|
||||
if(locked) {
|
||||
try {
|
||||
locker.lockHere(checkTime(0));
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
updateLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until unlocked, either by a timer, manually, or when it waited for timeout
|
||||
* @param timeout Timeout
|
||||
*/
|
||||
public void waitHere(int timeout) {
|
||||
updateLocked();
|
||||
if(locked) {
|
||||
try {
|
||||
locker.lockHere(checkTime(timeout));
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
updateLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock manually
|
||||
*/
|
||||
public synchronized void unlock() {
|
||||
locker.unlock();
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock until manually unlocked
|
||||
*/
|
||||
public synchronized void lock() {
|
||||
t = 0;
|
||||
ts = 0;
|
||||
locked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock for a specific amount of time. Timer is passive.
|
||||
* @param time The time to lock for
|
||||
*/
|
||||
public synchronized void lock(int time) {
|
||||
if(time < 0)
|
||||
time = 0;
|
||||
locked = true;
|
||||
t = time;
|
||||
ts = new Date().getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return If the lock is locked
|
||||
*/
|
||||
public synchronized boolean isLocked() {
|
||||
updateLocked();
|
||||
return locked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize multiple threads on this lock
|
||||
* @param amount The amount of threads to synchronize
|
||||
*/
|
||||
public void synchronize(int amount) {
|
||||
this.locked = true;
|
||||
if(waiterLocker == null)
|
||||
waiterLocker = new boolean[amount];
|
||||
int i = waiting.get();
|
||||
waiting.getAndIncrement();
|
||||
locker.unlock();
|
||||
while (amount > waiting.get()) {
|
||||
try {
|
||||
locker.lockHere();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
locker.unlock();
|
||||
boolean b;
|
||||
waiterLocker[i] = true;
|
||||
b = true;
|
||||
try {
|
||||
while (b) {
|
||||
b = false;
|
||||
for (int j = 0 ; j < waiterLocker.length ; j++) {
|
||||
if (!waiterLocker[j]) {
|
||||
b = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) { }
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
waiting.getAndDecrement();
|
||||
waiterLocker = null;
|
||||
this.locked = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher.util.security;
|
||||
|
||||
import org.baseband.launcher.launch.Loader;
|
||||
|
||||
import java.security.Permission;
|
||||
|
||||
public class BaseBandSecurityManager extends SecurityManager {
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission permission) {
|
||||
String permissionName = (permission.getName() != null) ? permission.getName() : "null";
|
||||
|
||||
if (permissionName.equals("setSecurityManager")) {
|
||||
Loader.exit();
|
||||
}
|
||||
|
||||
if (permissionName.startsWith("accessClassInPackage.com.baseband")) {
|
||||
Class<?>[] classContext = this.getClassContext();
|
||||
String callerClassName = (classContext.length > 4) ? classContext[4].getName() : null;
|
||||
String parentClassName = (classContext.length > 5) ? classContext[5].getName() : null;
|
||||
|
||||
if (callerClassName != null && !callerClassName.startsWith("com.baseband.")) {
|
||||
if (parentClassName == null || !parentClassName.startsWith("com.baseband.")) {
|
||||
Loader.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission b, Object a) {
|
||||
checkPermission(b);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,12 @@
|
|||
package org.baseband.launcher.util;
|
||||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
package org.baseband.launcher.util.security;
|
||||
|
||||
import org.baseband.launcher.classloader.CustomClassloader;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -11,11 +19,20 @@ import java.util.Vector;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class PermissionManager {
|
||||
|
||||
public static boolean checkMayAccessClasses(boolean checkCallerIsCL) {
|
||||
|
||||
if(!(System.getSecurityManager() instanceof BaseBandSecurityManager)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StackTraceElement[] st = Thread.currentThread().getStackTrace();
|
||||
|
||||
|
||||
|
||||
|
||||
Set<ClassLoader> uniqueClassLoaders = Thread.getAllStackTraces().keySet().stream()
|
||||
.map(thread -> thread.getContextClassLoader())
|
||||
.map(Thread::getContextClassLoader)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
|
@ -1,18 +1,22 @@
|
|||
package org.baseband.launcher.util;
|
||||
/*
|
||||
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
|
||||
*
|
||||
* Unauthorized copying of this file via any medium is Strictly Prohibited.
|
||||
*/
|
||||
|
||||
import tudbut.obj.DoubleTypedObject;
|
||||
import tudbut.tools.Lock;
|
||||
package org.baseband.launcher.util.security;
|
||||
|
||||
import org.baseband.launcher.util.Lock;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
// Keeps some data as safe as possible, unable to be accessed even by reflection
|
||||
public class DataKeeper<T> {
|
||||
public class SecureContainer<T> {
|
||||
public static boolean forgetAll = false;
|
||||
|
||||
|
||||
|
@ -20,9 +24,9 @@ public class DataKeeper<T> {
|
|||
private final boolean checkCallerIsCL;
|
||||
private final Lock lock = new Lock(true);
|
||||
private final Queue<DoubleTypedObject<Consumer<Accessor<T>>, Lock>> nextFunctionToRun = new LinkedList<>();
|
||||
Thread keeper = new Thread(this::keep, "DataKeeper"); { keeper.start(); }
|
||||
Thread keeper = new Thread(this::keep, "SecureContainer"); { keeper.start(); }
|
||||
|
||||
public DataKeeper(T toKeep, boolean checkCallerIsCL) {
|
||||
public SecureContainer(T toKeep, boolean checkCallerIsCL) {
|
||||
dataInsertion = () -> toKeep;
|
||||
this.checkCallerIsCL = checkCallerIsCL;
|
||||
lock.unlock();
|
||||
|
@ -62,6 +66,26 @@ public class DataKeeper<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public class DoubleTypedObject<O, T> {
|
||||
public O o;
|
||||
public T t;
|
||||
|
||||
public DoubleTypedObject(O o, T t) {
|
||||
this.o = o;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o1) {
|
||||
if (this == o1) return true;
|
||||
if (!(o1 instanceof DoubleTypedObject)) return false;
|
||||
DoubleTypedObject<?, ?> that = (DoubleTypedObject<?, ?>) o1;
|
||||
return Objects.equals(o, that.o) && Objects.equals(t, that.t);
|
||||
}
|
||||
}
|
||||
|
||||
// A very last, third layer of protection, not actually that necessary.
|
||||
public static class Accessor<T> {
|
||||
// The accessor will only ever be in local variables, so it does
|
Loading…
Add table
Reference in a new issue