mostly make loader work, mixins still broken (causing a crash)
Some checks failed
/ Build BaseBand DSM & Broadway (push) Successful in 5m6s
/ Build BaseBand Loader (push) Has been cancelled
/ Build BaseBand Server (push) Successful in 3m19s

This commit is contained in:
Daniella / Tove 2024-06-09 23:31:27 +02:00
parent 9d0d39df03
commit 1a9d14ef10
Signed by: TudbuT
GPG key ID: B3CF345217F202D3
38 changed files with 728 additions and 355 deletions

1
.gitignore vendored
View file

@ -12,3 +12,4 @@
valid_hashes.txt
Obf.tar
/Server/run/

View file

@ -0,0 +1,50 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BaseBandRewrite [build-full]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
<option value="proguard" />
<option value="proguardRelease" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration default="false" name="BaseBandRewrite [build-full]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
<option value="proguard" />
<option value="proguardRelease" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>

32
.run/mobf.run.xml Normal file
View file

@ -0,0 +1,32 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="mobf" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/mobf.sh" />
<option name="SCRIPT_OPTIONS" value="*/build/proguard/BaseBand-*.jar" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/fish" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
<configuration default="false" name="mobf" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="bash mobf.sh */build/proguard/BaseBand-*.jar" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/mobf.sh" />
<option name="SCRIPT_OPTIONS" value="*/build/proguard/BaseBand-*.jar" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/bash" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="false" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs />
<method v="2" />
</configuration>
</component>

32
.run/push_local.run.xml Normal file
View file

@ -0,0 +1,32 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="push_local" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/push_local.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/bash" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="false" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
<configuration default="false" name="push_local" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/push_local.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/bash" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="false" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
</component>

Binary file not shown.

View file

@ -11,15 +11,24 @@
-obfuscationdictionary dictionary.txt
-classobfuscationdictionary dictionary.txt
-packageobfuscationdictionary dictionary.txt
-repackageclasses org.baseband.prod
-repackageclasses com.baseband.prod
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,*Annotation*,Synthetic,EnclosingMethod
-ignorewarnings
-overloadaggressively
# keep things meant to exist in prod
-keep class com.baseband.prod.** { *; }
-keep class com.baseband.client.mixins.** { *; }
-keep class com.baseband.client.DevStub {
public <methods>;
}
-keep class com.baseband.launcher.Tweaker {
public <methods>;
}
# jna
-keep class com.sun.** { *; }
-keep class oshi.** { *; }
# spongepowered
-keep class org.** { *; }

View file

