This commit is contained in:
Jess H 2024-03-19 19:26:52 +00:00
parent 105794d197
commit 9870a0e6ab
58 changed files with 388 additions and 4807 deletions

View file

@ -37,11 +37,11 @@ import java.util.function.Consumer;
public class BaseBand {
public static int majorVersion = 1;
public static int buildNumber = 487;
public static String hash = "36c1edbaa0c2f6b3";
public static int buildNumber = 497;
public static String hash = "06b9a1db4ba97794";
public static String name = "BaseBand";
public long timeOfCompile = 1700171942984L;
public long timeOfCompile = 1710629129384L;
public CommandManager commandRegistry;
public EventBus eventBus;
public ArrayList<Module> modules = new ArrayList<>();

View file

@ -3,7 +3,7 @@
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package org.baseband.installer;
package old.baseband.installer;
import javax.swing.*;

View file

@ -3,15 +3,14 @@
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package org.baseband.installer;
package old.baseband.installer;
import org.baseband.installer.util.minecraft.MinecraftFiles;
import old.baseband.installer.util.minecraft.MinecraftFiles;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
@ -19,7 +18,6 @@ import java.awt.event.ItemListener;
import java.io.*;
import java.net.Socket;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.UUID;
@ -29,7 +27,7 @@ public class InstallerApp {
private JFrame installerFrame;
public static String username;
public static String password;
public static Key keyinstance;
public static old.baseband.installer.Key keyinstance;
public InstallerApp() {
try {
@ -134,7 +132,7 @@ public class InstallerApp {
//We need this to make sure we're not being poked at
String ticket = getRandomTicket();
keyinstance = new Key(ticket);
keyinstance = new old.baseband.installer.Key(ticket);
byte[] encryptedTicket = aesE.doFinal(ticket.getBytes());
outputF.writeInt(encryptedTicket.length);
outputF.write(encryptedTicket);
@ -294,7 +292,7 @@ public class InstallerApp {
//We need this to make sure we're not being poked at
String ticket = getRandomTicket();
keyinstance = new Key(ticket);
keyinstance = new old.baseband.installer.Key(ticket);
byte[] encryptedTicket = aesE.doFinal(ticket.getBytes());
outputF.writeInt(encryptedTicket.length);
outputF.write(encryptedTicket);

View file

@ -3,7 +3,7 @@
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package org.baseband.installer;
package old.baseband.installer;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

View file

@ -3,7 +3,7 @@
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package org.baseband.installer.util.minecraft;
package old.baseband.installer.util.minecraft;
import java.io.File;

View file

@ -70,6 +70,10 @@ dependencies {
exclude module: 'log4j-core'
}
jarLibs(fileTree(dir: "lib", include: "*.jar"));
jarLibs(group: 'com.github.oshi', name: 'oshi-core', version: '6.5.0');
annotationProcessor('org.spongepowered:mixin:0.8.5:processor') {
exclude module: 'gson'
}

BIN
Loader/lib/TuddyLIB.jar Normal file

Binary file not shown.

View file

@ -1,66 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.io;
import de.tudbut.tools.ReflectUtil;
import java.io.*;
public class CLSPrintWriter extends PrintWriter {
public String customLineSeparator = "\n";
public CLSPrintWriter(Writer writer) {
super(writer);
}
public CLSPrintWriter(Writer writer, boolean b) {
super(writer, b);
}
public CLSPrintWriter(OutputStream outputStream) {
super(outputStream);
}
public CLSPrintWriter(OutputStream outputStream, boolean b) {
super(outputStream, b);
}
public CLSPrintWriter(String s) throws FileNotFoundException {
super(s);
}
public CLSPrintWriter(String s, String s1) throws FileNotFoundException, UnsupportedEncodingException {
super(s, s1);
}
public CLSPrintWriter(File file) throws FileNotFoundException {
super(file);
}
public CLSPrintWriter(File file, String s) throws FileNotFoundException, UnsupportedEncodingException {
super(file, s);
}
@Override
public void println() {
try {
synchronized(this.lock) {
if (this.out == null) {
throw new IOException("Stream closed");
}
this.out.write(customLineSeparator);
if (ReflectUtil.getPrivateFieldByTypeIndex(PrintWriter.class, this, boolean.class, 0)) {
this.out.flush();
}
}
} catch (InterruptedIOException var4) {
Thread.currentThread().interrupt();
} catch (IOException var5) {
ReflectUtil.setPrivateFieldByTypeIndex(PrintWriter.class, this, boolean.class, 1, true);
}
}
}

View file

@ -1,143 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.io;
import de.tudbut.obj.CarrierException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Helper for reading {@link java.io.InputStream}
*/
public class StreamReader {
/**
* Buffer size for reading. Directly affects speed.
*/
public static int BUFFER_SIZE = 4096;
/**
* The stream to read from
*/
public final InputStream inputStream;
private boolean endReached = false;
/**
* Constructs a StreamReader for an InputStream
* @param stream The stream to read
*/
public StreamReader(InputStream stream) {
this.inputStream = stream;
}
/**
* Reads a byte from the input stream. Unaffected by {@link StreamReader#BUFFER_SIZE}
* @return read byte
* @throws IOException Inherited from {@link InputStream#read}
* @throws ArrayIndexOutOfBoundsException When the stream end was reached
*/
public byte readNextByte() throws IOException, ArrayIndexOutOfBoundsException {
int got = inputStream.read();
if (got < 0) {
endReached = true;
throw new ArrayIndexOutOfBoundsException("Stream end reached");
}
return (byte) got;
}
/**
* Reads a byte from the input stream. Unaffected by {@link StreamReader#BUFFER_SIZE}.
* Byte is converted to int, being unsigned in the process.
* @return read unsigned bytes
* @throws IOException Inherited from {@link StreamReader#readNextByte()}
* @throws ArrayIndexOutOfBoundsException Inherited from {@link StreamReader#readNextByte()}
*/
public int readNextUnsignedByte() throws IOException, ArrayIndexOutOfBoundsException {
return Byte.toUnsignedInt(readNextByte());
}
/**
* Reads bytes from the input stream until end is reached. Affected by {@link StreamReader#BUFFER_SIZE}.
* @return read bytes
* @throws IOException Inherited from {@link StreamReader#readNextByte()}
*/
public byte[] readAllAsBytes() throws IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte[] currentBytes = new byte[BUFFER_SIZE];
int len;
try {
while ((len = inputStream.read(currentBytes)) > 0) {
bytes.write(currentBytes, 0, len);
}
} catch (IOException e) {
throw new CarrierException(e, bytes.toByteArray());
}
return bytes.toByteArray();
}
/**
* Reads all bytes in the stream and converts them to a char[]
* @return {@link Character} array (native)
* @throws IOException Inherited from {@link StreamReader#readAllAsBytes()}
*/
public char[] readAllAsChars() throws IOException {
return new String(readAllAsBytes()).toCharArray();
}
/**
* Reads all bytes in the stream and converts them to a char[]
* @param encoding The encoding to use for conversion
* @return {@link Character} array (native)
* @throws IOException Inherited from {@link StreamReader#readAllAsBytes()}
*/
public char[] readAllAsChars(String encoding) throws IOException {
return new String(readAllAsBytes(), encoding).toCharArray();
}
/**
* Same as {@link StreamReader#readAllAsChars()}, but returns a string instead.
* @return The string
* @throws IOException Inherited from {@link StreamReader#readAllAsBytes()}
*/
public String readAllAsString() throws IOException {
return new String(readAllAsBytes());
}
/**
* Returns all lines in the file. All line ending are supported (\r\n, \n, \r).
* @return The lines
* @throws IOException Inherited from {@link StreamReader#readAllAsBytes()}
*/
public String[] readAllAsLines() throws IOException {
return new String(readAllAsBytes()).replaceAll("\r\n", "\n").replaceAll("\r", "\n").split("\n");
}
/**
* Same as {@link StreamReader#readAllAsChars()}, but returns a string instead.
* @param encoding The encoding to use
* @return The string
* @throws IOException Inherited from {@link StreamReader#readAllAsBytes()}
*/
public String readAllAsString(String encoding) throws IOException {
return new String(readAllAsBytes(), encoding);
}
/**
* Returns all lines in the file. All line ending are supported (\r\n, \n, \r).
* @param encoding The encoding to use
* @return The lines
* @throws IOException Inherited from {@link StreamReader#readAllAsBytes()}
*/
public String[] readAllAsLines(String encoding) throws IOException {
return new String(readAllAsBytes(), encoding).replaceAll("\r\n", "\n").replaceAll("\r", "\n").split("\n");
}
}

View file

@ -1,16 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.obj;
public class CarrierException extends RuntimeException {
public final Object carried;
public CarrierException(Exception e, Object o) {
super(e);
carried = o;
}
}

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.obj;
import de.tudbut.tools.ReflectUtil;
import java.util.Objects;
public class DoubleTypedObject<O, T> implements Cloneable {
public O o;
public T t;
public DoubleTypedObject(O o, T t) {
this.o = o;
this.t = t;
}
public DoubleTypedObject() {
}
@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);
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public DoubleTypedObject<O, T> clone() {
return new DoubleTypedObject<>(ReflectUtil.forceClone(o), ReflectUtil.forceClone(t));
}
}

View file

@ -1,204 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.obj;
import de.tudbut.tools.Retriever;
import java.util.*;
public class TLMap<K, V> {
protected Binding<K, V> binding = new Binding<>();
public static TLMap<String, String> stringToMap(String mapStringParsable) {
TLMap<String, String> map = new TLMap<>();
String[] splitTiles = mapStringParsable.split(";");
for (int i = 0; i < splitTiles.length; i++) {
String tile = splitTiles[i];
String[] splitTile = tile.split(":");
if (tile.contains(":")) {
if (splitTile.length == 2)
map.set(
splitTile[0].replaceAll("%I", ":").replaceAll("%B", ";").replaceAll("%P", "%"),
splitTile[1].equals("%N") ? null : splitTile[1].replaceAll("%I", ":").replaceAll("%B", ";").replaceAll("%P", "%")
);
else
map.set(splitTile[0].replaceAll("%I", ":").replaceAll("%B", ";").replaceAll("%P", "%"), "");
}
}
return map;
}
public static String mapToString(TLMap<String, String> map) {
StringBuilder r = new StringBuilder();
for (String key : map.keys().toArray(new String[0])) {
r
.append(key.replaceAll("%", "%P").replaceAll(";", "%B").replaceAll(":", "%I"))
.append(":")
.append(map.get(key) == null ? "%N" : map.get(key).replaceAll("%", "%P").replaceAll(";", "%B").replaceAll(":", "%I"))
.append(";")
;
}
return r.toString();
}
public void set(K key, V value) {
binding.set(key, value);
}
public void setIfNull(K key, V value) {
if(binding.get(key) == null) {
binding.set(key, value);
}
}
public V get(K key) {
return binding.get(key);
}
public V get(K key, V def) {
V v = binding.get(key);
return v == null ? def : v;
}
public V get(K key, Retriever<V> def) {
V v = binding.get(key);
return v == null ? def.retrieve() : v;
}
public Set<K> keys() {
return binding.keys();
}
public int size() {
return binding.size();
}
public Set<V> values() {
return binding.values();
}
public ArrayList<Entry<K, V>> entries() {
return binding.entries();
}
public TLMap<V, K> flip() {
TLMap<V, K> map = new TLMap<>();
map.binding = binding.flip();
return map;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TLMap<?, ?> tlMap = (TLMap<?, ?>) o;
return tlMap.binding.entries.equals(binding.entries);
}
protected static class Binding<K, V> {
protected ArrayList<Entry<K, V>> entries = new ArrayList<>();
protected void set(K key, V value) {
boolean exists = false;
for (int i = 0; i < entries.size(); i++) {
Entry<K, V> entry = entries.get(i);
if (key == entry.key || entry.key.equals(key)) {
exists = true;
if(value == null) {
entries.remove(i);
break;
}
entry.val = value;
}
}
if(!exists && value != null && key != null) {
this.entries.add(new Entry<>(key, value));
}
}
protected V get(K key) {
ArrayList<Entry<K, V>> entries = (ArrayList<Entry<K, V>>) this.entries.clone();
for (Entry<K, V> entry : entries) {
if (key == entry.key || entry.key.equals(key))
return entry.val;
}
return null;
}
protected Set<K> keys() {
Set<K> keys = new LinkedHashSet<>();
for (int i = 0; i < entries.size(); i++) {
keys.add(entries.get(i).key);
}
return keys;
}
protected Set<V> values() {
Set<V> vals = new LinkedHashSet<>();
for (int i = 0; i < entries.size(); i++) {
vals.add(entries.get(i).val);
}
return vals;
}
protected ArrayList<Entry<K, V>> entries() {
ArrayList<Entry<K, V>> vals = new ArrayList<>();
vals.addAll(entries);
return vals;
}
protected Binding<V, K> flip() {
Binding<V, K> binding = new Binding<>();
for (int i = 0 ; i < entries.size() ; i++) {
Entry<K, V> entry = entries.get(i);
binding.entries.add(new Entry<>(entry.val, entry.key));
}
return binding;
}
public int size() {
return entries.size();
}
}
public static class Entry<K, V> {
public K key;
public V val;
protected Entry() {
}
protected Entry(K key, V val) {
this.key = key;
this.val = val;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Entry<?, ?> entry = (Entry<?, ?>) o;
if (!Objects.equals(key, entry.key)) return false;
return Objects.equals(val, entry.val);
}
}
@Override
public TLMap<K, V> clone() {
TLMap<K, V> n = new TLMap<>();
Object[] keys = keys().toArray();
Object[] vals = values().toArray();
for (int i = 0, arrayLength = keys.length ; i < arrayLength ; i++) {
Object key = keys[i];
n.set((K)key, (V)vals[i]);
}
return n;
}
}

View file

@ -1,429 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.parsing;
import de.tudbut.tools.Stack;
import de.tudbut.tools.StringTools;
import java.util.ArrayList;
/**
* Interconverting JSON and TCN
*/
public class JSON {
/**
* Converts a JSON string to a TCN object
* @param string The JSON string, supports most compact and readable formats
* @return The parsed TCN object
* @throws JSONFormatException If a format error is found
*/
public static TCN read(String string) throws JSONFormatException {
while (string.startsWith(" ")) {
string = string.substring(1);
}
if(!string.startsWith("{") && !string.startsWith("[")) {
throw new JSONFormatException("Expected: { or [ at 0 (String is '" + string + "')");
}
boolean array = string.startsWith("[");
TCN tcn = new TCN("JSON", array);
boolean escape = false;
int pos = 1;
char[] a = string.toCharArray();
char c = a[pos];
int arrayPos = 0;
boolean inString = false;
boolean startString = false;
StringBuilder theString = new StringBuilder();
boolean kv = false;
String key = "";
boolean inStringKV = false;
boolean inObjectKV = false;
TCN sub = null;
try {
while (inString || (c != '}' && c != ']')) {
if(array) {
kv = true;
}
if (startString) {
inString = true;
startString = false;
}
if (c == '\\') {
escape = !escape;
}
if (!escape && c == '"') {
startString = !inString;
if (startString) {
if (kv)
inStringKV = true;
theString = new StringBuilder();
}
else {
inString = false;
if (!kv) { // Key
key = theString.toString();
}
}
}
if (inString) {
if (!escape)
theString.append(c);
else {
a:
{
// Make escapes work
if (c == 'n')
theString.append('\n');
if (c == 'r')
theString.append('\r');
if (c == 'u') {
String e = "";
e += c = a[++pos];
e += c = a[++pos];
e += c = a[++pos];
e += c = a[++pos];
theString.append((char) Integer.parseInt(e, 16));
break a;
}
if (c == '0') {
String e = "";
e += c = a[pos];
e += c = a[++pos];
e += c = a[++pos];
theString.append((char) Integer.parseInt(e, 8));
break a;
}
if (c == '1') {
String e = "";
e += c = a[pos];
e += c = a[++pos];
e += c = a[++pos];
theString.append((char) Integer.parseInt(e, 8));
break a;
}
if (c == '2') {
String e = "";
e += c = a[pos];
e += c = a[++pos];
e += c = a[++pos];
theString.append((char) Integer.parseInt(e, 8));
break a;
}
if (c == '3') {
String e = "";
e += c = a[pos];
e += c = a[++pos];
e += c = a[++pos];
theString.append((char) Integer.parseInt(e, 8));
break a;
}
if (c == 'x') {
String e = "";
e += c = a[++pos];
e += c = a[++pos];
theString.append((char) Integer.parseInt(e, 16));
break a;
}
if (c == '"') {
theString.append("\"");
}
}
}
}
// Booleans, ints, etc
else if (kv && !startString && !inStringKV && c != ',' && (Character.isLetterOrDigit(c) || c == '.' || c == '-')) {
theString.append(c);
}
// SubObjects
if (!inString && c == '{') {
inObjectKV = true;
escape = false;
theString = new StringBuilder("{");
int layer = 1;
while (layer > 0) {
c = a[++pos];
theString.append(c);
if(c == '{' && !inString) {
layer++;
}
if(c == '}' && !inString) {
layer--;
}
if (c == '\\') {
escape = !escape;
}
if (c == '\"' && !escape) {
inString = !inString;
}
if (c != '\\') {
escape = false;
}
}
theString.append("}");
sub = read(theString.toString());
theString = new StringBuilder();
}
// Arrays
if (!inString && c == '[') {
inObjectKV = true;
escape = false;
theString = new StringBuilder("[");
int layer = 1;
while (layer != 0) {
c = a[++pos];
theString.append(c);
if(c == '[' && !inString) {
layer++;
}
if(c == ']' && !inString) {
layer--;
}
if (c == '\\') {
escape = !escape;
}
if (c == '\"' && !escape) {
inString = !inString;
}
if (c != '\\') {
escape = false;
}
}
theString.append(']');
sub = read(theString.toString());
theString = new StringBuilder();
}
if(array) {
kv = true;
}
// Key vs Value parsing
if (!inString && c == ':') {
theString = new StringBuilder();
if (!kv)
kv = true;
else
throw new JSONFormatException("Unexpected: '" + c + "' at " + pos + " - Should be ','");
}
if (!inString && c == ',') {
if(array)
key = String.valueOf(arrayPos++);
if (inObjectKV) {
tcn.set(key, sub);
} else if(inStringKV || !theString.toString().equals("null")) {
tcn.set(key, theString.toString());
}
inObjectKV = false;
inStringKV = false;
theString = new StringBuilder();
if (kv)
kv = false;
else
throw new JSONFormatException("Unexpected: '" + c + "' at " + pos + " - Should be ':'");
}
if (c != '\\') {
escape = false;
}
c = a[++pos];
}
if(kv) {
if (array)
key = String.valueOf(arrayPos);
if (inObjectKV)
tcn.set(key, sub);
else if(inStringKV || !theString.toString().equals("null"))
tcn.set(key, theString.toString());
}
for (String theKey : tcn.map.keys()) {
TCN.deepConvert(theKey, tcn.get(theKey), tcn);
}
return tcn;
} catch (JSONFormatException e) {
throw e;
} catch (Throwable e) {
throw new JSONFormatException("At " + pos + " in " + string + " (Debug: " + inString + " " + kv + " " + theString + " " + key + " " + array + ")", e);
}
}
private static String indent(boolean b, int i, int il) {
if(b)
return StringTools.multiply(StringTools.multiply(" ", il), i);
else
return "";
}
/**
* Converts a TCN object to a JSON string, uses the most compact form
* @param tcn The TCN to write to JSON
* @return The JSON string
*/
public static String write(TCN tcn) {
return write(tcn, false, false, 0);
}
/**
* Converts a TCN object to a JSON string
* @param tcn The TCN to write to JSON
* @param spaces If the JSON string should have spaces after : and ,
* @return The JSON string
*/
public static String write(TCN tcn, boolean spaces) {
return write(tcn, false, spaces, 0);
}
/**
* Converts a TCN object to a JSON string, uses newlines with selected indent and without spaces
* @param tcn The TCN to write to JSON
* @param indent The indent to use
* @return The JSON string
*/
public static String write(TCN tcn, int indent) {
return write(tcn, true, false, indent);
}
/**
* Converts a TCN object to a JSON string, uses newlines with an indent of 2 and spaces
* @param tcn The TCN to write to JSON
* @return The JSON string
*/
public static String writeReadable(TCN tcn) {
return write(tcn, true, true, 2);
}
/**
* Converts a TCN object to a JSON string, uses newlines with selected indent and spaces
* @param tcn The TCN to write to JSON
* @param indent The indent to use
* @return The JSON string
*/
public static String writeReadable(TCN tcn, int indent) {
return write(tcn, true, true, indent);
}
/**
* Converts a TCN object to a JSON string
* @param tcn The TCN to write to JSON
* @param newlines If the JSON string should have newlines and indents
* @param spaces If the JSON string should have spaces after : and ,
* @param indentLength The indent to use
* @return The JSON string
*/
public static String write(TCN tcn, boolean newlines, boolean spaces, int indentLength) {
StringBuilder s = new StringBuilder();
s.append(tcn.isArray ? "[" : "{").append(newlines ? "\n" : "");
int i = 1;
ArrayList<Stack<String>> paths = new ArrayList<>();
Stack<TCN> tcnStack = new Stack<>();
Stack<String> path = new Stack<>();
tcnStack.add(tcn);
path.add("");
while (tcnStack.size() > 0) {
boolean b = false;
for(String key : tcnStack.peek().map.keys()) {
Object o = tcnStack.peek().map.get(key);
if(o == null)
continue;
String k = key.replaceAll("\\\\", "\\\\\\\\").replaceAll("\n", "\\\\n").replaceAll("\"", "\\\\\"");
if(o.getClass() == TCN.class) {
path.add(key);
if(!paths.contains(path)) {
paths.add(path.clone());
TCN theTCN = tcnStack.peek();
tcnStack.add((TCN) o);
if(theTCN.isArray) {
s.append(indent(newlines, i, indentLength)).append("{").append(newlines ? "\n" : "");
}
else
s.append(indent(newlines, i, indentLength)).append("\"").append(k).append("\":").append(spaces ? " " : "").append("{").append(newlines ? "\n" : "");
b = true;
i++;
} else
path.next();
} else if(o.getClass() == TCNArray.class) {
path.add(key);
if(!paths.contains(path)) {
paths.add(path.clone());
TCN theTCN = tcnStack.peek();
tcnStack.add(((TCNArray) o).toTCN());
if(theTCN.isArray) {
s.append(indent(newlines, i, indentLength)).append("[").append(newlines ? "\n" : "");
}
else
s.append(indent(newlines, i, indentLength)).append("\"").append(k).append("\":").append(spaces ? " " : "").append("[").append(newlines ? "\n" : "");
i++;
b = true;
} else
path.next();
} else if (o instanceof String) {
path.add(key);
if(!paths.contains(path)) {
paths.add(path.clone());
String val = o.toString().replaceAll("\\\\", "\\\\\\\\").replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\"", "\\\\\"");
if(tcnStack.peek().isArray) {
s.append(indent(newlines, i, indentLength)).append("\"").append(val).append("\",").append(spaces ? " " : "").append(newlines ? "\n" : "");
}
else
s.append(indent(newlines, i, indentLength)).append("\"").append(k).append("\":").append(spaces ? " \"" : "\"").append(val).append("\",").append(spaces ? " " : "").append(newlines ? "\n" : "");
b = true;
}
path.next();
}
else {
path.add(key);
if(!paths.contains(path)) {
paths.add(path.clone());
String val = o.toString();
if(tcnStack.peek().isArray) {
s.append(indent(newlines, i, indentLength)).append(val).append(",").append(spaces ? " " : "").append(newlines ? "\n" : "");
}
else
s.append(indent(newlines, i, indentLength)).append("\"").append(k).append("\":").append(spaces ? " " : "").append(val).append(",").append(spaces ? " " : "").append(newlines ? "\n" : "");
b = true;
}
path.next();
}
}
if(!b) {
TCN theTCN = tcnStack.next();
path.next();
i--;
if(theTCN.map.keys().isEmpty()) {
s.append(",").append(spaces ? " " : "");
}
s.delete(s.length() - ((newlines ? 2 : 1) + (spaces ? 1 : 0)), s.length());
s.append(newlines ? "\n" : "").append(indent(newlines, i, indentLength)).append(theTCN.isArray ? "]" : "}").append(",").append(spaces ? " " : "").append(newlines ? "\n" : "");
}
}
s.delete(s.length() - ((newlines ? 2 : 1) + (spaces ? 1 : 0)), s.length());
return s.toString();
}
public static class JSONFormatException extends Exception {
public JSONFormatException(String s, Throwable e) {
super(s, e);
}
public JSONFormatException(String s) {
super(s);
}
}
}

View file

@ -1,518 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.parsing;
import de.tudbut.tools.Tools;
import de.tudbut.obj.DoubleTypedObject;
import de.tudbut.obj.TLMap;
import de.tudbut.tools.Stack;
import de.tudbut.tools.StringTools;
import java.util.*;
/**
* T udbuT<br>
* C onfig<br>
* N otation<br>
*/
public class TCN {
/**
* The map
*/
public TLMap<String, Object> map = new TLMap<>();
public final boolean isArray;
public String type;
/**
* Creates a new, empty TCN
*/
public TCN() {
isArray = false;
this.type = "TCN";
}
TCN(boolean array) {
isArray = array;
this.type = "TCN";
}
public TCN(String type) {
isArray = false;
this.type = type;
}
TCN(String type, boolean array) {
isArray = array;
this.type = type;
}
/**
* Sets something in the map
* @param key Key
* @param o Object, can be a native type, string, or another TCN (or TCNArray)
*/
public void set(String key, Object o) {
/*TLMap<String, Object> map = this.map;
ArrayList<String> path = new ArrayList<>(Arrays.asList(key.split("#")));
while (path.size() > 1) {
map = ((TCN) map.get(path.remove(0))).map;
}
*/
map.set(key, o);
}
public String getString(String key) {
Object o = map.get(key);
if(o != null)
return get(key).toString();
else
return null;
}
public Short getShort(String key) {
Object o = get(key);
if(o != null)
return Short.valueOf(String.valueOf(o));
else
return null;
}
public Integer getInteger(String key) {
Object o = get(key);
if(o != null)
return Integer.valueOf(String.valueOf(o));
else
return null;
}
public Boolean getBoolean(String key) {
Object o = get(key);
if(o != null)
return Boolean.valueOf(String.valueOf(o));
else
return null;
}
public Float getFloat(String key) {
Object o = get(key);
if(o != null)
return Float.valueOf(String.valueOf(o));
else
return null;
}
public Long getLong(String key) {
Object o = get(key);
if(o != null)
return Long.valueOf(String.valueOf(o));
else
return null;
}
public Double getDouble(String key) {
Object o = get(key);
if(o != null)
return Double.valueOf(String.valueOf(o));
else
return null;
}
public TCN getSub(String key) {
Object o = get(key);
if(o != null && o.getClass() == TCN.class)
return (TCN) map.get(key);
else
return null;
}
public TCNArray getArray(String key) {
Object o = get(key);
if(o != null && o.getClass() == TCNArray.class)
return (TCNArray) map.get(key);
else
return null;
}
public Object get(String key) {
TLMap<String, Object> map = this.map;
ArrayList<String> path = new ArrayList<>(Collections.singletonList(key));
while (path.size() > 1) {
map = ((TCN) map.get(path.remove(0))).map;
}
return map.get(path.get(0));
}
/**
* Converts a Map to a TCN
* @param map The map to convert
* @return The converted TCN
*/
public static TCN readMap(Map<String, String> map) {
TCN tcn = new TCN(map.containsKey("TCN%isArray") && Boolean.parseBoolean(map.get("TCN%isArray")));
map.remove("TCN%isArray");
String[] array = map.keySet().toArray(new String[0]);
for (int i = 0, arrayLength = array.length; i < arrayLength; i++) {
String key = array[i];
String s = map.get(key);
if(s.contains(":")) {
tcn.map.set(key, TCN.readMap(Tools.stringToMap(s)));
}
else {
tcn.map.set(key, s.replaceAll("%C", ":").replaceAll("%P", "%"));
}
}
for (String key : tcn.map.keys()) {
deepConvert(key, tcn.get(key), tcn);
}
return tcn;
}
/**
* Converts this TCN object to a Map
* {@link #readMap}
* @return The converted Map
*/
public Map<String, String> toMap() {
Map<String, String> r = new LinkedHashMap<>();
if(isArray)
r.put("TCN%isArray", "true");
String[] array = map.keys().toArray(new String[0]);
for (int i = 0, arrayLength = array.length; i < arrayLength; i++) {
String key = array[i];
Object o = map.get(key);
if(o == null)
continue;
if(o.getClass() == TCN.class) {
r.put(key, Tools.mapToString(((TCN) o).toMap()));
}
else if(o.getClass() == TCNArray.class) {
r.put(key, Tools.mapToString(((TCNArray) o).toMap()));
}
else
r.put(key, o.toString().replaceAll("%", "%P").replaceAll(":", "%C"));
}
return r;
}
/**
* Converts this TCN to a reversible string
* @return The converted string
*/
public String toString() {
if(type.equalsIgnoreCase("TCN")) {
StringBuilder s = new StringBuilder();
int i = 0;
ArrayList<Stack<String>> paths = new ArrayList<>();
Stack<TCN> tcnStack = new Stack<>();
Stack<String> path = new Stack<>();
tcnStack.add(this);
path.add("");
while (tcnStack.size() > 0) {
boolean b = false;
for (String key : tcnStack.peek().map.keys()) {
Object o = tcnStack.peek().map.get(key);
if (o == null)
continue;
String k = key.replaceAll("%", "%P").replaceAll(":", "%C").replaceAll("\n", "%N");
if (k.startsWith(" ")) {
if (!k.equals(" ")) {
k = "%S" + k.substring(1);
} else
k = "%S";
}
if (k.startsWith("#")) {
if (!k.equals("#")) {
k = "%H" + k.substring(1);
} else
k = "%H";
}
if (o.getClass() == TCN.class) {
path.add(key);
if (!paths.contains(path)) {
paths.add(path.clone());
TCN tcn = tcnStack.peek();
tcnStack.add((TCN) o);
String indent = StringTools.multiply(" ", i);
if (tcn.isArray) {
s.append("\n").append(indent).append(";").append(((TCN) o).isArray ? " [\n" : " {\n");
} else
s.append("\n").append(indent).append(k).append(((TCN) o).isArray ? " [\n" : " {\n");
i++;
b = true;
break;
} else
path.next();
} else if (o.getClass() == TCNArray.class) {
path.add(key);
if (!paths.contains(path)) {
paths.add(path.clone());
TCN tcn = tcnStack.peek();
tcnStack.add(((TCNArray) o).toTCN());
String indent = StringTools.multiply(" ", i);
if (tcn.isArray) {
s.append("\n").append(indent).append(";").append(" [\n");
} else
s.append("\n").append(indent).append(k).append(" [\n");
i++;
b = true;
break;
} else
path.next();
} else {
path.add(key);
if (!paths.contains(path)) {
paths.add(path.clone());
String indent = StringTools.multiply(" ", i);
String val = o.toString().replaceAll("%", "%P").replaceAll("\n", "%N");
if (tcnStack.peek().isArray) {
s.append(indent).append("; ").append(val).append("\n");
} else
s.append(indent).append(k).append(": ").append(val).append("\n");
b = true;
}
path.next();
}
}
if (!b) {
TCN tcn = tcnStack.next();
path.next();
i--;
String indent = StringTools.multiply(" ", i);
s.append(indent).append(tcn.isArray ? "]\n\n" : "}\n\n");
}
}
try {
s.setLength(s.length() - "\n#\n\n".length());
s.trimToSize();
} catch (Exception ignored) {
}
return s.toString();
}
else if(type.equalsIgnoreCase("JSON")) {
return JSON.write(this);
}
return "";
}
/**
* Converts a string {@link #toString()} to a TCN object
* @param s The string
* @return The converted TCN
* @throws TCNException If a format error occurs
*/
public static TCN read(String s) throws TCNException {
TCN tcn = new TCN();
Map<DoubleTypedObject<Stack<String>, Stack<Integer>>, String> scanned = deepScan(s);
Set<DoubleTypedObject<Stack<String>, Stack<Integer>>> keys = scanned.keySet();
for (DoubleTypedObject<Stack<String>, Stack<Integer>> path : keys) {
deepPut(path.clone(), tcn, scanned.get(path));
}
for (String key : tcn.map.keys()) {
deepConvert(key, tcn.get(key), tcn);
}
return tcn;
}
/**
* Converts stray arrays to TCNArray objects, recursive.<br>
* <pre>Example:{@code
* for (String key : tcn.map.keys()) {
* deepConvert(key, tcn.get(key), tcn);
* }
* }</pre>
* @param key The key of o
* @param o Any value in a TCN
* @param top The TCN that o is embedded in
*/
public static void deepConvert(String key, Object o, TCN top) {
if(!(o instanceof TCN) && !(o instanceof TCNArray))
return;
TCN tcn;
if(o instanceof TCN) {
tcn = (TCN) o;
}
else
tcn = ((TCNArray) o).toTCN();
for (String theKey : tcn.map.keys()) {
deepConvert(theKey, tcn.get(theKey), tcn);
}
if (tcn.isArray) {
top.set(key, TCNArray.fromTCN(tcn));
}
}
private static void deepPut(DoubleTypedObject<Stack<String>, Stack<Integer>> path, TCN tcn, String value) throws TCNException {
try {
if (path.o.size() == 1) {
tcn.map.set(path.o.next(), value);
}
else {
int arrayPos = path.t.popBottom();
TCN toPut = (TCN) tcn.map.get(path.o.getBottom(), () -> new TCN(arrayPos != -1));
tcn.map.set(path.o.popBottom(), toPut);
deepPut(path, toPut, value);
}
} catch (Exception e) {
throw new TCNException(null, pathToString(path.o) + ": " + value, e);
}
}
private static Map<DoubleTypedObject<Stack<String>, Stack<Integer>>, String> deepScan(String s) throws TCNException {
String[] lines = s.split("\n");
Map<DoubleTypedObject<Stack<String>, Stack<Integer>>, String> map = new LinkedHashMap<>();
Stack<Boolean> array = new Stack<>();
array.add(false);
Stack<Integer> arrayPos = new Stack<>();
Stack<String> path = new Stack<>();
for (int i = 0; i < lines.length; i++) {
try {
String line = removePrefixSpaces(lines[i]);
if (!line.isEmpty() && !line.startsWith("#")) {
if (line.equals("}") || line.equals("]")) {
path.next();
array.next();
arrayPos.next();
}
else if (line.endsWith(" {") && !line.contains(": ")) {
String k = line.split(" \\{")[0].replaceAll("%C", ":").replaceAll("%N", "\n");
if (k.startsWith("%S")) {
if (!k.equals("%S"))
k = " " + k.substring(2);
else
k = " ";
}
if (k.startsWith("%H")) {
if (!k.equals("%H"))
k = "#" + k.substring(2);
else
k = "#";
}
if(!array.peek())
path.add(k.replaceAll("%P", "%"));
else {
path.add(arrayPos.peek() + "");
arrayPos.add(arrayPos.next() + 1);
}
array.add(false);
arrayPos.add(-1);
}
else if (line.endsWith(" [") && !line.contains(": ")) {
String k = line.split(" \\[")[0].replaceAll("%C", ":").replaceAll("%N", "\n");
if (k.startsWith("%S")) {
if (!k.equals("%S"))
k = " " + k.substring(2);
else
k = " ";
}
if (k.startsWith("%H")) {
if (!k.equals("%H"))
k = "#" + k.substring(2);
else
k = "#";
}
if(!array.peek())
path.add(k.replaceAll("%P", "%"));
else {
path.add(arrayPos.peek() + "");
arrayPos.add(arrayPos.next() + 1);
}
array.add(true);
arrayPos.add(0);
}
else {
Stack<String> p = path.clone();
if(array.peek()) {
p.add(String.valueOf(arrayPos.peek()));
if(line.equals(";"))
line = "; ";
map.put(new DoubleTypedObject<>(p, arrayPos.clone()), line.substring(2).replaceAll("%N", "\n").replaceAll("%P", "%"));
arrayPos.add(arrayPos.next() + 1);
}
else {
String rawk = line.split(": ")[0].replaceAll("%C", ":").replaceAll("%N", "\n");
String k = rawk;
if (k.startsWith("%S")) {
if (!k.equals("%S"))
k = " " + k.substring(2);
else
k = " ";
}
if (k.startsWith("%H")) {
if (!k.equals("%H"))
k = "#" + k.substring(2);
else
k = "#";
}
p.add(k.replaceAll("%P", "%"));
map.put(new DoubleTypedObject<>(p, arrayPos.clone()), line.substring(rawk.length() + 2).replaceAll("%N", "\n").replaceAll("%P", "%"));
}
}
}
} catch (Exception e) {
throw new TCNException(i, lines[i], e);
}
}
return map;
}
static String pathToString(Stack<String> path) {
StringBuilder s = new StringBuilder("/");
path = path.clone();
while (path.hasNext()) {
s.append(path.popBottom()).append("/");
}
return s.toString();
}
private static String removePrefixSpaces(String s) {
while (s.startsWith(" "))
s = s.substring(1);
return s;
}
/**
* Creates a new, empty TCN object
* @deprecated Use {@code new} {@link #TCN()}
* @return The new TCN
*/
@Deprecated
public static TCN getEmpty() {
return new TCN();
}
public static class TCNException extends Exception {
public TCNException(Integer line, String lineString, Exception e) {
super("Error in line " + line + " (" + lineString + ")", e);
}
}
}

View file

@ -1,132 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.parsing;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
/**
* TCN-Compatible Arrays
*/
public class TCNArray extends ArrayList<Object> {
/**
* Creates a new, empty TCNArray
*/
public TCNArray() { }
/**
* Creates a new TCNArray from a collection
*/
public TCNArray(Collection<?> collection) {
addAll(collection);
}
public String getString(int key) {
Object o = get(key);
if(o != null)
return o.toString();
else
return null;
}
public Short getShort(int key) {
Object o = get(key);
if(o != null)
return Short.valueOf(String.valueOf(o));
else
return null;
}
public Integer getInteger(int key) {
Object o = get(key);
if(o != null)
return Integer.valueOf(String.valueOf(o));
else
return null;
}
public Boolean getBoolean(int key) {
Object o = get(key);
if(o != null)
return Boolean.valueOf(String.valueOf(o));
else
return null;
}
public Float getFloat(int key) {
Object o = get(key);
if(o != null)
return Float.valueOf(String.valueOf(o));
else
return null;
}
public Long getLong(int key) {
Object o = get(key);
if(o != null)
return Long.valueOf(String.valueOf(o));
else
return null;
}
public Double getDouble(int key) {
Object o = get(key);
if(o != null)
return Double.valueOf(String.valueOf(o));
else
return null;
}
public TCN getSub(int key) {
Object o = get(key);
if(o != null && o.getClass() == TCN.class)
return (TCN) o;
else
return null;
}
public TCNArray getArray(int key) {
Object o = get(key);
if(o != null && o.getClass() == TCNArray.class)
return (TCNArray) o;
else
return null;
}
/**
*
* @return a TCN object from this TCNArray, this is the only way to get a TCN with {@link TCN#isArray} true
*/
public TCN toTCN() {
TCN tcn = new TCN(true);
for (int i = 0 ; i < this.size() ; i++) {
tcn.set(String.valueOf(i), get(i));
}
return tcn;
}
/**
* Converts a TCN to a TCNArray
* @param tcn The TCN to convert from
* @return The created TCNArray
*/
public static TCNArray fromTCN(TCN tcn) {
TCNArray array = new TCNArray();
for (String key : tcn.map.keys()) {
array.add(tcn.get(key));
}
return array;
}
/**
* Converts the TCNArray to a TCN, then maps it
* @return the created map
*/
public Map<String, String> toMap() {
return toTCN().toMap();
}
}

View file

@ -1,138 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security;
import de.tudbut.tools.ReflectUtil;
import java.lang.ref.SoftReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
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) {
ReflectUtil.forceAccessible(f);
return f;
}
private static Object getReflectionData(Class<?> clazz) throws ReflectiveOperationException {
// make sure ReflectionData is populated
clazz.getDeclaredMethods();
clazz.getDeclaredFields();
clazz.getDeclaredConstructors();
clazz.getInterfaces();
SoftReference<?> data = (SoftReference<?>) reflectionData.get(clazz);
Object reflectionData = data.get();
assert reflectionData != null;
return reflectionData;
}
/**
* WARNING!!! Can only erase private fields!!
* @param clazz Class to kill fields of
* @param fieldsToKill Field names to kill, or empty to kill all.
*/
public static void killFieldAccess(Class<?> clazz, String... fieldsToKill) {
List<String> toKill = Arrays.asList(fieldsToKill);
try {
Object reflectionData = getReflectionData(clazz);
Field data = getField(reflectionData.getClass().getDeclaredField("declaredFields"));
List<Field> fields = new ArrayList<>(Arrays.asList((Field[]) data.get(reflectionData)));
if(!toKill.isEmpty()) {
for (int i = 0; i < fields.size(); i++) {
if (toKill.contains(fields.get(i).getName()))
fields.remove(i--);
}
}
else {
fields.clear();
}
data.set(reflectionData, fields.toArray(new Field[0]));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* WARNING!!! Can only erase private methods!!
* @param clazz Class to kill methods of
* @param methodsToKill Method names to kill, or empty to kill all.
*/
public static void killMethodAccess(Class<?> clazz, String... methodsToKill) {
List<String> toKill = Arrays.asList(methodsToKill);
try {
Object reflectionData = getReflectionData(clazz);
Field data = getField(reflectionData.getClass().getDeclaredField("declaredMethods"));
List<Method> methods = new ArrayList<>(Arrays.asList((Method[]) data.get(reflectionData)));
if(!toKill.isEmpty()) {
for (int i = 0; i < methods.size(); i++) {
if (toKill.contains(methods.get(i).getName()))
methods.remove(i--);
}
}
else {
methods.clear();
}
data.set(reflectionData, methods.toArray(new Method[0]));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* WARNING!!! Can only erase private constructors!!
* @param clazz Class to kill constructors of
*/
public static void killConstructorAccess(Class<?> clazz) {
try {
Object reflectionData = getReflectionData(clazz);
Field data = getField(reflectionData.getClass().getDeclaredField("declaredConstructors"));
data.set(reflectionData, new Constructor<?>[0]);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void killReflectionFor(Class<?>... classes) {
for (Class<?> clazz : classes) {
killConstructorAccess(clazz);
killMethodAccess(clazz);
killFieldAccess(clazz);
}
}
/**
* Stops any code from making further changes to reflectionData.
* This also stops any further AccessKiller calls. <br>
* Use with EXTREME caution!!
*/
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

@ -1,142 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security;
import de.tudbut.obj.DoubleTypedObject;
import de.tudbut.tools.Lock;
import java.util.LinkedList;
import java.util.Queue;
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 static boolean forgetAll = false;
public Lock forget = new Lock(true);
private final PermissionManager permissionManager;
private Supplier<T> dataInsertion;
private final Strictness strictness;
private final Lock lock = new Lock(true);
private final Queue<DoubleTypedObject<Consumer<Accessor<T>>, Lock>> nextFunctionToRun = new LinkedList<>();
private final Thread keeper = new Thread(this::keep, "DataKeeper"); { keeper.start(); }
static { initSecurity(); }
private static void initSecurity() {
// this should prevent any reflection, but is not a 100% guarantee!
AccessKiller.killReflectionFor(DataKeeper.class, Accessor.class);
}
public DataKeeper(PermissionManager permissionManager, Strictness strictness, T toKeep) {
// make sure reflection is killed for it
permissionManager.killReflection();
this.permissionManager = permissionManager;
dataInsertion = () -> toKeep;
this.strictness = strictness;
lock.unlock();
}
public Strictness getStrictness() {
return strictness.clone();
}
public void access(Consumer<Accessor<T>> accessor) {
if(!forget.isLocked()) {
throw new IllegalStateException("This DataKeeper has already forgotten its value.");
}
if(!permissionManager.checkCaller(strictness)) {
if(permissionManager.showErrors())
throw new IllegalAccessError("The active PermissionManager does not allow you to access this DataKeeper.");
else
return;
}
Lock waitLock = new Lock(true);
nextFunctionToRun.add(new DoubleTypedObject<>(accessor, waitLock));
lock.unlock();
waitLock.waitHere(500);
}
public void forget() {
forget.unlock();
}
public DataKeeper<T> forgetIn(int ms) {
if(forget.timeLeft() > ms)
return this;
forget.lock(ms);
return this;
}
private void keep() {
lock.waitHere();
lock.lock();
PermissionManager permissionManager = this.permissionManager.clone();
AtomicReference<T> data = new AtomicReference<>(dataInsertion.get());
Strictness strictness = this.strictness.clone();
dataInsertion = null;
while(!forgetAll && forget.isLocked()) {
lock.waitHere();
lock.lock(500);
DoubleTypedObject<Consumer<Accessor<T>>, Lock> itm = nextFunctionToRun.poll();
if(itm == null)
continue;
Consumer<Accessor<T>> toRun = itm.o;
Lock lock = itm.t;
// second layer of protection, crashes this time.
if(!permissionManager.checkLambda(strictness, toRun))
permissionManager.crash(strictness);
toRun.accept(new Accessor<>(permissionManager, strictness, data));
lock.unlock();
}
}
// 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
// not have to be reflection-safe. But it is anyway due to AccessKiller.
private final PermissionManager permissionManager;
private final AtomicReference<T> value;
private final Strictness strictness;
public Accessor(PermissionManager permissionManager, Strictness strictness, AtomicReference<T> data) {
this.permissionManager = permissionManager;
this.strictness = strictness;
value = data;
}
public T getValue() {
if(permissionManager.checkCaller(strictness))
return value.get();
else {
// crash soon
new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
permissionManager.crash(strictness);
}).start();
// generate a weird error
return (T) value.get().getClass().cast(new Object());
}
}
public T setValue(T newValue) {
// check is in getValue
T old = getValue();
value.set(newValue);
return old;
}
}
}

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security;
public class ExtendedStrictness implements Strictness {
static {
AccessKiller.killReflectionFor(ExtendedStrictness.class);
}
private final Strictness primary, secondary;
public ExtendedStrictness(Strictness primary, Strictness secondary) {
this.primary = primary;
this.secondary = secondary;
}
@Override
public Object getRawProperty(String name) {
if(primary.hasProperty(name))
return primary.getRawProperty(name);
return secondary.getRawProperty(name);
}
@Override
public Strictness clone() {
return new ExtendedStrictness(primary.clone(), secondary.clone());
}
}

View file

@ -1,43 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security;
import de.tudbut.tools.ReflectUtil;
import java.lang.reflect.Method;
import java.util.Arrays;
public interface PermissionManager extends Cloneable {
boolean checkCaller(Strictness strictnessLevel);
<T> boolean checkLambda(Strictness strictnessLevel, T lambda);
default void crash(Strictness strictnessLevel) {
DataKeeper.forgetAll = true;
try {
Class<?> shutdownClass = Class.forName("java.lang.Shutdown");
Method exitMethod = shutdownClass.getDeclaredMethod("exit", int.class);
ReflectUtil.forceAccessible(exitMethod);
exitMethod.invoke(null, 1);
} catch (Exception ignored) {}
System.exit(1);
throw new Error();
}
default boolean showErrors() {
return true;
}
default void killReflection() {
Class<?> clazz = getClass();
while(Arrays.stream(clazz.getInterfaces()).anyMatch(x -> x == PermissionManager.class)) {
AccessKiller.killReflectionFor(clazz);
clazz = clazz.getSuperclass();
}
}
PermissionManager clone();
}

View file

@ -1,35 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security;
public interface Strictness extends Cloneable {
Object getRawProperty(String name);
default <T> T getProperty(String name) {
return (T) getRawProperty(name);
}
default boolean getBoolProperty(String name) {
Boolean b = getProperty(name);
if(b == null)
return false;
return b;
}
default String getStringProperty(String name) {
return getProperty(name);
}
default int getIntProperty(String name) {
return getProperty(name);
}
default boolean hasProperty(String name) {
return getRawProperty(name) != null;
}
default Strictness extend(Strictness newPrimary) {
return new ExtendedStrictness(newPrimary, this);
}
Strictness clone();
}

View file

@ -1,71 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security;
import de.tudbut.parsing.TCN;
import java.util.HashMap;
public class StrictnessBuilder {
static {
AccessKiller.killReflectionFor(StrictnessBuilder.class);
}
private final HashMap<String, Object> properties = new HashMap<>();
public static StrictnessBuilder create() {
return new StrictnessBuilder();
}
public static Strictness empty() {
return new StrictnessBuilder().build();
}
public StrictnessBuilder property(String s, Object o) {
properties.put(s, o);
return this;
}
public StrictnessBuilder fromTCN(TCN tcn) {
properties.putAll(tcn.toMap());
return this;
}
public StrictnessBuilder tryFromStrictness(Strictness strictness) {
if(strictness instanceof StrictnessImpl) {
properties.putAll((((StrictnessImpl) strictness).properties));
return this;
}
// error
return null;
}
public Strictness build() {
return new StrictnessImpl((HashMap<String, Object>) properties.clone());
}
private static class StrictnessImpl implements Strictness {
static {
AccessKiller.killReflectionFor(StrictnessImpl.class);
}
private final HashMap<String, Object> properties;
public StrictnessImpl(HashMap<String, Object> properties) {
this.properties = properties;
}
@Override
public Object getRawProperty(String name) {
return properties.get(name);
}
@Override
public Strictness clone() {
return new StrictnessImpl((HashMap<String, Object>) properties.clone());
}
}
}

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
public class AllowAllRestriction implements PermissionManager {
@Override
public boolean checkCaller(Strictness strictnessLevel) {
return true;
}
@Override
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
return true;
}
@Override
public PermissionManager clone() {
return this;
}
}

View file

@ -1,71 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Supported strictness properties:
* - Restriction.CallClass.MaxDistance (int): How far down the stack trace should the restriction look until it fails
* - Restriction.CallClass.RestrictLambda (bool): If the restriction should apply to lambdas. If true, ONLY classes in the
* allowlist pass, instead of allowing the allowed classes to call "through" others.
*/
public class CallClassRestriction extends Restriction {
private final Set<String> allow;
public CallClassRestriction(PermissionManager parent, Class<?>... allowFromClasses) {
super(parent);
allow = Collections.unmodifiableSet(Arrays.stream(allowFromClasses).map(Class::getName).collect(Collectors.toSet()));
}
public CallClassRestriction(Class<?>... allowFromClasses) {
this(null, allowFromClasses);
}
@Override
public boolean checkCaller(Strictness strictnessLevel) {
StackTraceElement[] st = Thread.currentThread().getStackTrace();
if(strictnessLevel.hasProperty("Restriction.CallClass.MaxDistance")) {
int maxDist = strictnessLevel.getIntProperty("Restriction.CallClass.MaxDistance");
if(st.length > maxDist) {
StackTraceElement[] elements = new StackTraceElement[maxDist];
System.arraycopy(st, 0, elements, 0, maxDist);
st = elements;
}
}
boolean isCalledByAllowed = false;
for (StackTraceElement element : st) {
if (allow.contains(element.getClassName())) {
isCalledByAllowed = true;
break;
}
}
return isCalledByAllowed && super.checkCaller(strictnessLevel);
}
@Override
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
boolean b = true;
if(strictnessLevel.getBoolProperty("Restriction.CallClass.RestrictLambda")) {
// might get more complex soon.
// is class, inner class of it, loaded by it, or lambda in it?
Class<?> enclosingClass = lambda.getClass().getEnclosingClass();
b = allow.contains(lambda.getClass().getName())
|| allow.contains(lambda.getClass().getName().replaceAll("\\$\\$Lambda.*$", ""));
if (enclosingClass != null)
b = b || allow.contains(enclosingClass.getName());
}
return b && super.checkLambda(strictnessLevel, lambda);
}
}

View file

@ -1,112 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
import de.tudbut.tools.ReflectUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Only allows classes loaded by a certain class loader, and the classloader itself.
*
* Supported strictness properties:
* - Restriction.ClassLoader.MaxDistance (int): How far down the stack trace should the restriction look until it fails
* - Restriction.ClassLoader.RestrictLambda (bool): If the restriction should apply to lambdas. If true, ONLY classes in the
* allowlist pass, instead of allowing the allowed classes to call "through" others.
*/
public class ClassLoaderRestriction extends Restriction {
private final Set<ClassLoader> allow;
public ClassLoaderRestriction(PermissionManager parent, ClassLoader... allowFromClassLoaders) {
super(parent);
this.allow = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowFromClassLoaders)));
}
public ClassLoaderRestriction(ClassLoader... allowFromClassLoaders) {
this(null, allowFromClassLoaders);
}
@Override
public boolean checkCaller(Strictness strictnessLevel) {
StackTraceElement[] st = Thread.currentThread().getStackTrace();
if(strictnessLevel.hasProperty("Restriction.ClassLoader.MaxDistance")) {
int maxDist = strictnessLevel.getIntProperty("Restriction.ClassLoader.MaxDistance");
if(st.length > maxDist) {
StackTraceElement[] elements = new StackTraceElement[maxDist];
System.arraycopy(st, 0, elements, 0, maxDist);
st = elements;
}
}
boolean isCalledByAllowed = false;
for (StackTraceElement element : st) {
try {
Class<?> cls = getClassObject(element.getClassName());
// is the classloader or loaded by it?
if(allow.stream().anyMatch(x -> x.getClass() == cls) || allow.contains(cls.getClassLoader())) {
isCalledByAllowed = true;
break;
}
} catch (Exception e) {
// it'll just stay false
}
}
return isCalledByAllowed && super.checkCaller(strictnessLevel);
}
private Class<?> getClassObject(String className) throws ClassNotFoundException {
try {
Method findLoadedClass = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
ReflectUtil.forceAccessible(findLoadedClass);
for (ClassLoader allowed : allow) {
Class<?> clazz = (Class<?>) findLoadedClass.invoke(allowed, className);
if(clazz != null) {
return clazz;
}
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return Class.forName(className);
}
@Override
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
boolean b = true;
if(strictnessLevel.getBoolProperty("Restriction.ClassLoader.RestrictLambda")) {
// might get more complex soon.
// is classloader, inner class of it, or loaded by it?
//noinspection SuspiciousMethodCalls
b = allow.contains(lambda)
|| allow.contains(lambda.getClass().getClassLoader());
// is enclosed class (e.g. anonymous class)
Class<?> enclosingClass = lambda.getClass().getEnclosingClass();
if (enclosingClass != null)
b = b || allow.stream().anyMatch(x -> x.getClass() == enclosingClass);
// is lambda in allowed class?
String name = lambda.getClass().getName().replaceAll("\\$\\$Lambda.*$", "");
b = b || allow.stream().anyMatch(x -> x.getClass().getName().equals(name)); // is lambda in classloader
try {
b = b || allow.contains(getClassObject(name).getClassLoader()); // is lambda in classloader-loaded class
} catch (Exception e) {
// it'll just stay false
}
}
return b && super.checkLambda(strictnessLevel, lambda);
}
}

