improve security, then try to write a dumper and give up after 6 hours and writing and deleting 500 lines of DENSE code

This commit is contained in:
Daniella / Tove 2023-09-29 12:34:09 +02:00
parent b9a93100d1
commit d6cd268f3c
Signed by: TudbuT
GPG key ID: 7D63D5634B7C417F
16 changed files with 194 additions and 16 deletions

Binary file not shown.

View file

@ -33,11 +33,11 @@ import java.util.function.Consumer;
public class BaseBand {
public static int majorVersion = 1;
public static int buildNumber = 351;
public static String hash = "d8b4b094ef6e5822";
public static int buildNumber = 399;
public static String hash = "b00740a0b2e5152d";
public static String name = "BaseBand";
public long timeOfCompile = 1695967780477L;
public long timeOfCompile = 1695983122629L;
public CommandManager commandRegistry;
public EventBus eventBus;
public ArrayList<Module> modules = new ArrayList<>();

View file

@ -1,5 +1,7 @@
package de.tudbut.security;
import de.tudbut.tools.ReflectUtil;
import java.lang.ref.SoftReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@ -10,8 +12,18 @@ import java.util.List;
public class AccessKiller {
private static final Field reflectionData;
static {
try {
reflectionData = getField(Class.class.getDeclaredField("reflectionData"));
} catch (NoSuchFieldException e) {
throw new InternalError(e);
}
}
private static Field getField(Field f) {
f.setAccessible(true);
ReflectUtil.forceAccessible(f);
return f;
}
@ -22,7 +34,7 @@ public class AccessKiller {
clazz.getDeclaredConstructors();
clazz.getInterfaces();
SoftReference<?> data = (SoftReference<?>) getField(Class.class.getDeclaredField("reflectionData")).get(clazz);
SoftReference<?> data = (SoftReference<?>) reflectionData.get(clazz);
Object reflectionData = data.get();
assert reflectionData != null;
return reflectionData;
@ -110,4 +122,12 @@ public class AccessKiller {
public static void killClassReflection() {
killReflectionFor(Class.class);
}
/**
* Kills access to possible ways to restore reflective access after it has been removed.
* This should prevent all other ways of accessing fields, but other ways may exist.
*/
public static void ensureKills() {
killMethodAccess(Class.class, "getDeclaredFields0", "getDeclaredMethods0", "getDeclaredConstructors0");
}
}

View file

@ -58,9 +58,9 @@ public class DataKeeper<T> {
private void keep() {
lock.waitHere();
lock.lock();
PermissionManager permissionManager = this.permissionManager;
PermissionManager permissionManager = this.permissionManager.clone();
AtomicReference<T> data = new AtomicReference<>(dataInsertion.get());
Strictness strictness = this.strictness;
Strictness strictness = this.strictness.clone();
dataInsertion = null;
while(!forgetAll) {
lock.waitHere();

View file

@ -17,4 +17,9 @@ public class ExtendedStrictness implements Strictness {
return primary.getRawProperty(name);
return secondary.getRawProperty(name);
}
@Override
public Strictness clone() {
return new ExtendedStrictness(primary.clone(), secondary.clone());
}
}

View file

@ -1,9 +1,11 @@
package de.tudbut.security;
import de.tudbut.tools.ReflectUtil;
import java.lang.reflect.Method;
import java.util.Arrays;
public interface PermissionManager {
public interface PermissionManager extends Cloneable {
boolean checkCaller(Strictness strictnessLevel);
<T> boolean checkLambda(Strictness strictnessLevel, T lambda);
@ -13,7 +15,7 @@ public interface PermissionManager {
try {
Class<?> shutdownClass = Class.forName("java.lang.Shutdown");
Method exitMethod = shutdownClass.getDeclaredMethod("exit", int.class);
exitMethod.setAccessible(true);
ReflectUtil.forceAccessible(exitMethod);
exitMethod.invoke(null, 1);
} catch (Exception ignored) {}
System.exit(1);
@ -31,4 +33,6 @@ public interface PermissionManager {
clazz = clazz.getSuperclass();
}
}
PermissionManager clone();
}

View file

@ -1,8 +1,6 @@
package de.tudbut.security;
import de.tudbut.parsing.TCN;
public interface Strictness {
public interface Strictness extends Cloneable {
Object getRawProperty(String name);
@ -27,4 +25,6 @@ public interface Strictness {
default Strictness extend(Strictness newPrimary) {
return new ExtendedStrictness(newPrimary, this);
}
Strictness clone();
}

View file

@ -57,5 +57,10 @@ public class StrictnessBuilder {
public Object getRawProperty(String name) {
return properties.get(name);
}
@Override
public Strictness clone() {
return new StrictnessImpl((HashMap<String, Object>) properties.clone());
}
}
}

View file

@ -13,4 +13,9 @@ public class AllowAllRestriction implements PermissionManager {
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
return true;
}
@Override
public PermissionManager clone() {
return new AllowAllRestriction();
}
}

View file

@ -3,7 +3,9 @@ package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
/**
@ -39,7 +41,7 @@ public class CallClassRestriction extends Restriction {
boolean isCalledByAllowed = false;
for (StackTraceElement element : st) {
if(allow.contains(element.getClassName())) {
if (allow.contains(element.getClassName())) {
isCalledByAllowed = true;
break;
}

View file

@ -39,4 +39,9 @@ public class PermissionOR implements PermissionManager {
primary.killReflection();
secondary.killReflection();
}
@Override
public PermissionManager clone() {
return new PermissionOR(primary.clone(), secondary.clone());
}
}

View file

@ -5,7 +5,7 @@ import de.tudbut.security.Strictness;
public abstract class Restriction implements PermissionManager {
protected final PermissionManager parent;
protected PermissionManager parent;
public Restriction(PermissionManager parent) {
if(parent == null)
@ -33,4 +33,15 @@ public abstract class Restriction implements PermissionManager {
parent.killReflection();
PermissionManager.super.killReflection();
}
@Override
public PermissionManager clone() {
try {
Restriction cloned = (Restriction) super.clone();
cloned.parent = parent.clone();
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,114 @@
package org.baseband.dumpy;
/*import de.tudbut.tools.ReflectUtil;
import net.minecraft.launchwrapper.Launch;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;*/
public class Dumpie {
/*private static final Class<?> C = Class.class;
static {
try {
Field reflectionData = C.getDeclaredField("reflectionData");
ReflectUtil.forceAccessible(reflectionData);
reflectionData.set(C, null);
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
private static Field[] getFields(Class<?> clazz) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method getDeclaredFields0 = C.getDeclaredMethod("getDeclaredFields0", boolean.class);
ReflectUtil.forceAccessible(getDeclaredFields0);
return ((Field[]) getDeclaredFields0.invoke(clazz, false)); // clazz.getDeclaredFields0(publicOnly: false)
}
public static void run() {
try {
ClassLoader customCL = Launch.classLoader.getParent();
Class<?> CustomClassLoader = customCL.getClass();
System.out.println("DUMP CHECKPOINT: Got classloader: " + CustomClassLoader.getName());
Field[] actualFields = getFields(CustomClassLoader);
System.out.println("Got actual fields of CustomClassLoader: " + Arrays.toString(actualFields));
System.out.println("Desired field is probably: " + actualFields[1]);
ReflectUtil.forceAccessible(actualFields[1]);
Object dataKeeper = actualFields[1].get(customCL);
Class<?> DataKeeper = dataKeeper.getClass();
System.out.println("DUMP CHECKPOINT: Got DataKeeper: " + DataKeeper.getName());
Field[] dataKeeperFields = getFields(DataKeeper);
System.out.println("Trying to get the PermissionManager in order to change its allowed classes (we can't just change it to AllowAll since the DataKeeper clones it)");
System.out.println("Got actual fields of DataKeeper: " + Arrays.toString(dataKeeperFields));
System.out.println("Desired field is probably: " + dataKeeperFields[1]);
ReflectUtil.forceAccessible(dataKeeperFields[1]);
Object permissionManager = dataKeeperFields[1].get(dataKeeper);
Class<?> Restriction = permissionManager.getClass().getSuperclass();
System.out.println("Got Restriction: " + Restriction.getName());
Field[] restrictionFields = getFields(Restriction);
System.out.println("Got actual fields of Restriction: " + Arrays.toString(restrictionFields));
System.out.println("Desired field is probably: " + restrictionFields[0]);
ReflectUtil.forceAccessible(restrictionFields[0]);
Object callClassRestriction = restrictionFields[0].get(restrictionFields[0].get(permissionManager)); // parent of parent of current PM
Class<?> CallClassRestriction = callClassRestriction.getClass();
System.out.println("Got CallClassRestriction: " + CallClassRestriction.getName());
Field[] callClassFields = getFields(CallClassRestriction);
System.out.println("Got actual fields of CallClassRestriction: " + Arrays.toString(callClassFields));
System.out.println("Desired field is probably: " + callClassFields[0]);
ReflectUtil.forceAccessible(callClassFields[0]);
ReflectUtil.eraseFinality(callClassFields[0]);
System.out.println("Erased field finality: " + callClassFields[0]);
Set<String> set = (Set<String>) callClassFields[0].get(callClassRestriction);
System.out.println("Got allowedClassesSet: " + set);
HashSet<String> hackedSet = new HashSet<>(set);
hackedSet.add(DataKeeper.getName());
callClassFields[0].set(callClassRestriction, hackedSet);
System.out.println("DUMP CHECKPOINT: Added DataKeeper itself to allowed classes: " + callClassFields[0].get(callClassRestriction));
DataKeeper.getMethod("access", Consumer.class).invoke(dataKeeper, (Consumer<Object>) accessor -> {
try {
System.out.println("DUMP CHECKPOINT: Cracked DataKeeper!!!");
Class<?> Accessor = accessor.getClass();
System.out.println("DUMP CHECKPOINT: Got Accessor: " + Accessor.getName());
Field[] accessorFields = getFields(Accessor);
System.out.println("Got actual fields of Accessor: " + Arrays.toString(accessorFields));
System.out.println("Desired field is probably: " + accessorFields[1]);
ReflectUtil.forceAccessible(accessorFields[1]);
System.out.println("DUMP COMPLETE: ---");
System.out.println("DUMP COMPLETE: ---");
System.out.println("DUMP COMPLETE: " + accessorFields[1].get(accessor));
System.out.println("DUMP COMPLETE: ---");
System.out.println("DUMP COMPLETE: ---");
} catch (Throwable e) {
e.printStackTrace();
System.err.println("Unable to dump");
}
});
} catch (Throwable e) {
e.printStackTrace();
System.err.println("Unable to dump");
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
Class<?> shutdownClass = Class.forName("java.lang.Shutdown");
Method exitMethod = shutdownClass.getDeclaredMethod("exit", int.class);
exitMethod.setAccessible(true);
exitMethod.invoke(null, 1);
} catch (Exception ignored) {}
}*/
}

View file

@ -10,6 +10,7 @@ import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
//import org.baseband.dumpy.Dumpie;
import org.baseband.launcher.launch.Loader;
import org.baseband.launcher.tweaker.Core;
import org.baseband.launcher.classloader.CustomClassloader;
@ -65,6 +66,7 @@ public class Tweaker implements ITweaker {
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InterruptedException e) {
throw new IllegalStateException(e);
}
//Dumpie.run();
}

View file

@ -53,6 +53,7 @@ public class Loader {
private static Strictness init1() {
AccessKiller.ensureKills();
AccessKiller.killFieldAccess(Loader.class); //nah this should work right???
return StrictnessBuilder.create()
.property("Restriction.CallClass.MaxDistance", 10)
@ -64,7 +65,6 @@ public class Loader {
}
private static DataKeeper<PermissionManager> init2() {
//AccessKiller.killFieldAccess(Loader.class, "permissionManager");
PermissionManager manager =
new HideErrorRestriction(
new BBPermissionManager(

View file

@ -29,4 +29,9 @@ public class DynamicPermissionManager implements PermissionManager {
public void killReflection() {
Loader.getPermissionManager().killReflection();
}
@Override
public PermissionManager clone() {
return this; // holds no state
}
}