@ -23,7 +23,7 @@ public class BaseBand {
public static final Logger LOGGER = LogManager.getLogger("BaseBand");
public static final SecureRandom RANDOM = new SecureRandom();
public static BaseBand INSTANCE; { INSTANCE = this; }
public static BaseBand INSTANCE = new BaseBand();
public static String buildString = "Broadway";
public static final EventManager eventManager = new EventManager(LOGGER::error);

View file

@ -26,7 +26,7 @@ public class DevStub implements IFMLLoadingPlugin {
@Mod.EventHandler
public void onInit(FMLPostInitializationEvent event) {
BaseBand.buildString = "Dark Side of the Moon";
new BaseBand().onInit();
BaseBand.INSTANCE.onInit();
}
@Override

View file

@ -0,0 +1,15 @@
package com.baseband.prod;
import com.baseband.client.BaseBand;
public class LoadHandler {
public static void loaded() {
BaseBand.LOGGER.info("We have been loaded!");
try {
Class.forName("com.baseband.launcher.Tweaker").getDeclaredMethod("loaded", Class.class).invoke(null, BaseBand.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -76,7 +76,7 @@ dependencies {
jarLibs(fileTree(dir: "lib", include: "*.jar"));
jarLibs(group: 'com.github.oshi', name: 'oshi-core', version: '6.5.0');
//jarLibs(group: 'com.github.oshi', name: 'oshi-core', version: '1.+');
annotationProcessor('org.spongepowered:mixin:0.8.5:processor') {
exclude module: 'gson'
@ -111,7 +111,7 @@ jar {
manifest {
attributes(
'TweakClass': 'org.baseband.launcher.Tweaker',
'TweakClass': 'com.baseband.launcher.Tweaker',
'TweakOrder': 0,
'FMLCorePluginContainsFMLMod': 'true',
'ForceLoadAsMod': 'true'

Binary file not shown.

Binary file not shown.

1
Loader/lib/TuddyLIB.jar Symbolic link
View file

@ -0,0 +1 @@
../../Client/libs/TuddyLIB.jar

View file

@ -0,0 +1,153 @@
package com.baseband.launcher;
import de.tudbut.io.TypedInputStream;
import de.tudbut.io.TypedOutputStream;
import de.tudbut.parsing.JSON;
import de.tudbut.parsing.TCN;
import de.tudbut.tools.Hasher;
import de.tudbut.tools.Tools;
import de.tudbut.tools.encryption.Key;
import com.baseband.launcher.classloader.CustomClassLoader;
import com.baseband.launcher.util.RSAKey;
import com.baseband.launcher.util.Util;
import de.tudbut.tools.encryption.RawKey;
import oshi.SystemInfo;
import oshi.hardware.Processor;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.stream.Collectors;
public class Loader implements Util {
public static Class<?> baseBandClass;
public static Object baseBand;
public enum Response {
OK,
FORBIDDEN,
OUTDATED,
BANNED,
RESET,
SERVER_ERROR,
SERVER_DOWN,
HWID_INVALID,
LOGIN_LOCKOUT,
}
private static final SystemInfo systemInfo = new SystemInfo();
private static CustomClassLoader classLoader;
public Loader() {
try(Socket client = new Socket("baseband.lol", 40000)) {
TypedInputStream inputStream = new TypedInputStream(client.getInputStream());
TypedOutputStream outputStream = new TypedOutputStream(client.getOutputStream());
RSAKey rsaKey = new RSAKey(inputStream.readString()); //get publickey
Key key = new Key();
outputStream.writeString(rsaKey.rsaEnc(key.toString().getBytes(StandardCharsets.ISO_8859_1)));
outputStream.writeString(key.encryptString(Tools.mapToString(getData().toMap())));
Response status = Response.values()[inputStream.readInt()];
if(status == Response.OK) {
try {
HashMap<String, byte[]> data = new HashMap<>();
RawKey rk = new RawKey(key.toBytes());
int n = inputStream.readInt();
for (int i = 0; i < n; i++) {
data.put(rk.decryptString(inputStream.readString()), rk.decryptBytes(inputStream.readByteArray()));
}
LOGGER.info("BaseBand downloaded: " + data.size() + " classes.");
classLoader = new CustomClassLoader(data);
classLoader.inject();
} catch (Exception e) {
LOGGER.fatal("BaseBand failed to (down)load.");
e.printStackTrace();
}
}
else {
LOGGER.fatal("Server refused.");
LOGGER.error(status.ordinal());
exit();
}
} catch (Exception e) {
LOGGER.fatal("Failed to connect to Server-side.");
LOGGER.fatal(e.getMessage());
exit();
}
}
public static void informClient() {
classLoader.informClient();
}
public static void loaded(Class<?> baseBandClass) {
LOGGER.info("BaseBand was loaded successfully.");
Loader.baseBandClass = baseBandClass;
try {
baseBand = Arrays.stream(baseBandClass.getDeclaredFields()).filter(x -> x.getType() == baseBandClass).findFirst().get().get(null);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public static void onInit() {
try {
Arrays.stream(baseBandClass.getDeclaredMethods()).filter(x -> (x.getModifiers() & Modifier.STATIC) == 0).findFirst().get().invoke(baseBand);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static TCN getData() throws Exception {
File file = new File("baseband.login");
Key key = new Key(Hasher.sha256hex(getToken())); //We encrypt using the hwid
System.out.println(key);
if (file.exists()) {
TCN tcn = new TCN();
FileReader fileReader = new FileReader(file);
BufferedReader reader = new BufferedReader(fileReader);
tcn.set("username", key.decryptString(reader.readLine()));
tcn.set("password", key.decryptString(reader.readLine()));
tcn.set("hardware-id", getToken());
LOGGER.info("MAGIC " + Base64.getEncoder().encodeToString(key.encryptString("Logging in with " + JSON.write(tcn)).getBytes()));
return tcn;
}
exit();
throw new RuntimeException();
}
private static String getToken() {
String string = //this is intellij's fault I wanted a string-builder
Arrays.stream(systemInfo.getHardware().getProcessors()).map(Processor::getIdentifier).collect(Collectors.joining(";;")) +
systemInfo.getOperatingSystem().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

@ -3,21 +3,38 @@
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package org.baseband.launcher;
package com.baseband.launcher;
import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.spongepowered.asm.launch.MixinTweaker;
import java.io.File;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@SuppressWarnings("unused")
@Mod(modid = "baseband")
public class Tweaker implements ITweaker {
public static CountDownLatch latch;
public static void loaded(Class<?> baseBandClass) {
Loader.loaded(baseBandClass);
}
private final MixinTweaker wrapped;
@Mod.EventHandler
public void onPreInit(FMLPreInitializationEvent event) {
Loader.informClient();
}
@Mod.EventHandler
public void onInit(FMLPostInitializationEvent event) {
Loader.onInit();
}
public Tweaker() {
wrapped = new MixinTweaker();
}

View file

@ -1,5 +1,6 @@
package org.baseband.launcher.classloader;
package com.baseband.launcher.classloader;
import com.baseband.launcher.url.URLWrapper;
import de.tudbut.security.DataKeeper;
import de.tudbut.security.PermissionManager;
import de.tudbut.security.StrictnessBuilder;
@ -7,10 +8,9 @@ import de.tudbut.security.permissionmanager.CallClassRestriction;
import de.tudbut.security.permissionmanager.ClassLoaderRestriction;
import de.tudbut.security.permissionmanager.PermissionOR;
import net.minecraft.launchwrapper.Launch;
import org.baseband.launcher.Loader;
import org.baseband.launcher.url.URLWrapper;
import org.baseband.launcher.util.Util;
import com.baseband.launcher.util.Util;
import org.spongepowered.asm.mixin.transformer.MixinTransformer;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
import java.io.IOException;
@ -18,22 +18,25 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import static com.baseband.launcher.Loader.exit;
public class CustomClassLoader extends ClassLoader implements Util {
private final DataKeeper<Map<String, byte[]>> binaryKeeper;
private final DataKeeper<PermissionManager> mixinPermissionManager;
public CustomClassLoader(Map<String, byte[]> resources) {
public CustomClassLoader(Map<String, byte[]> data) {
this.binaryKeeper = new DataKeeper<>(
new PermissionOR(new ClassLoaderRestriction(this), new CallClassRestriction(CustomClassLoader.class, CustomClassLoader.class)),
StrictnessBuilder.create()
.property("Restriction.ClassLoader.RestrictLambda", true)
.property("Restriction.ClassLoader.MaxDistance", 3)
.property("Restriction.ClassLoader.MaxDistance", 5)
.property("Restriction.CallClass.RestrictLambda", true)
.property("Restriction.CallClass.MaxDistance", 3)
.property("Restriction.CallClass.MaxDistance", 5)
.build(),
resources
data
);
PermissionManager mixinRestriction = new CallClassRestriction(MixinTransformer.class);
mixinRestriction.killReflection();
@ -48,15 +51,18 @@ public class CustomClassLoader extends ClassLoader implements Util {
public void inject() {
try {
CustomMixinServer customService = new CustomMixinServer();
CustomMixinServer customService = new CustomMixinServer(this);
Class<?> mixinServiceClass = Class.forName("org.spongepowered.asm.service.MixinService");
Method instanceField = mixinServiceClass.getDeclaredMethod("getInstance");
instanceField.setAccessible(true);
Object serviceInstance = instanceField.invoke(null);
Method instanceMethod = mixinServiceClass.getDeclaredMethod("getInstance");
instanceMethod.setAccessible(true);
Object serviceInstance = instanceMethod.invoke(null);
Field serviceField = mixinServiceClass.getDeclaredField("service");
serviceField.setAccessible(true);
serviceField.set(serviceInstance, customService);
LOGGER.debug("Injected Mixin Service.");
LOGGER.info("Injected Mixin Service.");
if (MixinService.getService() != customService) {
throw new IllegalStateException(MixinService.getService().getClass().toString());
}
Field parent = ClassLoader.class.getDeclaredField("parent");
parent.setAccessible(true);
@ -65,7 +71,16 @@ public class CustomClassLoader extends ClassLoader implements Util {
LOGGER.debug("Set parent of Launch.classLoader.");
} catch (Exception e) {
LOGGER.fatal(e);
Loader.exit();
exit();
}
}
public void informClient() {
LOGGER.info("Informing client that it has been loaded.");
try {
this.loadClass("com.baseband.prod.LoadHandler").getDeclaredMethod("loaded").invoke(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@ -85,7 +100,7 @@ public class CustomClassLoader extends ClassLoader implements Util {
binaryKeeper.access(m -> data[0] = m.getValue().get(name));
if (data[0] == null) {
return Launch.classLoader.findResource(name);
return super.findResource(name);
}
try {
return URLWrapper.wrap(name, data[0]);
@ -96,17 +111,48 @@ public class CustomClassLoader extends ClassLoader implements Util {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Set<ClassLoader> uniqueClassLoaders = Thread.getAllStackTraces().keySet().stream()
.map(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
exit();
if(s.contains("dump")) // hell nah if this triggers i don't even know wtf is happening
exit();
if(s.contains("hook")) //Maybe?
exit();
}
} catch (Exception e) {
exit();
}
}
final byte[][] bytes = {null};
binaryKeeper.access(m -> bytes[0] = m.getValue().get(name));
binaryKeeper.access(m -> bytes[0] = m.getValue().get(name.replace('.', '/') + ".class"));
if (bytes[0] != null) {
return defineClass(name, bytes[0], 0, bytes[0].length);
}
return super.findClass(name);
try {
return Launch.classLoader.findClass(name);
} catch (ClassNotFoundException e) {
return super.findClass(name);
}
}
public class CustomMixinServer extends MixinServiceLaunchWrapper {
public static class CustomMixinServer extends MixinServiceLaunchWrapper {
private final CustomClassLoader parent;
public CustomMixinServer() {
public CustomMixinServer(CustomClassLoader parent) {
this.parent = parent;
}
@Override
@ -123,12 +169,12 @@ public class CustomClassLoader extends ClassLoader implements Util {
private byte[] getBytes(String name) {
PermissionManager[] pm = new PermissionManager[1];
mixinPermissionManager.access(x -> pm[0] = x.getValue());
if(!name.startsWith("com/baseband/client/mixins") || !pm[0].checkCaller(mixinPermissionManager.getStrictness()))
parent.mixinPermissionManager.access(x -> pm[0] = x.getValue());
if(!name.startsWith("com/baseband/client/mixins") || !pm[0].checkCaller(parent.mixinPermissionManager.getStrictness()))
return null;
final byte[][] bytes = {null};
binaryKeeper.access(m -> bytes[0] = m.getValue().get(name));
parent.binaryKeeper.access(m -> bytes[0] = m.getValue().get(name));
return bytes[0];
}
}

View file

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

View file

@ -1,6 +1,6 @@
package org.baseband.launcher.security.impl;
package com.baseband.launcher.security.impl;
import org.baseband.launcher.security.SecurityImpl;
import com.baseband.launcher.security.SecurityImpl;
public class TestImpl implements SecurityImpl {
@Override

View file

@ -1,4 +1,4 @@
package org.baseband.launcher.url;
package com.baseband.launcher.url;
import java.net.URL;
import java.net.URLConnection;

View file

@ -1,4 +1,4 @@
package org.baseband.launcher.url;
package com.baseband.launcher.url;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

View file

@ -1,4 +1,4 @@
package org.baseband.launcher.url;
package com.baseband.launcher.url;
import java.net.MalformedURLException;
import java.net.URL;

View file

@ -1,7 +1,10 @@
package org.baseband.launcher.util;
package com.baseband.launcher.util;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
@ -12,21 +15,24 @@ public class RSAKey implements Util {
PrivateKey privateKey;
public RSAKey(String publicKey) {
this.publicKey = decodeBase64ToPublicKey(publicKey);
this.publicKey = decodePublicKey(publicKey);
}
public RSAKey() {
KeyPair keyPair = generateKeyPair();
this.publicKey = keyPair.getPublic();
this.privateKey = keyPair.getPrivate();
}
public RSAKey(KeyPair keyPair) {
this.publicKey = keyPair.getPublic();
this.privateKey = keyPair.getPrivate();
}
private KeyPair generateKeyPair() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(4096);
keyPairGenerator.initialize(1024 * 9);
return keyPairGenerator.generateKeyPair();
} catch (Exception e) {
LOGGER.fatal(e);
@ -34,35 +40,34 @@ public class RSAKey implements Util {
}
}
public String rsaEnc(String plainText) {
public String rsaEnc(byte[] plainText) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
return Base64.getEncoder().encodeToString(cipher.doFinal(plainText));
} catch (Exception e) {
LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public String rsaDec(String encryptedBytesInBase64) {
public byte[] 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);
return cipher.doFinal(Base64.getDecoder().decode(encryptedBytesInBase64));
} catch (Exception e) {
LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public PublicKey decodeBase64ToPublicKey(String base64PublicKey) {
public static RSAPublicKey decodePublicKey(String b64) {
try {
byte[] publicKeyBytes = Base64.getDecoder().decode(base64PublicKey);
byte[] bytes = Base64.getDecoder().decode(b64);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
return keyFactory.generatePublic(keySpec);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
LOGGER.fatal(e);
throw new RuntimeException(e);
@ -73,4 +78,21 @@ public class RSAKey implements Util {
byte[] publicKeyBytes = publicKey.getEncoded();
return Base64.getEncoder().encodeToString(publicKeyBytes);
}
public static RSAPrivateKey decodePrivateKey(String b64) {
try {
byte[] bytes = Base64.getDecoder().decode(b64);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public String encodePrivateKeyToBase64() {
byte[] publicKeyBytes = privateKey.getEncoded();
return Base64.getEncoder().encodeToString(publicKeyBytes);
}
}

View file

@ -1,4 +1,4 @@
package org.baseband.launcher.util;
package com.baseband.launcher.util;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

View file

@ -1,86 +0,0 @@
package org.baseband.launcher;
import de.tudbut.net.ws.Client;
import de.tudbut.parsing.TCN;
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;
import java.security.SecureRandom;
import java.util.Base64;
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.encryptObject(getData()));
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 TCN getData() throws Exception {
File file = new File("baseband.login");
TCN tcn = new TCN();
if (file.exists()) {
FileReader fileReader = new FileReader(file);
BufferedReader reader = new BufferedReader(fileReader);
Key key = new Key(getToken()); //We encrypt using the hwid
tcn.set("Username", key.decryptString(reader.readLine()));
tcn.set("Password", key.decryptString(reader.readLine()));
tcn.set("Hardware-ID", getToken());
return tcn;
}
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

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

View file

@ -31,7 +31,7 @@ jar {
}
manifest {
attributes(
'Main-Class': 'dev.baseband.server.Main'
'Main-Class': 'com.baseband.server.Main'
)
}
baseName = 'BaseBand'

Binary file not shown.

1
Server/lib/TuddyLIB.jar Symbolic link
View file

@ -0,0 +1 @@
../../Client/libs/TuddyLIB.jar

View file

@ -1,4 +1,4 @@
package dev.baseband.server;
package com.baseband.server;
import java.util.Arrays;
import java.util.Objects;

View file

@ -0,0 +1,38 @@
package com.baseband.server;
import de.tudbut.io.TypedInputStream;
import de.tudbut.io.TypedOutputStream;
import de.tudbut.parsing.TCN;
import de.tudbut.tools.Tools;
import de.tudbut.tools.encryption.Key;
import de.tudbut.tools.encryption.RawKey;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;
public class LoaderHandler {
public static void handle(Socket connection) throws IOException {
TypedInputStream inputStream = new TypedInputStream(connection.getInputStream());
TypedOutputStream outputStream = new TypedOutputStream(connection.getOutputStream());
outputStream.writeString(Main.rsaKey.encodePublicKeyToBase64());
Key key = new Key(Main.rsaKey.rsaDec(inputStream.readString()));
TCN userData = TCN.readMap(Tools.stringToMap(key.decryptString(inputStream.readString())));
int response = UserHandler.isValid(userData);
outputStream.writeInt(response);
if(response == UserHandler.Response.OK.ordinal()) {
RawKey rk = new RawKey(key.toBytes());
outputStream.writeInt(Main.classes.size());
for (Map.Entry<String, byte[]> entry : Main.classes.entrySet()) {
outputStream.writeString(rk.encryptString(entry.getKey()));
outputStream.writeByteArray(rk.encryptBytes(entry.getValue()));
}
}
connection.close();
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package com.baseband.server;
import at.favre.lib.crypto.bcrypt.BCrypt;
import de.tudbut.io.StreamReader;
import de.tudbut.io.TypedInputStream;
import de.tudbut.io.TypedOutputStream;
import de.tudbut.parsing.JSON;
import de.tudbut.parsing.TCN;
import de.tudbut.parsing.TCNArray;
import de.tudbut.tools.Hasher;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.security.KeyPair;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Main {
public static RSAKey rsaKey;
public static boolean denyAll = false;
public static Map<String, byte[]> classes;
public static void main(String[] args) throws Exception {
File key = new File("baseband.key");
if(key.exists()) {
TypedInputStream stream = new TypedInputStream(new FileInputStream(key));
rsaKey = new RSAKey(new KeyPair(
RSAKey.decodePublicKey(stream.readString()),
RSAKey.decodePrivateKey(stream.readString())
));
}
else {
System.out.println("Generating private key...");
key.createNewFile();
rsaKey = new RSAKey();
TypedOutputStream stream = new TypedOutputStream(new FileOutputStream(key));
stream.writeString(rsaKey.encodePublicKeyToBase64());
stream.writeString(rsaKey.encodePrivateKeyToBase64());
stream.getStream().close();
}
//Loader
File db = new File("baseband.db");
if(db.exists()) {
UserHandler.users = TCNArray.fromTCN(JSON.read(new StreamReader(Files.newInputStream(db.toPath())).readAllAsString()));
} else {
db.createNewFile();
TCN tcn = new TCN();
tcn.set("username", "root");
tcn.set("password", BCrypt.withDefaults().hashToString(4, "test".toCharArray()));
tcn.set("hardware-id", Hasher.sha512hex("hardware-id"));
tcn.set("hardware-id-reset", true);
tcn.set("disabled", false);
UserHandler.users.add(tcn);
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
try (FileOutputStream fileOutputStream = new FileOutputStream(db)) {
fileOutputStream.write(JSON.writeReadable(UserHandler.users.toTCN(), 4).getBytes());
fileOutputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}));
System.out.println("Indexing...");
classes = new HashMap<>();
ZipInputStream jar = new ZipInputStream(new FileInputStream("BaseBand-Broadway.jar"));
ZipEntry entry;
while ((entry = jar.getNextEntry()) != null) {
byte[] bytes = new StreamReader(jar).readAllAsBytes();
classes.put(entry.getName(), bytes);
System.out.println(entry.getName() + ": " + bytes.length);
jar.closeEntry();
}
System.out.println("Listening!");
ServerSocket server = new ServerSocket(40000);
Socket client;
while ((client = server.accept()) != null) {
client.setSoTimeout(1000);
Socket thisClient = client;
new Thread(() -> {
try {
LoaderHandler.handle(thisClient);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
//WebServices
//Server webServiceServer = new Server(40001);
//webServiceServer.addHandler(new WebServiceHandler());
//webServiceServer.run();
}
}

View file

@ -0,0 +1,98 @@
package com.baseband.server;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAKey {
final PublicKey publicKey;
PrivateKey privateKey;
public RSAKey(String publicKey) {
this.publicKey = decodePublicKey(publicKey);
}
public RSAKey() {
KeyPair keyPair = generateKeyPair();
this.publicKey = keyPair.getPublic();
this.privateKey = keyPair.getPrivate();
}
public RSAKey(KeyPair keyPair) {
this.publicKey = keyPair.getPublic();
this.privateKey = keyPair.getPrivate();
}
private KeyPair generateKeyPair() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024 * 9);
return keyPairGenerator.generateKeyPair();
} catch (Exception e) {
//LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public String rsaEnc(byte[] plainText) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(plainText));
} catch (Exception e) {
//LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public byte[] rsaDec(String encryptedBytesInBase64) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(Base64.getDecoder().decode(encryptedBytesInBase64));
} catch (Exception e) {
//LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public static RSAPublicKey decodePublicKey(String b64) {
try {
byte[] bytes = Base64.getDecoder().decode(b64);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
//LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public String encodePublicKeyToBase64() {
byte[] publicKeyBytes = publicKey.getEncoded();
return Base64.getEncoder().encodeToString(publicKeyBytes);
}
public static RSAPrivateKey decodePrivateKey(String b64) {
try {
byte[] bytes = Base64.getDecoder().decode(b64);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
//LOGGER.fatal(e);
throw new RuntimeException(e);
}
}
public String encodePrivateKeyToBase64() {
byte[] publicKeyBytes = privateKey.getEncoded();
return Base64.getEncoder().encodeToString(publicKeyBytes);
}
}

View file

@ -1,4 +1,4 @@
package dev.baseband.server;
package com.baseband.server;
import at.favre.lib.crypto.bcrypt.BCrypt;
import de.tudbut.parsing.TCN;
@ -9,7 +9,7 @@ public class UserHandler {
public static int isValid(TCN remoteTCN) {
if(CheckNull.isNull(remoteTCN.get("username"))) {
return RESPONSE.FORBIDDEN.getValue();
return Response.FORBIDDEN.ordinal();
}
try {
@ -24,57 +24,49 @@ public class UserHandler {
boolean isDisabled = localTCN.getBoolean("disabled");
if(isDisabled) { //if they're banned we're not even looking at their TCN
return RESPONSE.BANNED.getValue();
return Response.BANNED.ordinal();
}
String remotePassword = remoteTCN.getString("password");
String remoteHardwareID = remoteTCN.getString("hardware-id");
if(CheckNull.isNull(remotePassword, remoteHardwareID)) {
return RESPONSE.SERVER_ERROR.getValue();
return Response.SERVER_ERROR.ordinal();
}
if (isReset) {
localTCN.set("hardware-id-reset", false);
localTCN.set("hardware-id", remoteHardwareID);
return RESPONSE.RESET.getValue();
return Response.RESET.ordinal();
}
if(!localHardwareID.equals(remoteTCN.getString("hardware-id"))) {
return RESPONSE.HWID_INVALID.getValue();
return Response.HWID_INVALID.ordinal();
}
if(BCrypt.verifyer().verify(remotePassword.toCharArray(), localPassword.toCharArray()).verified) {
return RESPONSE.OK.getValue();
return Response.OK.ordinal();
}
}
//LOL
return RESPONSE.FORBIDDEN.getValue();
return Response.FORBIDDEN.ordinal();
} catch(Exception e) {
return RESPONSE.SERVER_ERROR.getValue();
return Response.SERVER_ERROR.ordinal();
}
}
public enum RESPONSE {
OK(0),
FORBIDDEN(1),
OUTDATED(2),
BANNED(3),
RESET(4),
SERVER_ERROR(5),
SERVER_DOWN(6),
HWID_INVALID(7),
LOGIN_LOCKOUT(8);
private final int value;
RESPONSE(final int newValue) {
value = newValue;
}
public int getValue() { return value; }
public enum Response {
OK,
FORBIDDEN,
OUTDATED,
BANNED,
RESET,
SERVER_ERROR,
SERVER_DOWN,
HWID_INVALID,
LOGIN_LOCKOUT,
}
}

View file

@ -1,4 +1,4 @@
package dev.baseband.server;
package com.baseband.server;
import de.tudbut.net.ws.Connection;
import de.tudbut.net.ws.ConnectionHandler;

View file

@ -1,38 +0,0 @@
package dev.baseband.server;
import de.tudbut.net.ws.Connection;
import de.tudbut.net.ws.ConnectionHandler;
import de.tudbut.parsing.TCN;
import de.tudbut.tools.encryption.Key;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class LoaderHandler implements ConnectionHandler {
@Override
public void run(Connection connection) throws IOException {
//TODO: no auth but otherwise "fully functional"
connection.send(Main.rsaKey.encodePublicKeyToBase64());
Key key = new Key(Main.rsaKey.rsaDec(connection.receive()));
Object userData = key.decryptObject(connection.receive());
if(!(userData instanceof TCN)) {
connection.send(String.valueOf(UserHandler.RESPONSE.SERVER_ERROR.getValue()));
return;
}
int response = UserHandler.isValid((TCN) userData);
connection.send(String.valueOf(response));
if(response == 0) {
Map<String, byte[]> classes = new HashMap<>();
connection.send(key.encryptObject(classes));
}
}
}

View file

@ -1,67 +0,0 @@
/*
* Copyright (c) 2023 Jess H & Daniella H. All Rights Reserved.
* Unauthorized copying of this file via any medium is Strictly Prohibited.
*/
package dev.baseband.server;
import at.favre.lib.crypto.bcrypt.BCrypt;
import de.tudbut.io.StreamReader;
import de.tudbut.net.ws.Server;
import de.tudbut.parsing.JSON;
import de.tudbut.parsing.TCN;
import de.tudbut.parsing.TCNArray;
import de.tudbut.tools.Hasher;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
public class Main {
public static final RSAKey rsaKey = new RSAKey();
public static boolean denyAll = false;
public static void main(String[] args) throws Exception {
//Loader
File db = new File("baseband.db");
if(db.exists()) {
UserHandler.users = TCNArray.fromTCN(JSON.read(new StreamReader(Files.newInputStream(db.toPath())).readAllAsString()));
} else {
db.createNewFile();
TCN tcn = new TCN();
tcn.set("username", "root");
tcn.set("password", BCrypt.withDefaults().hashToString(4, "test".toCharArray()));
tcn.set("hardware-id", Hasher.sha512hex("hardware-id"));
tcn.set("hardware-id-reset", false);
tcn.set("disabled", false);
UserHandler.users.add(tcn);
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
try (FileOutputStream fileOutputStream = new FileOutputStream(db)) {
fileOutputStream.write(JSON.writeReadable(UserHandler.users.toTCN(), 4).getBytes());
fileOutputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}));
Server loaderServer = new Server(40000);
loaderServer.addHandler(new LoaderHandler());
loaderServer.run();
//WebServices
//Server webServiceServer = new Server(40001);
//webServiceServer.addHandler(new WebServiceHandler());
//webServiceServer.run();
}
}

View file

@ -1,76 +0,0 @@
package dev.baseband.server;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAKey {
PublicKey publicKey;
PrivateKey privateKey;
public RSAKey(String publicKey) {
this.publicKey = decodeBase64ToPublicKey(publicKey);
}
public RSAKey() {
KeyPair keyPair = generateKeyPair();
assert keyPair != null; //thanks intellij
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) {
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);
}
}

7
mobf.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
curl https://data.tudbut.de/mobf.jar > mobf.jar
for file in "$@" ; do
echo "$file"
java -jar mobf.jar !mixin !org/ !spotify !google !sun !oshi -k "$file" || exit 1
done

0
push_file.sh Normal file → Executable file
View file

10
push_local.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash
export SSH_PRIVATEKEY="$(cat ~/.ssh/upload_key)"
export BB_HOST=baseband.lol
export BB_PORT=22
export BB_PATH="$PWD/Server/run"
bash push_file.sh Server/build/libs/BaseBand-Server.jar
bash push_file.sh Client/build/proguard/BaseBand-Broadway.jar
bash push_file.sh Loader/build/proguard/BaseBand-Loader.jar