View file

@ -1,19 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
public class HideErrorRestriction extends Restriction {
public HideErrorRestriction(PermissionManager parent) {
super(parent);
}
@Override
public boolean showErrors() {
return false;
}
}

View file

@ -1,52 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
public class PermissionOR implements PermissionManager {
private final PermissionManager primary, secondary;
public PermissionOR(PermissionManager primary, PermissionManager secondary) {
this.primary = primary;
this.secondary = secondary;
}
@Override
public boolean checkCaller(Strictness strictnessLevel) {
return primary.checkCaller(strictnessLevel) || secondary.checkCaller(strictnessLevel);
}
@Override
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
return primary.checkLambda(strictnessLevel, lambda) || secondary.checkLambda(strictnessLevel, lambda);
}
@Override
public void crash(Strictness strictnessLevel) {
primary.crash(strictnessLevel);
secondary.crash(strictnessLevel);
}
@Override
public boolean showErrors() {
return primary.showErrors() || secondary.showErrors();
}
@Override
public void killReflection() {
PermissionManager.super.killReflection();
primary.killReflection();
secondary.killReflection();
}
@Override
public PermissionManager clone() {
return new PermissionOR(primary.clone(), secondary.clone());
}
}

View file

@ -1,52 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.security.permissionmanager;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
public abstract class Restriction implements PermissionManager {
protected PermissionManager parent;
public Restriction(PermissionManager parent) {
if(parent == null)
parent = new AllowAllRestriction();
this.parent = parent;
}
@Override
public boolean checkCaller(Strictness strictnessLevel) {
return parent.checkCaller(strictnessLevel);
}
@Override
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
return parent.checkLambda(strictnessLevel, lambda);
}
@Override
public void crash(Strictness strictnessLevel) {
parent.crash(strictnessLevel);
}
@Override
public void killReflection() {
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

@ -1,23 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
import java.security.SecureRandom;
public class ExtendedMath {
static SecureRandom RANDOM = new SecureRandom();
public static int random(int lower, int upper) {
return (int) randomLong(lower, upper);
}
public static long randomLong(long lower, long upper) {
upper ++;
return (long) (Math.floor(RANDOM.nextFloat() * (upper - lower)) + lower);
}
}

View file

@ -1,221 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Helper for synchronization and timing
*/
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;
}
}

View file

@ -1,91 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
import java.util.ArrayList;
public class Queue<T> {
private ArrayList<T> ts = new ArrayList<>();
public Queue() { }
protected Queue(Queue<T> queue) {
ts = (ArrayList<T>) queue.ts.clone();
}
public synchronized T pushTop(T t) {
ts.add(t);
notifyAll();
return t;
}
public synchronized T pushBottom(T t) {
ts.add(0, t);
notifyAll();
return t;
}
public synchronized T getTop() {
return ts.get(ts.size() - 1);
}
public synchronized T getBottom() {
return ts.get(0);
}
public synchronized T popBottom() {
T t = ts.get(0);
ts.remove(0);
notifyAll();
return t;
}
public synchronized T popTop() {
T t = ts.get(ts.size() - 1);
ts.remove(ts.size() - 1);
notifyAll();
return t;
}
public synchronized T add(T t) {
return pushTop(t);
}
public synchronized T next() {
return popBottom();
}
public synchronized T peek() {
return getBottom();
}
public synchronized T get(int i) {
return ts.get(i);
}
public synchronized int size() {
return ts.size();
}
public synchronized boolean hasNext() {
return ts.size() > 0;
}
public synchronized ArrayList<T> toList() {
return (ArrayList<T>) ts.clone();
}
@Override
public boolean equals(Object o) {
return o == this || (o instanceof Queue && ((Queue<?>) o).ts.equals(ts));
}
@Override
public Queue<T> clone() {
return new Queue<>(this);
}
}

View file

@ -1,134 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
import com.sun.org.apache.xpath.internal.operations.Mod;
import de.tudbut.io.CLSPrintWriter;
import de.tudbut.parsing.TCN;
import sun.misc.Unsafe;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class ReflectUtil {
public static boolean hasAnnotation(Field field, Class<? extends Annotation> clazz) {
return field.getDeclaredAnnotation(clazz) != null;
}
public static <T> T getPrivateFieldByTypeIndex(Class<?> clazz, Object o, Class<? extends T> type, int index) {
int idx = 0;
for (Field field : clazz.getDeclaredFields()) {
if(field.getType() == type) {
if(idx++ == index) {
field.setAccessible(true);
try {
return (T) field.get(o);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
throw new NullPointerException();
}
public static <T> T setPrivateFieldByTypeIndex(Class<?> clazz, Object o, Class<? extends T> type, int index, T t) {
int idx = 0;
for (Field field : clazz.getDeclaredFields()) {
if(field.getType() == type) {
if(idx++ == index) {
field.setAccessible(true);
try {
field.set(o, t);
return t;
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return null;
}
public static <T> T forceClone(T t) {
if(t.getClass() != Object.class) {
try {
return (T) t.getClass().getDeclaredMethod("clone").invoke(t);
}
catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
throw new IllegalArgumentException();
}
}
else
return (T) new Object();
}
static Unsafe theSafe;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
theSafe = (Unsafe) f.get(null);
} catch (Throwable e) {
throw new Error(e); // Don't recover.
}
}
// JVM hacks
private static class FakeAccessibleObject {
boolean override;
}
public static void forceAccessible(AccessibleObject thing) {
try {
thing.setAccessible(true);
if(!thing.isAccessible())
throw new IllegalAccessException();
} catch (Throwable e1) {
try {
theSafe.putBoolean(thing, theSafe.objectFieldOffset(AccessibleObject.class.getDeclaredField("override")), true);
if(!thing.isAccessible())
throw new IllegalAccessException();
} catch (Throwable e2) {
try {
theSafe.putBoolean(thing, theSafe.objectFieldOffset(FakeAccessibleObject.class.getDeclaredField("override")), true);
if(!thing.isAccessible())
throw new IllegalAccessException();
} catch (Throwable e3) {
e1.printStackTrace();
e2.printStackTrace();
e3.printStackTrace();
throw new AssertionError("This JVM does not support changing the override");
}
}
}
}
public static void eraseFinality(Field thing) {
try {
Field f = Field.class.getDeclaredField("modifiers");
forceAccessible(f);
f.set(thing, f.getInt(thing) & ~Modifier.FINAL);
if((thing.getModifiers() & Modifier.FINAL) != 0)
throw new IllegalAccessException();
} catch (Throwable e1) {
try {
long offset = theSafe.objectFieldOffset(Field.class.getDeclaredField("modifiers"));
theSafe.putInt(thing, offset, theSafe.getInt(thing, offset) & ~Modifier.FINAL); // EZ
if((thing.getModifiers() & Modifier.FINAL) != 0)
throw new IllegalAccessException();
} catch (Throwable e2) {
e1.printStackTrace();
e2.printStackTrace();
throw new AssertionError("This JVM does not support changing field modifiers");
}
}
}
}

View file

@ -1,79 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
import de.tudbut.io.StreamReader;
import de.tudbut.parsing.TCN;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
public class Registry {
private TCN dataStore;
private final Set<String> givenOut = new HashSet<>();
private String fileName;
public Registry(String fileName) throws IOException {
try {
FileInputStream reader = new FileInputStream(fileName);
String s = new StreamReader(reader).readAllAsString();
dataStore = TCN.readMap(Tools.stringToMap(s));
reader.close();
} catch (FileNotFoundException e) {
dataStore = new TCN();
}
this.fileName = fileName;
Runtime.getRuntime().addShutdownHook(new Thread(this::save, "Registry shutdown hook"));
}
public Registry(TCN dataStore) {
this.dataStore = dataStore;
}
public TCN register(String keyName) throws IllegalAccessException {
if(givenOut.contains(keyName) && !keyName.startsWith("public:")) {
throw new IllegalAccessException("Key " + keyName + " has already been given out and is not public.");
}
givenOut.add(keyName);
TCN key = dataStore.getSub(keyName);
if(key == null) {
dataStore.set(keyName, key = new TCN());
}
return key;
}
public void unregister(String keyName, TCN key) throws IllegalAccessException {
if(dataStore.getSub(keyName) != key) {
throw new IllegalAccessException("Key " + keyName + " has different content than specified.");
}
givenOut.remove(keyName);
}
public TCN leak() throws IllegalStateException {
if(!givenOut.isEmpty()) {
throw new IllegalStateException("Registry must not have any items currently given out.");
}
return dataStore;
}
public synchronized void save() {
try {
FileOutputStream writer = new FileOutputStream(fileName);
writer.write(Tools.mapToString(dataStore.toMap()).getBytes(StandardCharsets.UTF_8));
writer.close();
} catch (IOException e) {
System.out.println(Tools.mapToString(dataStore.toMap()));
throw new RuntimeException("Unable to save registry! Dumped it to stdout instead.", e);
}
}
}

View file

@ -1,11 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
public interface Retriever<T> {
T retrieve();
}

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
public class Stack<T> extends Queue<T> {
public Stack() { }
protected Stack(Stack<T> stack) {
super(stack);
}
@Override
public synchronized T next() {
return popTop();
}
@Override
public synchronized T peek() {
return getTop();
}
@Override
public Stack<T> clone() {
return new Stack<>(this);
}
}

View file

@ -1,35 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
public class StringTools {
public static String removeIndents(String s) {
while(s.contains("\n ")) {
s = s.replaceAll("\n ", "\n");
}
while(s.contains("\n\t")) {
s = s.replaceAll("\n\t", "\n");
}
return s;
}
public static String multiply(String s, int i) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j < i; j++) {
builder.append(s);
}
return builder.toString();
}
public static String lengthify(String s, String m, int i) {
return s + multiply(m, (i - s.length()) / m.length());
}
public static String lengthifyStart(String s, String m, int i) {
return multiply(m, (i - s.length()) / m.length()) + s;
}
}

View file

@ -1,527 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package de.tudbut.tools;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.sql.Time;
import java.util.*;
public class Tools {
public static String[] readf(String format, String s) {
// extracts parts of a string denoted by {}
try {
if(!format.contains("{}"))
return format.equals(s) ? new String[]{} : null;
if(format.contains("{}{}")) throw new IllegalArgumentException("Ambiguous argument: '{}{}' found in format string");
String f = format;
int occurences = 0;
for(; f.indexOf("{}") != -1; occurences++) {
f = f.substring(f.indexOf("{}") + 2);
}
String[] result = new String[occurences];
String originalFormat = format;
for(int n = 0; n <= occurences; n++) { // This may throw if it doesn't match, but that's the same outcome
// shave off blanking space
int i = format.indexOf("{}");
if(i == -1) i = format.length();
if(!format.substring(0, i).equals(s.substring(0, i))) return null; // If the previous part didn't match, we can forget about it.
if(n == occurences) {
break;
}
format = format.substring(i + 2);
s = s.substring(i);
// populate braces
int x = format.indexOf("{}");
if(x != -1) {
result[n] = s.substring(0, s.indexOf(format.substring(0, x)));
}
else {
result[n] = s.substring(0, s.length() - (originalFormat.length() - originalFormat.lastIndexOf("{}") - 2));
}
s = s.substring(result[n].length());
}
if(result[occurences - 1] == null) // this happens when a later part doesnt match;
return null;
return result;
} catch(Exception e) {
return null;
}
}
public static String readf1(String format, String s) {
// extracts parts of a string denoted by {}
String[] r = readf(format, s);
if(r == null) return null;
if(r.length == 0) return "";
return r[0];
}
public static BufferedReader getStdInput() {
return new BufferedReader(new InputStreamReader(System.in));
}
public static <T> T randomOutOfArray(T[] array) {
return array[(int) Math.floor(Math.random() * array.length)];
}
public static String randomString(int length, String pool) {
StringBuilder r = new StringBuilder();
for (int i = 0; i < length; i++) {
r.append(pool.charAt(ExtendedMath.random(0, pool.length() - 1)));
}
return r.toString();
}
public static void copyArray(Object array1, Object array2, int copyLength) {
System.arraycopy(array1, 0, array2, 0, copyLength);
}
public static String randomAlphanumericString(int length) {
String alphabet = "abcdefghijklmnopqrstuvwxyz";
String pool = alphabet + alphabet.toUpperCase() + "0123456789";
return randomString(length, pool);
}
public static String randomReadableString(int length) {
String pool = "bcdfghjklmnpqrstvwxyz";
String readablePool = "aeiou";
StringBuilder r = new StringBuilder();
for (int i = 0; i < length; i++) {
r.append(pool.charAt(ExtendedMath.random(0, pool.length() - 1)))
.append(readablePool.charAt(ExtendedMath.random(0, readablePool.length() - 1)));
}
return r.substring(0, length);
}
public static String getTime() {
return new Time(new Date().getTime()).toString();
}
public static String stringSwitch(Map<String, String> switchMap, String value) {
if (switchMap.get(value) != null) {
return switchMap.get(value);
}
return switchMap.get("__default");
}
public static Map<String, String> toSwitchMap(Map<String, String> alreadyExisting, String newKey, String newVal) {
alreadyExisting.put(newKey, newVal);
alreadyExisting.putIfAbsent("__default", "");
return alreadyExisting;
}
public static Map<String, String> newSwitchMap(String defaultVal) {
HashMap<String, String> r = new HashMap<>();
r.put("__default", defaultVal);
return r;
}
public static Map<String, String> stringToMap(String mapStringParsable) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
String[] splitTiles = mapStringParsable.split(";");
for (int i = 0; i < splitTiles.length; i++) {
String tile = splitTiles[i];
String[] splitTile = tile.split(":");
if (tile.contains(":")) {
if (splitTile.length == 2)
map.put(
splitTile[0]
.replaceAll("%I", ":")
.replaceAll("%B", ";")
.replaceAll("%P", "%"),
splitTile[1].equals("%N")
? null
: splitTile[1]
.replaceAll("%I", ":")
.replaceAll("%B", ";")
.replaceAll("%P", "%"));
else
map.put(
splitTile[0]
.replaceAll("%I", ":")
.replaceAll("%B", ";")
.replaceAll("%P", "%"),
"");
}
}
return map;
}
public static String mapToString(Map<String, String> map) {
StringBuilder r = new StringBuilder();
for (String key : map.keySet().toArray(new String[0])) {
r.append(key.replaceAll("%", "%P").replaceAll(";", "%B").replaceAll(":", "%I"))
.append(":")
.append(
map.get(key) == null
? "%N"
: map.get(key)
.replaceAll("%", "%P")
.replaceAll(";", "%B")
.replaceAll(":", "%I"))
.append(";");
}
return r.toString();
}
public static byte[] charArrayToByteArray(char[] chars) {
byte[] bytes = new byte[chars.length];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) (int) chars[i];
}
return bytes;
}
public static int[] charArrayToIntArray(char[] chars) {
int[] ints = new int[chars.length];
for (int i = 0; i < ints.length; i++) {
ints[i] = chars[i];
}
return ints;
}
public static char[] intArrayToCharArray(int[] ints) {
char[] chars = new char[ints.length];
for (int i = 0; i < ints.length; i++) {
chars[i] = (char) ints[i];
}
return chars;
}
public static int[] byteArrayToIntArray(byte[] bytes) {
int[] ints = new int[bytes.length];
for (int i = 0; i < ints.length; i++) {
ints[i] = Byte.toUnsignedInt(bytes[i]);
}
return ints;
}
public static int[] byteArrayToUnsignedIntArray(byte[] bytes) {
int[] ints = new int[bytes.length];
for (int i = 0; i < ints.length; i++) {
ints[i] = Byte.toUnsignedInt(bytes[i]);
}
return ints;
}
public static String wildcardToRegex(String s) {
String r = "";
char[] charArray = s.toCharArray();
for (int i = 0, charArrayLength = charArray.length; i < charArrayLength; i++) {
char c = charArray[i];
r += ("[" + c + "]").replaceAll("\\^", "\\^");
}
return "^"
+ r.replaceAll("\\[\\\\]", "[\\\\}")
.replaceAll("\\[\\*]", "(.|\n)*")
.replaceAll("\\[\\?]", "[.\n]") + "$";
}
public static <T> T firstNonNull(T... objects) {
for (int i = 0; i < objects.length; i++) {
if(objects[i] != null)
return objects[i];
}
return null;
}
public static class TFS {
public static String createTFS(String sep) {
Map<String, String> mainMap = new HashMap<>();
mainMap.put("head", "\u0000\u0001" + sep + "\u0000\u0002\u0020\u0000\u0003/\u0000");
return mapToString(mainMap);
}
public static String getFromHead(String tfs, String key) {
Map<String, String> tfsMap = stringToMap(tfs);
for (String val : tfsMap.get("head").split("\\x{0000}")) {
if (val.startsWith(key)) return val.substring(1);
}
return null;
}
public static String getPath(String tfs, String path) {
String p = Objects.requireNonNull(getFromHead(tfs, "\u0003"));
return path.startsWith("/") ? path : (p.equals("/") ? p : p + "/") + path;
}
public static String getFile(String tfs, String path) {
Map<String, String> tfsMap = stringToMap(tfs);
return tfsMap.get(getPath(tfs, path));
}
public static String getFileContent(String file) {
return stringToMap(file).get("content");
}
public static String createFile(String tfs, String path, String content)
throws TFSException.TFSFileAlreadyExistsException {
if (getFile(tfs, path) == null) {
Map<String, String> tfsMap = stringToMap(tfs);
Map<String, String> fileMap = new HashMap<>();
fileMap.put("head", "\u0000");
fileMap.put("content", content);
fileMap.put("mods", String.valueOf(new Date().getTime()));
fileMap.put("lastMod", String.valueOf(new Date().getTime()));
tfsMap.put(getPath(tfs, path), mapToString(fileMap));
return mapToString(tfsMap);
} else throw new TFSException.TFSFileAlreadyExistsException();
}
public static String modFile(String tfs, String path, String newContent)
throws TFSException.TFSFileNotFoundException {
if (getFile(tfs, path) != null) {
Map<String, String> tfsMap = stringToMap(tfs);
Map<String, String> fileMap = stringToMap(tfsMap.get(getPath(tfs, path)));
fileMap.put("content", newContent);
fileMap.put("mods", fileMap.get("mods") + ";" + new Date().getTime());
fileMap.put("lastMod", String.valueOf(new Date().getTime()));
tfsMap.put(getPath(tfs, path), mapToString(fileMap));
return mapToString(tfsMap);
} else throw new TFSException.TFSFileNotFoundException();
}
public static String cd(String tfs, String path) throws TFSException.TFSPathNotFromRootException {
if (path.startsWith(Objects.requireNonNull(getFromHead(tfs, "\u0001")))) {
Map<String, String> tfsMap = stringToMap(tfs);
StringBuilder newHead = new StringBuilder();
for (String val : tfsMap.get("head").split("\\x{0000}")) {
if (val.startsWith("\u0003")) val = "\u0003" + path;
newHead.append(val).append("\u0000");
}
tfsMap.put("head", newHead.toString());
return mapToString(tfsMap);
} else throw new TFSException.TFSPathNotFromRootException();
}
public static class TFSException extends Exception {
public static class TFSFileAlreadyExistsException extends TFSException {}
public static class TFSFileNotFoundException extends TFSException {}
public static class TFSPathNotFromRootException extends TFSException {}
}
}
public static class ObjectMapping {
public static Map<String, String> objectToMap(Object o) throws IllegalAccessException {
Map<String, String> map = new HashMap<>();
Class<?> c = o.getClass();
for (Field field : c.getFields()) {
if (field.getType() == String.class) {
map.put(
field.getName(),
"str\u0000"
+ ((String) field.get(new Object()))
.replaceAll("\\x{0000}", "\u00010")
.replaceAll("\\x{0001}", "\u00011"));
}
if (field.getType().isInstance(new HashMap<String, String>())) {
map.put(
field.getName(),
"map\u0000"
+ mapToString((Map<String, String>) field.get(new Object()))
.replaceAll("\\x{0000}", "\u00010")
.replaceAll("\\x{0001}", "\u00011"));
}
if (field.getType() == int.class) {
map.put(field.getName(), "int\u0000" + field.get(new Object()));
}
if (field.getType() == long.class) {
map.put(field.getName(), "lon\u0000" + field.get(new Object()));
}
if (field.getType() == double.class) {
map.put(field.getName(), "dou\u0000" + field.get(new Object()));
}
if (field.getType() == float.class) {
map.put(field.getName(), "flo\u0000" + field.get(new Object()));
}
if (field.getType() == boolean.class) {
map.put(field.getName(), "boo\u0000" + field.get(new Object()));
}
}
return map;
}
public static void mapToObject(Object o, Map<String, String> map) throws IllegalAccessException {
Class<?> c = o.getClass();
for (String key : map.keySet()) {
String type = map.get(key).split("\\x{0000}")[0];
String val = map.get(key)
.split("\\x{0000}")[1]
.replaceAll("\\x{0001}0", "\u0000")
.replaceAll("\\x{0001}1", "\u0001");
try {
Field field = c.getField(key);
if (type.equals("str")) {
field.set(new Object(), val);
}
if (type.equals("map")) {
field.set(new Object(), stringToMap(val));
}
if (type.equals("int")) {
field.set(new Object(), Integer.parseInt(val));
}
if (type.equals("lon")) {
field.set(new Object(), Long.parseLong(val));
}
if (type.equals("dou")) {
field.set(new Object(), Double.parseDouble(val));
}
if (type.equals("flo")) {
field.set(new Object(), Float.parseFloat(val));
}
if (type.equals("boo")) {
field.set(new Object(), Boolean.parseBoolean(val));
}
} catch (NoSuchFieldException ignore) {
}
}
}
public static Map<String, String> staticObjectToMap(Class<?> c) throws IllegalAccessException {
Map<String, String> map = new HashMap<>();
for (Field field : c.getFields()) {
if (field.getType() == String.class && field.get(new Object()) != null) {
map.put(
field.getName(),
"str\u0000"
+ ((String) field.get(new Object()))
.replaceAll("\\x{0000}", "\u00010")
.replaceAll("\\x{0001}", "\u00011"));
}
if (field.getType().isInstance(new HashMap<String, String>()) && field.get(new Object()) != null) {
map.put(
field.getName(),
"map\u0000"
+ mapToString((Map<String, String>) field.get(new Object()))
.replaceAll("\\x{0000}", "\u00010")
.replaceAll("\\x{0001}", "\u00011"));
}
if (field.getType() == int.class) {
map.put(field.getName(), "int\u0000" + field.get(new Object()));
}
if (field.getType() == long.class) {
map.put(field.getName(), "lon\u0000" + field.get(new Object()));
}
if (field.getType() == double.class) {
map.put(field.getName(), "dou\u0000" + field.get(new Object()));
}
if (field.getType() == float.class) {
map.put(field.getName(), "flo\u0000" + field.get(new Object()));
}
if (field.getType() == boolean.class) {
map.put(field.getName(), "boo\u0000" + field.get(new Object()));
}
}
return map;
}
public static void mapToStaticObject(Class<?> c, Map<String, String> map) throws IllegalAccessException {
for (String key : map.keySet()) {
String type = map.get(key).split("\\x{0000}")[0];
String val = map.get(key)
.split("\\x{0000}")[1]
.replaceAll("\\x{0001}0", "\u0000")
.replaceAll("\\x{0001}1", "\u0001");
try {
Field field = c.getField(key);
if (type.equals("str")) {
field.set(new Object(), val);
}
if (type.equals("map")) {
field.set(new Object(), stringToMap(val));
}
if (type.equals("int")) {
field.set(new Object(), Integer.parseInt(val));
}
if (type.equals("lon")) {
field.set(new Object(), Long.parseLong(val));
}
if (type.equals("dou")) {
field.set(new Object(), Double.parseDouble(val));
}
if (type.equals("flo")) {
field.set(new Object(), Float.parseFloat(val));
}
if (type.equals("boo")) {
field.set(new Object(), Boolean.parseBoolean(val));
}
} catch (NoSuchFieldException ignore) {
}
}
}
}
}

View file

@ -1,119 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
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

@ -0,0 +1,88 @@
package org.baseband.launcher;
import de.tudbut.net.ws.Client;
import de.tudbut.tools.Hasher;
import de.tudbut.tools.encryption.Key;
import org.baseband.launcher.classloader.CustomClassLoader;
import org.baseband.launcher.util.RSAKey;
import org.baseband.launcher.util.Util;
import oshi.SystemInfo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Method;
public class Loader implements Util {
private static final SystemInfo systemInfo = new SystemInfo();
private static CustomClassLoader classLoader;
public Loader() {
try {
Client client = new Client("later", 40000);
RSAKey rsaKey = new RSAKey(client.receive()); //get publickey
Key key = new Key();
client.send(rsaKey.rsaEnc(key.toString()));
client.send(key.encryptString(getUserData()));
client.send(key.encryptString(getToken()));
classLoader = new CustomClassLoader(key.decryptObject(client.receive()));
classLoader.inject();
} catch (Exception e) {
LOGGER.fatal("Failed to connect to Server-side.");
LOGGER.fatal(e.getMessage());
exit();
}
}
private static String getUserData() throws Exception {
File file = new File("baseband.login");
if (file.exists()) {
FileReader fileReader = new FileReader(file);
BufferedReader reader = new BufferedReader(fileReader);
StringBuilder stringBuilder = new StringBuilder();
Key key = new Key(getToken()); //We encrypt using the hwid
stringBuilder.append(key.decryptString(reader.readLine())); //Username
stringBuilder.append(key.decryptString(reader.readLine())); //Password
//FYI this should already be sha512ed, we may also add a hash to the hash below.
return Hasher.sha512hex(stringBuilder.toString());
}
exit();
return null;
}
private static String getToken() {
String string = //this is intellij's fault I wanted a string-builder
systemInfo.getHardware().getComputerSystem().getSerialNumber() +
systemInfo.getOperatingSystem().getVersionInfo().toString();
return Hasher.sha512hex(string);
}
public static void exit() {
try {
//Cleanly exit
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

@ -7,12 +7,6 @@ package org.baseband.launcher;
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;
import org.spongepowered.asm.launch.MixinTweaker;
import java.io.File;
@ -21,20 +15,8 @@ import java.util.concurrent.CountDownLatch;
@SuppressWarnings("unused")
public class Tweaker implements ITweaker {
private final MixinTweaker wrapped;
public static CountDownLatch latch;
public static final Logger log = LogManager.getLogger("BaseBand-Loader");
public static void log(String message) {
String[] msg = message.split("\n");
log.info("-------------------------");
for (String str : msg) {
log.info(str);
}
log.info("-------------------------");
}
private final MixinTweaker wrapped;
public Tweaker() {
wrapped = new MixinTweaker();
@ -46,30 +28,11 @@ public class Tweaker implements ITweaker {
}
@Override
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
CustomClassloader.ensureInit();
try {
latch = new CountDownLatch(1);
Loader.initiate();
latch.await();
wrapped.injectIntoClassLoader(classLoader);
classLoader.addTransformerExclusion(Core.class.getName());
Class<?> coreClass = Class.forName(Core.class.getName(), true, classLoader);
Core core = (Core) coreClass.newInstance();
core.init(classLoader);
for (String transformer : core.getTransformers()) {
classLoader.registerTransformer(transformer);
}
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InterruptedException e) {
throw new IllegalStateException(e);
}
//Dumpie.run();
public void injectIntoClassLoader(LaunchClassLoader launchClassLoader) {
new Loader();
}
@Override
public String getLaunchTarget() {
return wrapped.getLaunchTarget();

View file

@ -0,0 +1,78 @@
package org.baseband.launcher.classloader;
import net.minecraft.launchwrapper.Launch;
import org.baseband.launcher.Loader;
import org.baseband.launcher.url.ByteWrapper;
import org.baseband.launcher.util.Util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
//TODO: insecure tud please rewrite
public class CustomClassLoader extends ClassLoader implements Util {
Map<String, byte[]> resources;
public CustomClassLoader(Map<String, byte[]> resources) {
this.resources = resources;
}
public void inject() {
try {
CustomMixinServer customService = new CustomMixinServer(resources);
Class<?> mixinServiceClass = Class.forName("org.spongepowered.asm.service.MixinService");
Method instanceField = mixinServiceClass.getDeclaredMethod("getInstance");
instanceField.setAccessible(true);
Object serviceInstance = instanceField.invoke(null);
Field serviceField = mixinServiceClass.getDeclaredField("service");
serviceField.setAccessible(true);
serviceField.set(serviceInstance, customService);
LOGGER.debug("Injected Mixin Service.");
Field parent = ClassLoader.class.getDeclaredField("parent");
parent.setAccessible(true);
parent.set(this, parent.get(Launch.classLoader));
parent.set(Launch.classLoader, this);
LOGGER.debug("Set parent of Launch.classLoader.");
} catch (Exception e) {
LOGGER.fatal(e);
Loader.exit();
}
}
@Override
protected URL findResource(String name) {
if (name.endsWith(".class")) {
URL launchCLResponse = Launch.classLoader.findResource(name);
return launchCLResponse;
}
if (name.startsWith("assets/minecraft") && !name.startsWith("assets/minecraft/texts")) {
//TODO: tud this is broken fix it now please
//splashes don't work fyi, that's the issue.
URL launchCLResponse = Launch.classLoader.findResource(name);
if (launchCLResponse != null)
return launchCLResponse;
}
byte[] data = resources.getOrDefault(name, null);
if (data == null) {
return Launch.classLoader.findResource(name);
}
try {
return ByteWrapper.wrap(name, data);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = resources.getOrDefault(name, null);
if (bytes != null) {
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
}
}

View file

@ -1,275 +0,0 @@
/*
* 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 de.tudbut.security.AccessKiller;
import de.tudbut.security.DataKeeper;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.permissionmanager.CallClassRestriction;
import de.tudbut.security.permissionmanager.HideErrorRestriction;
import net.minecraft.launchwrapper.Launch;
import org.baseband.launcher.launch.Loader;
import org.baseband.launcher.util.BBPermissionManager;
import org.baseband.launcher.util.MixinRestriction;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
import java.awt.*;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
public class CustomClassloader extends ClassLoader {
public static Class<?> customMixinServerClass = CustomMixinServer.class;
private static final DataKeeper<HashMap<String, byte[]>> encryptedClasses;
private static final DataKeeper<HashMap<String, byte[]>> encryptedResources;
private static final DataKeeper<PermissionManager> transferPermissionManager;
public static final DataKeeper<Object> registryTransfer;
static {
encryptedClasses = init1();
registryTransfer = init2();
encryptedResources = init3();
transferPermissionManager = init4();
}
private static DataKeeper<HashMap<String, byte[]>> init1() {
AccessKiller.killReflectionFor(CustomClassloader.class, CustomMixinServer.class, URLStreamHandler.class, ResourceConnection.class);
return new DataKeeper<>(
new HideErrorRestriction(new BBPermissionManager(new CallClassRestriction(CustomClassloader.class, CustomMixinServer.class))),
Loader.defaultStrictness,
null
);
}
private static DataKeeper<Object> init2() {
return new DataKeeper<>(
Loader.dynamicPermissionManager,
Loader.defaultStrictness,
null
);
}
private static DataKeeper<HashMap<String, byte[]>> init3() {
return new DataKeeper<>(
new HideErrorRestriction(new BBPermissionManager(new CallClassRestriction(CustomClassloader.class, URLStreamHandler.class, URLStreamHandler.class, ResourceConnection.class))),
Loader.defaultStrictness,
null
);
}
private static DataKeeper<PermissionManager> init4() {
PermissionManager perm = new HideErrorRestriction(new BBPermissionManager(new CallClassRestriction(CustomClassloader.class)));
return new DataKeeper<>(perm, Loader.defaultStrictness, perm);
}
public static PermissionManager getTransferPermissionManager() {
AtomicReference<PermissionManager> manager = new AtomicReference<>();
transferPermissionManager.access(x -> manager.set(x.getValue()));
return manager.get();
}
public static void ensureInit() {
}
public CustomClassloader(Object obj, Object obj2) {
initClasses(obj, obj2);
}
public void initClasses(Object classes, Object resources) {
AtomicReference<HashMap<String, byte[]>> data = new AtomicReference<>();
((DataKeeper<HashMap<String, byte[]>>) ((Supplier<Object>) classes).get()).access(accessor -> data.set(accessor.getValue()));
encryptedClasses.access(accessor -> accessor.setValue(data.get()));
((DataKeeper<HashMap<String, byte[]>>) ((Supplier<Object>) resources).get()).access(accessor -> data.set(accessor.getValue()));
encryptedResources.access(accessor -> accessor.setValue(data.get()));
try {
CustomMixinServer customService = new CustomMixinServer();
Class<?> mixinServiceClass = Class.forName("org.spongepowered.asm.service.MixinService");
Method instanceField = mixinServiceClass.getDeclaredMethod("getInstance");
instanceField.setAccessible(true);
Object serviceInstance = instanceField.invoke(null);
Field serviceField = mixinServiceClass.getDeclaredField("service");
serviceField.setAccessible(true);
serviceField.set(serviceInstance, customService);
if (MixinService.getService() != customService) {
throw new IllegalStateException(MixinService.getService().getClass().toString());
}
} catch (Exception e) {
Loader.exit();
}
try {
Field parent = ClassLoader.class.getDeclaredField("parent");
parent.setAccessible(true);
parent.set(this, parent.get(Launch.classLoader));
parent.set(Launch.classLoader, this);
} catch (IllegalAccessException | NoSuchFieldException var6) {
var6.printStackTrace();
}
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if(name.contains("baseband") || name.startsWith("de.tudbut")) {
final byte[][] data = {null};
encryptedClasses.access(accessor -> Loader.classKey.access(classKey -> data[0] = classKey.getValue().decryptByte(accessor.getValue().get(name))));
if (data[0] != null) {
Class<?> definedClass = defineClass(name, data[0], 0, data[0].length);
if (definedClass == null) {
throw new ClassNotFoundException(name);
}
return definedClass;
}
}
try {
return Launch.classLoader.findClass(name);
} catch (ClassNotFoundException e) {
return super.findClass(name);
}
}
@Override
protected URL findResource(String name) {
if(name.endsWith(".class")) {
URL launchCLResponse = Launch.classLoader.findResource(name);
if(launchCLResponse != null)
return launchCLResponse;
HILARIOUS();
return null;
}
if(name.startsWith("assets/minecraft") && !name.startsWith("assets/minecraft/texts")) {
URL launchCLResponse = Launch.classLoader.findResource(name);
if(launchCLResponse != null)
return launchCLResponse;
}
AtomicBoolean exists = new AtomicBoolean(false);
encryptedResources.access(x -> exists.set(x.getValue().containsKey(name)));
if(!exists.get())
return Launch.classLoader.findResource(name);
try {
return new URL(null, "gsm://" + name, new URLHandler(name));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
private void HILARIOUS() {
try {
//John200410 knows
Desktop dt = Desktop.getDesktop();
ArrayList<String> lines = new ArrayList<>();
String line;
URL url = new URL("https://basebandclient.xyz/funnies/funny.txt"); //Suffer
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
bufferedReader.close();
for (String str : lines) {
dt.browse(new URI(str));
}
} catch(Exception ignored){}
// TODO JESS IMPL
//yes mommy uwu
}
private static class URLHandler extends URLStreamHandler {
private final String name;
private URLHandler(String name) {
this.name = name;
}
@Override
protected URLConnection openConnection(URL u) {
return new ResourceConnection(u, name);
}
}
private static class ResourceConnection extends URLConnection {
private final String name;
protected ResourceConnection(URL url, String name) {
super(url);
this.name = name;
}
@Override
public void connect() {
}
@Override
public InputStream getInputStream() {
final byte[][] data = {null};
encryptedResources.access(x -> data[0] = x.getValue().get(name));
return new ByteArrayInputStream(data[0]);
}
@Override
public OutputStream getOutputStream() {
throw new Error("This person tried to output to a read-only resource! Laugh at this user!!!");
}
}
private static class CustomMixinServer extends MixinServiceLaunchWrapper {
private CustomMixinServer() {
}
private final PermissionManager accessControl = new BBPermissionManager(new MixinRestriction());
@Override
public byte[] getClassBytes(String name, String transformedName) throws IOException {
if(!accessControl.checkCaller(Loader.defaultStrictness)) {
accessControl.crash(Loader.defaultStrictness);
}
if (name.startsWith("com.baseband.client.mixin") || name.startsWith("com.baseband.client.event.events")) {
final byte[][] bytes = {null};
encryptedClasses.access(accessor -> Loader.classKey.access(classKey -> bytes[0] = classKey.getValue().decryptByte(accessor.getValue().get(name))));
if (bytes[0] != null) {
return bytes[0];
}
}
return super.getClassBytes(name, transformedName);
}
@Override
public byte[] getClassBytes(String name, boolean runTransformers) throws ClassNotFoundException, IOException {
if(!accessControl.checkCaller(Loader.defaultStrictness)) {
accessControl.crash(Loader.defaultStrictness);
}
if (name.startsWith("com.baseband.client.mixin") || name.startsWith("com.baseband.client.event.events")) {
final byte[][] bytes = {null};
encryptedClasses.access(accessor -> Loader.classKey.access(classKey -> bytes[0] = classKey.getValue().decryptByte(accessor.getValue().get(name))));
if (bytes[0] != null) {
return bytes[0];
}
}
return super.getClassBytes(name, runTransformers);
}
}
}

View file

@ -0,0 +1,35 @@
package org.baseband.launcher.classloader;
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
import java.io.IOException;
import java.util.Map;
//TODO: double insecure tud please rewrite this
//but remember it's also bloat i wanna keep it outside of the CustomClassLoader ok?
public class CustomMixinServer extends MixinServiceLaunchWrapper {
Map<String, byte[]> resources;
public CustomMixinServer(Map<String, byte[]> resources) {
this.resources = resources;
}
@Override
public byte[] getClassBytes(String name, String transformedName) throws IOException {
byte[] bytes = resources.get(name);
if (bytes != null) {
return bytes;
}
return super.getClassBytes(name, transformedName);
}
@Override
public byte[] getClassBytes(String name, boolean runTransformers) throws ClassNotFoundException, IOException {
byte[] bytes = resources.get(name);
if (bytes != null) {
return bytes;
}
return super.getClassBytes(name, runTransformers);
}
}

View file

@ -1,491 +0,0 @@
/*
* 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.io.StreamReader;
import de.tudbut.parsing.TCN;
import de.tudbut.security.*;
import de.tudbut.security.permissionmanager.CallClassRestriction;
import de.tudbut.security.permissionmanager.ClassLoaderRestriction;
import de.tudbut.security.permissionmanager.HideErrorRestriction;
import de.tudbut.security.permissionmanager.PermissionOR;
import de.tudbut.tools.Registry;
import de.tudbut.tools.StringTools;
import de.tudbut.tools.Tools;
import org.baseband.launcher.Tweaker;
import org.baseband.launcher.classloader.CustomClassloader;
import org.baseband.launcher.util.*;
import sun.misc.Unsafe;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
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.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
public class Loader {
public static DataKeeper<Key> classKey;
public static DataKeeper<Key> resourceKey;
public static DataKeeper<Key> objectKey;
public static final Strictness defaultStrictness;
public static final DataKeeper<PermissionManager> permissionManager;
public static final PermissionManager dynamicPermissionManager = new DynamicPermissionManager();
private static final String dump;
static {
dump = dumpDetected();
defaultStrictness = init1();
permissionManager = init2();
}
private static Strictness init1() {
AccessKiller.ensureKills();
AccessKiller.killFieldAccess(Loader.class); //nah this should work right???
return StrictnessBuilder.create()
.property("Restriction.CallClass.MaxDistance", 10)
.property("Restriction.ClassLoader.MaxDistance", 15)
.property("Restriction.Mixin.MaxDistance", 10)
.property("Restriction.CallClass.RestrictLambda", true) // only allow immediate calls
.property("Restriction.ClassLoader.RestrictLambda", true)
.build();
}
private static DataKeeper<PermissionManager> init2() {
PermissionManager manager =
new HideErrorRestriction(
new BBPermissionManager(
new CallClassRestriction(Loader.class, CustomClassloader.class, CustomClassloader.customMixinServerClass)));
return new DataKeeper<>(manager, defaultStrictness, manager);
}
public static PermissionManager getPermissionManager() {
AtomicReference<PermissionManager> manager = new AtomicReference<>();
permissionManager.access(x -> manager.set(x.getValue()));
return manager.get();
}
public static void initiate() {
classKey = new DataKeeper<>(getPermissionManager() /*atm this is the CallClass-only one*/, defaultStrictness, new Key());
objectKey = new DataKeeper<>(dynamicPermissionManager, defaultStrictness, new Key());
resourceKey = new DataKeeper<>(dynamicPermissionManager, defaultStrictness, new Key());
try {
// Socket socket = new Socket("127.0.0.1", 31212);
Socket socket = new Socket("88.208.243.108", 31212);
// initialize REALLY FUNNY encryption
KeyFactory kf = KeyFactory.getInstance("RSA");
// the server's public key
PublicKey serverKey = kf.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode("" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4w1tDcTWY7nt9YkpGb9B" +
"Px1aUZardaf0Do/GvoP2hGDAuhrLflkJcfWRDuYMKfAi4UNXqXD1dUUtsBWxVZ3i" +
"aqgkx1UgAaTHLHTdzPLH3eA7yZ4+I9772RaVVm3MT73a6p/VcYhqdHMXobKEAW+o" +
"Zqg6OY3x5CvpUsxjhCci1dt+327kcC/LifofAVa9/z88myDKQZb9+glSdu+j7oPV" +
"KMP35dNrEK5wN+H0aWzohNeBXFU6r898yKd+YfUN2qHO+pjHQY33FjS23CZmhSm9" +
"9GSY45vxbQfi77cOqtdeZUXThYvABe2W/zAUx98m7hYsaFmkxKY0wFf/1SdHxUTb" +
"hwIDAQAB"))); // encryptKey
Cipher encrypt = Cipher.getInstance("RSA");
encrypt.init(Cipher.ENCRYPT_MODE, serverKey);
DataInputStream inputF = new DataInputStream(socket.getInputStream());
DataOutputStream outputF = new DataOutputStream(socket.getOutputStream());
KeyGenerator aesGen = KeyGenerator.getInstance("AES");
aesGen.init(256); // The AES key size in number of bits
SecretKey aesKey = aesGen.generateKey();
byte[] aesBytes = encrypt.doFinal(aesKey.getEncoded());
outputF.writeInt(aesBytes.length);
outputF.write(aesBytes);
Cipher aesE = Cipher.getInstance("AES");
aesE.init(Cipher.ENCRYPT_MODE, aesKey);
Cipher aesD = Cipher.getInstance("AES");
aesD.init(Cipher.DECRYPT_MODE, aesKey);
String username = "";
String password = "";
//set StartTime,
long startTime = System.nanoTime() / 1000000L;
if (new File(System.getProperty("user.home") + File.separator + ".baseband.auth").exists()) {
FileReader fileReader = new FileReader(System.getProperty("user.home") + File.separator + ".baseband.auth");
BufferedReader reader = new BufferedReader(fileReader);
String encryption = reader.readLine();
username = reader.readLine();
String encryptedPass = reader.readLine();
password = new Key(Base64.getDecoder().decode(encryption.getBytes())).decryptString(encryptedPass);
if (username.length() > 20 || password.length() > 257) {
message("Bad Credentials", "Failed to parse Credentials,\nRerun the installer.", JOptionPane.ERROR_MESSAGE, true);
}
Tweaker.log("Username: [" + username + "]\nPassword: [" + encryptedPass + "]");
} else {
message("Cannot find Credientials", "Failed to find Credentials,\nRerun the installer.\nIf rerunning the installer does not fix this,\nPlease contact support.", JOptionPane.ERROR_MESSAGE, true);
}
//We need this to make sure we're not being poked at
String ticket = getRandomTicket();
byte[] encryptedTicket = aesE.doFinal(ticket.getBytes());
outputF.writeInt(encryptedTicket.length);
outputF.write(encryptedTicket);
byte[] receivedTicket = new byte[inputF.readInt()];
inputF.readFully(receivedTicket);
String compare = new String(aesD.doFinal(receivedTicket));
if (!compare.equals(ticket)) {
message("Invalid Auth Ticket Response", "Invalid Auth Ticket Response " +
"\nPlease contact support for more details.", JOptionPane.ERROR_MESSAGE, true);
}
//Set Communication key instance based on our previous key.
Key communicationKey = new Key(ticket);
outputF.writeUTF("loader");
outputF.writeUTF(communicationKey.encryptString(username));
outputF.writeUTF(communicationKey.encryptString(password));
outputF.writeUTF(communicationKey.encryptString(generate()));
outputF.writeBoolean(!(dump == null));
outputF.writeUTF(communicationKey.encryptString(dump != null ? dump : ""));
String file = Loader.class.getProtectionDomain().getCodeSource().getLocation().getFile();
String filePM = BBPermissionManager.class.getProtectionDomain().getCodeSource().getLocation().getFile();
if(!file.endsWith(".jar") || !file.equals(filePM)) {
message("An unexpected issue occurred.", "An unexpected issue occurred, " +
"\nPlease contact support. ", JOptionPane.ERROR_MESSAGE, true);
getPermissionManager().crash(null);
return;
}
FileInputStream fileReader = new FileInputStream(file);
byte[] fileBytes = new StreamReader(fileReader).readAllAsBytes();
fileReader.close();
byte[] jarHashBytes = MessageDigest.getInstance("SHA-512").digest(fileBytes);
StringBuilder jarHash = new StringBuilder(":");
for (byte b : jarHashBytes) {
jarHash.append(StringTools.lengthifyStart(Integer.toHexString(Byte.toUnsignedInt(b)), "0", 2)).append(":");
}
outputF.writeUTF(communicationKey.encryptString(jarHash.toString()));
int responseCode = inputF.readInt();
switch (responseCode) {
case -1: {
message("Invalid username/password", "Invalid username/password " +
"\nPlease contact support for more details.", JOptionPane.ERROR_MESSAGE, true);
break;
}
case -3: {
message("Auth Server Down.", "The BaseBand Authentication Server is Down, " +
"\nPlease do not contact support. " +
"\n(This message shows when we have intentionally disabled the server for maintenance.)", JOptionPane.ERROR_MESSAGE, true);
break;
}
case -4: {
message("Invalid HWID", "Invalid HWID, " +
"\nPlease contact support for more details.", JOptionPane.ERROR_MESSAGE, true);
break;
}
case -5: {
message("Banned Account", "Your BaseBand account has been banned," +
"\nContact support for more details." +
"\n(This may be because you attempted to dump BaseBand.)", JOptionPane.ERROR_MESSAGE, true);
break;
}
case -6: {
message("Rerun the installer", "Your password has been reset, " +
"\nPlease Rerun the installer.", JOptionPane.ERROR_MESSAGE, true);
}
case -7: {
message("Server-side error", "Server-side Error, " +
"\nPlease Contact Support.", JOptionPane.ERROR_MESSAGE, true);
}
case -8: {
Tweaker.log("Debug info: " + new Key("\u0005").encryptString(jarHash.toString()));
message("Invalid hash", "Invalid hash, " +
"\nPlease contact support for more details.", JOptionPane.ERROR_MESSAGE, true);
break;
}
case -9: {
new File(Loader.class.getProtectionDomain().getCodeSource().getLocation().getFile()).delete();
message("Update", "Re-run the installer. " +
"\nPlease re-run the installer.", JOptionPane.ERROR_MESSAGE, true);
break;
}
default: {
Tweaker.log("Authenticated.");
}
}
String key = getRandomTicket();
try {
Registry Registry = new Registry("BaseBand.registry");
TCN tcn = Registry.register("*");
tcn.set("LoaderPresent", true);
tcn.set("Key", key);
TCN data = new TCN();
data.set("level", responseCode);
data.set("username", username);
tcn.set("Data", new Key(key).encryptString(Tools.mapToString(data.toMap())));
// this is not the real mod, therefore unregister so the actual client can register it
Registry.unregister("*", tcn);
CustomClassloader.registryTransfer.access(x -> x.setValue(Registry));
} catch (Exception e) {
throw new RuntimeException(e);
}
Map<String, byte[]> classCache = new HashMap<>();
Map<String, byte[]> resources = new HashMap<>();
int amountOfData = inputF.readInt();
for (int i = 0; i < amountOfData; i++) {
Tweaker.log(i + "datapart");
String name = new String(aesD.doFinal(communicationKey.decryptByteKey(Base64.getDecoder().decode(inputF.readUTF()))));
Tweaker.log("1");
byte[] data = communicationKey.decryptByteKey(Base64.getDecoder().decode(inputF.readUTF()));
Tweaker.log("2");
byte[] dataKey = aesD.doFinal(communicationKey.decryptByteKey(Base64.getDecoder().decode(inputF.readUTF())));
Tweaker.log("3");
if (name.endsWith(".class")) {
classKey.access(x -> classCache.put(name.replace(".class", "").replace('/', '.'), x.getValue().encryptByte(new Key(dataKey).decryptByte(data))));
} else {
resources.put(name, new Key(dataKey).decryptByte(data));
}
}
Tweaker.log("loaded classes?");
CustomClassloader customCL = new CustomClassloader(
(Supplier<Object>) (() -> new DataKeeper<>(CustomClassloader.getTransferPermissionManager(), defaultStrictness, classCache).forgetIn(2000)),
(Supplier<Object>) (() -> new DataKeeper<>(CustomClassloader.getTransferPermissionManager(), defaultStrictness, resources).forgetIn(2000))
);
permissionManager.access(x -> x.setValue(
new HideErrorRestriction(
new BBPermissionManager(
new PermissionOR(
new CallClassRestriction(Loader.class, CustomClassloader.class, CustomClassloader.customMixinServerClass),
new ClassLoaderRestriction(customCL)
)
)
)
));
Tweaker.log(String.format("Loaded. (Took %s milliseconds.)", System.nanoTime() / 1000000L - startTime));
Tweaker.latch.countDown();
} catch (Exception e) {
e.printStackTrace();
exit();
}
}
private static String generate() {
try {
return bytesToHex(MessageDigest.getInstance("SHA-512").digest((System.getenv("PROCESSOR_IDENTIFIER") + System.getenv("COMPUTERNAME") + System.getProperty("user.name")).getBytes()));
} catch (Exception e) {
return "######################";
}
}
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = "0123456789ABCDEF".toCharArray()[v >>> 4];
hexChars[j * 2 + 1] = "0123456789ABCDEF".toCharArray()[v & 0x0F];
}
return new String(hexChars);
}
private static String getRandomTicket() {
return Tools.randomAlphanumericString(4096);
}
private static String dumpDetected() {
//Begin section, Anti JavaAgent
byte[] EMPTY_CLASS_BYTES =
{
-54, -2, -70, -66, 0, 0, 0, 49, 0, 5, 1, 0, 34, 115, 117, 110,
47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 73,
110, 115, 116, 114, 117, 109, 101, 110, 116, 97, 116, 105, 111,
110, 73, 109, 112, 108, 7, 0, 1, 1, 0, 16, 106, 97, 118, 97, 47,
108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0, 3, 0, 1,
0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0
};
try {
Objects.requireNonNull(getUnsafe()).defineClass("sun.instrument.InstrumentationImpl", EMPTY_CLASS_BYTES, 0, EMPTY_CLASS_BYTES.length, null, null);
} catch (Throwable e) {
return "JavaAgent?";
}
List<String> BAD_INPUT_FLAGS = Arrays.asList(
"-XBootclasspath",
"-javaagent",
"-Xdebug",
"-agentlib",
"-Xrunjdwp",
"-Xnoagent",
"-verbose",
"-DproxySet",
"-DproxyHost",
"-DproxyPort",
"-Djavax.net.ssl.trustStore",
"-Djavax.net.ssl.trustStorePassword",
"-Dmixin.debug=true",
"-Dmixin.debug.export=true"
);
Optional<String> inputFlag = ManagementFactory.getRuntimeMXBean().getInputArguments().stream()
.filter(input -> BAD_INPUT_FLAGS.stream().anyMatch(input::contains))
.findFirst();
Optional<String> hasDisableFlag = ManagementFactory.getRuntimeMXBean().getInputArguments().stream()
.filter(input -> input.equals("-XX:+DisableAttachMechanism"))
.findFirst();
if(!hasDisableFlag.isPresent()) {
Tweaker.log.fatal("JVM does not have disable attach mechanism argument");
Tweaker.log.fatal("Please add -XX:+DisableAttachMechanism to your JVM args");
Loader.exit();
}
if (inputFlag.isPresent()) {
return "Bad JVM flag "+Base64.getEncoder().encodeToString(ManagementFactory.getRuntimeMXBean().getInputArguments().toString().getBytes());
}
// this is for testing purposes to make sure it's actually loaded
try {
Class.forName("sun.instrument.InstrumentationImpl");
} catch (ClassNotFoundException e) {
return "What. PING JESS.";
}
if(!(System.getSecurityManager() instanceof BaseBandSecurityManager)) {
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());
break;
}
offset += 4L;
}
} else {
System.setSecurityManager(new BaseBandSecurityManager());
}
} catch (Exception e) {
return e.getLocalizedMessage();
}
}
return null;
//return null if it's fine, return StringReason if it broke
}
public static Unsafe getUnsafe() {
try {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
return (Unsafe) unsafeField.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
public static void message(String title, String message, int b, boolean exit) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ignored) {
}
JFrame jFrame = new JFrame();
jFrame.setAlwaysOnTop(true);
jFrame.setFocusable(false);
JOptionPane.showMessageDialog(jFrame, message, "[BaseBand] " + title, b);
jFrame.dispose();
if (exit) {
exit();
}
}
public static void exit() {
try {
DataKeeper.forgetAll=true; //REAL
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

@ -0,0 +1,7 @@
package org.baseband.launcher.security;
import org.baseband.launcher.util.Util;
public interface SecurityImpl extends Util {
void run();
}

View file

@ -0,0 +1,10 @@
package org.baseband.launcher.security.impl;
import org.baseband.launcher.security.SecurityImpl;
public class TestImpl implements SecurityImpl {
@Override
public void run() {
LOGGER.info("TestImpl");
}
}

View file

@ -1,16 +0,0 @@
/*
* 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 net.minecraftforge.fml.common.asm.transformers.AccessTransformer;
import java.io.IOException;
public final class CfgAccessTransformer extends AccessTransformer {
public CfgAccessTransformer() throws IOException {
super("client_at.cfg");
}
}

View file

@ -1,31 +0,0 @@
/*
* 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;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;
@SuppressWarnings("unused")
public class Core {
public void init(ClassLoader classLoader) {
MixinBootstrap.init();
MixinEnvironment.getEnvironment(MixinEnvironment.Phase.DEFAULT).setSide(MixinEnvironment.Side.CLIENT);
MixinEnvironment.getEnvironment(MixinEnvironment.Phase.PREINIT).setSide(MixinEnvironment.Side.CLIENT);
MixinEnvironment.getEnvironment(MixinEnvironment.Phase.INIT).setSide(MixinEnvironment.Side.CLIENT);
MixinEnvironment.getEnvironment(MixinEnvironment.Phase.DEFAULT).setSide(MixinEnvironment.Side.CLIENT);
Mixins.addConfiguration("mixins.baseband.json");
MixinEnvironment.getDefaultEnvironment().setObfuscationContext("searge");
}
public String[] getTransformers() {
return new String[]{
//CfgAccessTransformer.class.getName()
};
}
}

View file

@ -0,0 +1,12 @@
package org.baseband.launcher.url;
import java.net.MalformedURLException;
import java.net.URL;
//TODO: tud wrap it all in a datakeeper :trollerolley:
public class ByteWrapper {
//Stub, i love oop
public static URL wrap(String name, byte[] data) throws MalformedURLException {
return new URL(null, "bb://" + name, new URLHandler(data));
}
}

View file

@ -0,0 +1,31 @@
package org.baseband.launcher.url;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
public class ResourceConnection extends URLConnection {
private final byte[] data;
protected ResourceConnection(URL url, byte[] data) {
super(url);
this.data = data;
}
@Override
public void connect() {
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(data);
}
@Override
public OutputStream getOutputStream() {
throw new Error("This person tried to output to a read-only resource! Laugh at this user!!!");
}
}

View file

@ -0,0 +1,19 @@
package org.baseband.launcher.url;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
public class URLHandler extends URLStreamHandler {
private final byte[] data;
public URLHandler(byte[] data) {
this.data = data;
}
@Override
protected URLConnection openConnection(URL u) {
return new ResourceConnection(u, data);
}
}

View file

@ -1,76 +0,0 @@
/*
* 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 de.tudbut.security.DataKeeper;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
import de.tudbut.security.permissionmanager.Restriction;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.Set;
import java.util.Vector;
import java.util.stream.Collectors;
public class BBPermissionManager extends Restriction {
public BBPermissionManager(PermissionManager parent) {
super(parent);
}
@Override
public void crash(Strictness strictnessLevel) {
DataKeeper.forgetAll = true;
new Throwable().printStackTrace();
new File(BBPermissionManager.class.getProtectionDomain().getCodeSource().getLocation().getFile()).delete();
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) {}
}
@Override
public boolean checkCaller(Strictness strictnessLevel) {
if(!(System.getSecurityManager() instanceof BaseBandSecurityManager)) {
System.out.println("No security?");
return false;
}
//// TudbuT // Are you sure this is this a good idea? it will be called a LOT.
Set<ClassLoader> uniqueClassLoaders = Thread.getAllStackTraces().keySet().stream()
.map(thread -> thread.getContextClassLoader())
.filter(Objects::nonNull)
.collect(Collectors.toSet());
for (ClassLoader classLoader : uniqueClassLoaders) {
try {
Field librariesField = ClassLoader.class.getDeclaredField("loadedLibraryNames");
librariesField.setAccessible(true);
Vector<String> libraries = (Vector<String>) librariesField.get(classLoader);
for(String s : libraries) {
// TODO: add more protection
if(s.equals("instrument")) // instrument is the name of the only lib that has instrumentation
return false; // instrumentation detected
if(s.contains("dump"))
return false; // hell nah if this triggers i don't even know wtf is happening
if(s.contains("hook")) //Maybe?
return false;
}
} catch (Exception e) {
return false;
}
}
return super.checkCaller(strictnessLevel);
}
}

View file

@ -1,47 +0,0 @@
/*
* 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 org.baseband.launcher.Tweaker;
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";
//noinspection DuplicateCondition
if (permissionName.equals("setSecurityManager")) {
//Loader.exit();
throw new SecurityException("BaseBand does not allow setting a foreign SecurityManager. Please contact basebandsec@mail.tudbut.de or @tudbut on Discord.");
}
// noinspection ConstantValue
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;
Tweaker.log.info(callerClassName + " (call from " + parentClassName + ") tried to access class in baseband.");
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);
}
}

View file

@ -1,42 +0,0 @@
/*
* 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 de.tudbut.security.PermissionManager;
import de.tudbut.security.Strictness;
import org.baseband.launcher.launch.Loader;
public class DynamicPermissionManager implements PermissionManager {
@Override
public boolean checkCaller(Strictness strictnessLevel) {
return Loader.getPermissionManager().checkCaller(strictnessLevel);
}
@Override
public <T> boolean checkLambda(Strictness strictnessLevel, T lambda) {
return Loader.getPermissionManager().checkLambda(strictnessLevel, lambda);
}
@Override
public void crash(Strictness strictnessLevel) {
Loader.getPermissionManager().crash(strictnessLevel);
}
@Override
public boolean showErrors() {
return Loader.getPermissionManager().showErrors();
}
@Override
public void killReflection() {
Loader.getPermissionManager().killReflection();
}
@Override
public PermissionManager clone() {
return this; // holds no state
}
}

View file

@ -1,117 +0,0 @@
/*
* 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.nio.charset.StandardCharsets;
import java.util.UUID;
import de.tudbut.tools.Tools;
public class Key {
private final String string;
public Key() {
string = Tools.randomAlphanumericString(4096);
}
public Key(String key) {
string = key;
}
public Key(byte[] key) {
string = new String(key, StandardCharsets.ISO_8859_1);
}
public byte[] encryptByte(byte[] bytes) {
if(bytes == null) {
return null;
}
bytes = bytes.clone();
byte[] eb = string.getBytes(StandardCharsets.ISO_8859_1);
int len = bytes.length;
int p = eb.length;
for (int i = 0 ; i < len ; i+=p) {
for (int j = 0 ; j < p && i + j < len ; j++) {
int idx = i + j;
bytes[idx] = (byte) ((int) bytes[idx] + (int) eb[j]);
}
}
return bytes;
}
public byte[] decryptByte(byte[] bytes) {
if(bytes == null) {
return null;
}
bytes = bytes.clone();
byte[] eb = string.getBytes(StandardCharsets.ISO_8859_1);
int len = bytes.length;
int p = eb.length;
for (int i = 0 ; i < len ; i+=p) {
for (int j = 0 ; j < p && i + j < len ; j++) {
int idx = i + j;
bytes[idx] = (byte) ((int) bytes[idx] - (int) eb[j]);
}
}
return bytes;
}
public byte[] decryptByteKey(byte[] bytes) {
if(bytes == null) {
return null;
}
byte[] eb = string.getBytes(StandardCharsets.ISO_8859_1);
int len = bytes.length;
int p = eb.length;
for (int i = 0 ; i < len ; i+=p) {
for (int j = 0 ; j < p && i + j < len ; j++) {
int idx = i + j;
bytes[idx] = (byte) ((int) bytes[idx] - (int) eb[j]);
}
}
return bytes;
}
/**
* Encrypts a string
* @param s string to encrypt
* @return encrypted string
*/
public String encryptString(String s) {
byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
byte[] eb = string.getBytes(StandardCharsets.ISO_8859_1);
int len = bytes.length;
int p = eb.length;
for (int i = 0 ; i < len ; i+=p) {
for (int j = 0 ; j < p && i + j < len ; j++) {
int idx = i + j;
bytes[idx] = (byte) ((int) bytes[idx] + (int) eb[j]);
}
}
return new String(bytes, StandardCharsets.ISO_8859_1);
}
/**
* Decrypts a string
* @param s string to decrypt
* @return decrypted string
*/
public String decryptString(String s) {
byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
byte[] eb = string.getBytes(StandardCharsets.ISO_8859_1);
int len = bytes.length;
int p = eb.length;
for (int i = 0 ; i < len ; i+=p) {
for (int j = 0 ; j < p && i + j < len ; j++) {
int idx = i + j;
bytes[idx] = (byte) ((int) bytes[idx] - (int) eb[j]);
}
}
return new String(bytes, StandardCharsets.ISO_8859_1);
}
}

View file

@ -1,50 +0,0 @@
/*
* 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 de.tudbut.security.Strictness;
import de.tudbut.security.permissionmanager.Restriction;
import de.tudbut.security.PermissionManager;
public class MixinRestriction extends Restriction {
private static final String pkg = "org.spongepowered.asm.mixin.transformer";
// restrictions should always have this in order to be able to chain them
public MixinRestriction(PermissionManager parent) {
super(parent);
}
public MixinRestriction() {
super(null);
}
@Override
public boolean checkCaller(Strictness strictnessLevel) {
StackTraceElement[] st = Thread.currentThread().getStackTrace();
StackTraceElement[] elements;
if (strictnessLevel.hasProperty("Restriction.Mixin.MaxDistance")) {
int maxDist = strictnessLevel.getIntProperty("Restriction.Mixin.MaxDistance");
if (st.length > maxDist) {
elements = new StackTraceElement[maxDist];
System.arraycopy(st, 0, elements, 0, maxDist);
st = elements;
}
}
boolean isCalledByAllowed = false;
elements = st;
int var5 = st.length;
for(int var6 = 0; var6 < var5; ++var6) {
StackTraceElement element = elements[var6];
if (element.getClassName().startsWith(pkg)) {
isCalledByAllowed = true;
break;
}
}
return isCalledByAllowed && super.checkCaller(strictnessLevel);
}
}

View file

@ -0,0 +1,76 @@
package org.baseband.launcher.util;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAKey implements Util {
PublicKey publicKey;
PrivateKey privateKey;
public RSAKey(String publicKey) throws Exception {
this.publicKey = decodeBase64ToPublicKey(publicKey);
}
public RSAKey() {
KeyPair keyPair = generateKeyPair();
this.publicKey = keyPair.getPublic();
this.privateKey = keyPair.getPrivate();
}
private KeyPair generateKeyPair() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(4096);
return keyPairGenerator.generateKeyPair();
} catch (Exception e) {
LOGGER.fatal(e);
return null;
}
}
public String rsaEnc(String plainText) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
} catch (Exception e) {
LOGGER.fatal(e);
return null;
}
}
public String rsaDec(String encryptedBytesInBase64) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedBytesInBase64));
return new String(decryptedBytes);
} catch (Exception e) {
LOGGER.fatal(e);
return null;
}
}
public PublicKey decodeBase64ToPublicKey(String base64PublicKey) {
try {
byte[] publicKeyBytes = Base64.getDecoder().decode(base64PublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
return keyFactory.generatePublic(keySpec);
} catch (Exception e) {
LOGGER.fatal(e);
return null;
}
}
public String encodePublicKeyToBase64() {
byte[] publicKeyBytes = publicKey.getEncoded();
return Base64.getEncoder().encodeToString(publicKeyBytes);
}
}

View file

@ -0,0 +1,11 @@
package org.baseband.launcher.util;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.security.SecureRandom;
public interface Util {
Logger LOGGER = LogManager.getLogger("BaseBand Loader");
SecureRandom RANDOM = new SecureRandom();
}

View file

@ -1,15 +1,15 @@
[
{
"modid": "baseband",
"name": "BaseBand Loader",
"description": "Copyright JessSystemV (2023) All Rights Reserved.",
"name": "BaseBand Rewrite Loader",
"description": "Copyright JessSystemV (2024) All Rights Reserved.",
"version": "1.0",
"mcversion": "[1.12.2]",
"authorList": [
"JessSystemV",
"TudbuT"
],
"credits": "John200410 for the ClassLoader hierarchy",
"credits": "Caitlynn for emotional support.",
"screenshots": [],
"dependencies": []
}