This commit is contained in:
Jess 2023-09-02 20:05:13 +01:00
parent 720170427a
commit c253224b48
27 changed files with 654 additions and 72 deletions

View file

@ -4,6 +4,9 @@
<content url="file://$MODULE_DIR$/../../../Loader/build/generated/sources/annotationProcessor/java/main"> <content url="file://$MODULE_DIR$/../../../Loader/build/generated/sources/annotationProcessor/java/main">
<sourceFolder url="file://$MODULE_DIR$/../../../Loader/build/generated/sources/annotationProcessor/java/main" isTestSource="false" generated="true" /> <sourceFolder url="file://$MODULE_DIR$/../../../Loader/build/generated/sources/annotationProcessor/java/main" isTestSource="false" generated="true" />
</content> </content>
<content url="file://$MODULE_DIR$/../../../Loader/src/main" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/../../../Loader/src/main/resources" type="java-resource" />
</content>
</component> </component>
<component name="FacetManager"> <component name="FacetManager">
<facet type="minecraft" name="Minecraft"> <facet type="minecraft" name="Minecraft">

View file

@ -2,6 +2,7 @@ package com.baseband.client;
import com.baseband.client.command.CommandManager; import com.baseband.client.command.CommandManager;
import com.baseband.client.event.EventBus;
import com.baseband.client.module.ModuleRegistry; import com.baseband.client.module.ModuleRegistry;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
@ -15,17 +16,19 @@ import org.apache.logging.log4j.Logger;
import java.awt.*; import java.awt.*;
public class Main { public class Main {
public static int buildNumber = 67; public static int buildNumber = 3;
public static final String name = "BaseBand"; public static final String name = "BaseBand";
public static ModuleRegistry moduleRegistry; public static ModuleRegistry moduleRegistry;
public static CommandManager commandRegistry; public static CommandManager commandRegistry;
public static EventBus eventBus;
public static final Logger log = LogManager.getLogger("BaseBand"); public static final Logger log = LogManager.getLogger("BaseBand");
public static boolean authed = true; //TODO: make this update along with whatever protection Daniella's figuring out public static boolean authed = true; //TODO: make this update along with whatever protection Daniella's figuring out
public static void onInit() { public static void onInit() {
moduleRegistry = new ModuleRegistry(); moduleRegistry = new ModuleRegistry();
commandRegistry = new CommandManager(); commandRegistry = new CommandManager();
eventBus = new EventBus();
log.info("BaseBand Instantiated."); log.info("BaseBand Instantiated.");
} }

View file

@ -1,6 +1,5 @@
package com.baseband.client.command.commands; package com.baseband.client.command.commands;
import com.baseband.client.Utils;
import com.baseband.client.command.Command; import com.baseband.client.command.Command;
public class CreditsCommand extends Command { public class CreditsCommand extends Command {
@ -10,7 +9,8 @@ public class CreditsCommand extends Command {
@Override @Override
public String run(String[] args) { public String run(String[] args) {
Utils.sendChatMessage("Base and most of the loader written by JessSystemV, \nJohn200410 helped with the loader."); return "Base and most of the loader written by JessSystemV, " +
return ""; "\nJohn200410 helped with the loader. " +
"\nTudbuT made the GUI.";
} }
} }

View file

@ -1,5 +1,6 @@
package com.baseband.client.command.commands; package com.baseband.client.command.commands;
import com.baseband.client.Main;
import com.baseband.client.command.Command; import com.baseband.client.command.Command;
public class HelpCommand extends Command { public class HelpCommand extends Command {
@ -9,6 +10,8 @@ public class HelpCommand extends Command {
@Override @Override
public String run(String[] args) { public String run(String[] args) {
return "BaseBand Rewrite Copyright (2023) JessSystemV & TudbuT"; return "BaseBand Rewrite Build" + Main.buildNumber +
"\nCopyright JessSystemV & TudbuT (2023)" +
"\nAll rights reserved.";
} }
} }

View file

@ -0,0 +1,13 @@
package com.baseband.client.event;
public class CancellableEvent {
boolean cancelled = false;
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View file

@ -0,0 +1,90 @@
package com.baseband.client.event;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EventBus {
private final List<EventHandler> eventHandlers = new ArrayList<>();
private final Map<Class<?>, List<Object>> subscribersMap = new HashMap<>();
public synchronized void subscribe(EventHandler eventHandler) {
eventHandlers.add(eventHandler);
}
public synchronized void unsubscribe(EventHandler eventHandler) {
eventHandlers.remove(eventHandler);
}
public synchronized void register(Object eventInstance) {
Class<?> clazz = eventInstance.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?> parameterType = method.getParameterTypes()[0];
subscribersMap.computeIfAbsent(parameterType, k -> new ArrayList<>()).add(eventInstance);
}
}
}
public synchronized void unregister(Object eventInstance) {
Class<?> clazz = eventInstance.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?> parameterType = method.getParameterTypes()[0];
List<Object> subscribers = subscribersMap.get(parameterType);
if (subscribers != null) {
subscribers.remove(eventInstance);
}
}
}
}
public void publish(Object eventData) {
List<EventHandler> handlersCopy;
synchronized (this) {
handlersCopy = new ArrayList<>(eventHandlers);
}
for (EventHandler handler : handlersCopy) {
handler.handle(eventData);
}
List<Object> subscribers = subscribersMap.get(eventData.getClass());
if (subscribers != null) {
for (Object subscriber : subscribers) {
invokeAnnotatedMethods(subscriber, eventData);
}
}
}
private void invokeAnnotatedMethods(Object subscriber, Object eventData) {
Class<?> clazz = subscriber.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?> parameterType = method.getParameterTypes()[0];
if (parameterType.isAssignableFrom(eventData.getClass())) {
try {
method.setAccessible(true);
method.invoke(subscriber, eventData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
@FunctionalInterface
interface EventHandler {
void handle(Object eventData);
}

View file

@ -0,0 +1,8 @@
package com.baseband.client.event;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
}

View file

@ -0,0 +1,26 @@
package com.baseband.client.event.events;
import com.baseband.client.event.CancellableEvent;
import net.minecraft.network.Packet;
public class PacketEvent extends CancellableEvent {
private final Packet<?> packet;
public PacketEvent(Packet<?> packet) {
this.packet = packet;
}
public Packet<?> getPacket() { return packet; }
public static class Write extends PacketEvent {
public Write(Packet<?> packet) {
super(packet);
}
}
public static class Read extends PacketEvent {
public Read(Packet<?> packet) {
super(packet);
}
}
}

View file

@ -0,0 +1,34 @@
package com.baseband.client.mixins;
import com.baseband.client.Main;
import com.baseband.client.event.events.PacketEvent;
import io.netty.channel.ChannelHandlerContext;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(NetworkManager.class)
public class MixinNetworkManager {
@Inject(method = "channelRead0", at = @At("HEAD"), cancellable = true)
public void channelRead0(ChannelHandlerContext p_channelRead0_1_, Packet<?> p_channelRead0_2_, CallbackInfo ci) {
PacketEvent.Read event = new PacketEvent.Read(p_channelRead0_2_);
Main.eventBus.publish(event);
if (event.isCancelled())
ci.cancel();
}
@Inject(method = "sendPacket(Lnet/minecraft/network/Packet;)V", at = @At("HEAD"), cancellable = true)
public void channelRead0(Packet<?> packetIn, CallbackInfo ci) {
PacketEvent.Write event = new PacketEvent.Write(packetIn);
Main.eventBus.publish(event);
if (event.isCancelled())
ci.cancel();
}
}

View file

@ -1,5 +1,7 @@
package com.baseband.client.module; package com.baseband.client.module;
import com.baseband.client.Main;
public class Module { public class Module {
String name; String name;
boolean isEnabled = false; boolean isEnabled = false;
@ -17,10 +19,10 @@ public class Module {
isEnabled=enabled; isEnabled=enabled;
if(isEnabled) { if(isEnabled) {
enable(); enable();
//Main.EVENT_MANAGER.subscribe(this); Main.eventBus.register(this);
}else { }else {
disable(); disable();
//Main.EVENT_MANAGER.unsubscribe(this); Main.eventBus.unregister(this);
} }
} }

View file

@ -3,7 +3,7 @@ package com.baseband.client.module;
import com.baseband.client.module.modules.Brightness; import com.baseband.client.module.modules.Brightness;
import com.baseband.client.module.modules.ClickGUI; import com.baseband.client.module.modules.ClickGUI;
import com.baseband.client.module.modules.HUD; import com.baseband.client.module.modules.HUD;
import com.baseband.client.module.modules.Test; import com.baseband.client.module.modules.PacketTest;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@ -22,9 +22,10 @@ public class ModuleRegistry {
void addModules() { void addModules() {
modules.add(new Brightness()); modules.add(new Brightness());
modules.add(new Test()); modules.add(new PacketTest());
modules.add(new HUD()); modules.add(new HUD());
modules.add(new ClickGUI()); modules.add(new ClickGUI());
modules.add(new PacketTest());
} }
@SubscribeEvent @SubscribeEvent

View file

@ -3,6 +3,7 @@ package com.baseband.client.module.modules;
import com.baseband.client.Main; import com.baseband.client.Main;
import com.baseband.client.module.Module; import com.baseband.client.module.Module;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@ -16,6 +17,14 @@ public class HUD extends Module {
@SubscribeEvent @SubscribeEvent
public void text(RenderGameOverlayEvent.Text e) { public void text(RenderGameOverlayEvent.Text e) {
Minecraft.getMinecraft().fontRenderer.drawStringWithShadow("BaseBand Build-" + Main.buildNumber, 2, 2, Color.GREEN.getRGB()); FontRenderer fr = Minecraft.getMinecraft().fontRenderer;
fr.drawStringWithShadow("BaseBand B" + Main.buildNumber, 2, 2, Color.GREEN.getRGB());
int y = 12;
for (Module m : Main.moduleRegistry.getModuleList()) {
if(m.isEnabled()) {
fr.drawStringWithShadow(m.getName(), 2, 2, Color.GREEN.getRGB());
y=y+fr.FONT_HEIGHT;
}
}
} }
} }

View file

@ -0,0 +1,22 @@
package com.baseband.client.module.modules;
import com.baseband.client.Utils;
import com.baseband.client.event.Subscribe;
import com.baseband.client.event.events.PacketEvent;
import com.baseband.client.module.Module;
public class PacketTest extends Module {
public PacketTest() {
super("PacketTest");
}
@Subscribe
public void handleEventA(PacketEvent.Read event) {
Utils.sendChatMessage(event.getPacket().getClass().getName());
}
@Subscribe
public void handleEventB(PacketEvent.Write event) {
Utils.sendChatMessage(event.getPacket().getClass().getName());
}
}

View file

@ -1,20 +0,0 @@
package com.baseband.client.module.modules;
import com.baseband.client.module.Module;
public class Test extends Module {
public Test() {
super("Test");
}
public void enable() {
}
public void disable() {
}
}

View file

@ -5,6 +5,8 @@
"minVersion": "0", "minVersion": "0",
"refmap": "mixins.baseband.refmap.json", "refmap": "mixins.baseband.refmap.json",
"mixins": [ "mixins": [
"MixinMinecraft" "MixinMinecraft",
"MixinForgeBus",
"MixinNetworkManager"
] ]
} }

View file

@ -10,6 +10,7 @@ import java.awt.event.ItemListener;
import java.io.*; import java.io.*;
import java.net.Socket; import java.net.Socket;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.UUID;
public class InstallerApp { public class InstallerApp {
private JFrame loginFrame; private JFrame loginFrame;
@ -88,12 +89,24 @@ public class InstallerApp {
InstallerApp.username=username; InstallerApp.username=username;
InstallerApp.password=bytesToHex(MessageDigest.getInstance("MD5").digest(password.getBytes())); InstallerApp.password=bytesToHex(MessageDigest.getInstance("SHA-512").digest(password.getBytes()));
//We need this to make sure we're not being poked at
String ticket = getRandomTicket();
outputF.writeUTF(ticket);
String compare = inputF.readUTF();
if(!compare.equals(ticket)) {
JOptionPane.showMessageDialog(loginFrame, "Invalid Auth Ticket Response",
"Please contact support for more details.", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
outputF.writeUTF("installer"); outputF.writeUTF("installer");
outputF.writeUTF(InstallerApp.username); outputF.writeUTF(InstallerApp.username);
outputF.writeUTF(InstallerApp.password); outputF.writeUTF(InstallerApp.password);
outputF.writeUTF(generate()); outputF.writeUTF(generate());
outputF.writeBoolean(false);
outputF.writeInt(0); outputF.writeInt(0);
int responseInt = inputF.readInt(); int responseInt = inputF.readInt();
@ -102,10 +115,16 @@ public class InstallerApp {
loginFrame.dispose(); loginFrame.dispose();
createInstallerWindow(); createInstallerWindow();
} else if (responseInt == -4) { } else if (responseInt == -4) {
JOptionPane.showMessageDialog(loginFrame, "Invalid HWID\nPlease contact support.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(loginFrame, "Invalid HWID\nPlease contact support.", "BaseBand Installer", JOptionPane.ERROR_MESSAGE);
System.exit(0); System.exit(0);
} else { } else if (responseInt == -5){
JOptionPane.showMessageDialog(loginFrame, "Invalid username or password.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(loginFrame, "Your BaseBand account has been banned\nPlease contact support.", "BaseBand Installer", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}else if (responseInt == -6){
JOptionPane.showMessageDialog(loginFrame, "Your Password has been Reset\nPlease re-run the installer.", "BaseBand Installer", JOptionPane.ERROR_MESSAGE);
System.exit(0);
} else{
JOptionPane.showMessageDialog(loginFrame, "Invalid username or password.", "BaseBand Installer", JOptionPane.ERROR_MESSAGE);
System.exit(0); System.exit(0);
} }
}catch (Exception ignored){} }catch (Exception ignored){}
@ -122,9 +141,17 @@ public class InstallerApp {
loginFrame.setVisible(true); loginFrame.setVisible(true);
} }
private static String getRandomTicket() {
StringBuilder buffer = new StringBuilder();
for (int count = 0; count < 10; ++count) {
buffer.append(UUID.randomUUID());
}
return buffer.toString();
}
public static String generate() { public static String generate() {
try { try {
return bytesToHex(MessageDigest.getInstance("MD5").digest((System.getenv("PROCESSOR_IDENTIFIER") + System.getenv("COMPUTERNAME") + System.getProperty("user.name")).getBytes())); return bytesToHex(MessageDigest.getInstance("SHA-512").digest((System.getenv("PROCESSOR_IDENTIFIER") + System.getenv("COMPUTERNAME") + System.getProperty("user.name")).getBytes()));
} catch (Exception e) { } catch (Exception e) {
return "######################"; return "######################";
} }
@ -189,6 +216,7 @@ public class InstallerApp {
outputF.writeUTF(username); outputF.writeUTF(username);
outputF.writeUTF(password); outputF.writeUTF(password);
outputF.writeUTF(generate()); outputF.writeUTF(generate());
outputF.writeBoolean(false);
outputF.writeInt(1); outputF.writeInt(1);
int responseInt = inputF.readInt(); int responseInt = inputF.readInt();

View file

@ -32,7 +32,7 @@ public class Tweaker implements ITweaker {
public void injectIntoClassLoader(LaunchClassLoader classLoader) { public void injectIntoClassLoader(LaunchClassLoader classLoader) {
try { try {
latch = new CountDownLatch(1); latch = new CountDownLatch(1);
Loader.initiate(classLoader); Loader.initiate();
latch.await(); latch.await();
wrapped.injectIntoClassLoader(classLoader); wrapped.injectIntoClassLoader(classLoader);

View file

@ -1,23 +1,34 @@
package org.baseband.launcher.launch; package org.baseband.launcher.launch;
import net.minecraft.launchwrapper.LaunchClassLoader; import net.minecraft.launchwrapper.Launch;
import org.baseband.launcher.Tweaker; import org.baseband.launcher.Tweaker;
import org.baseband.launcher.util.CustomClassloader; import org.baseband.launcher.util.CustomClassloader;
import org.baseband.launcher.util.HWID; import org.baseband.launcher.util.HWID;
import sun.misc.Unsafe;
import sun.reflect.Reflection;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.*; import javax.swing.*;
import java.io.*; import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.Socket; import java.net.Socket;
import java.util.HashMap; import java.security.SecureRandom;
import java.util.Map; import java.security.spec.KeySpec;
import java.util.*;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
public class Loader { public class Loader {
public static void initiate(LaunchClassLoader classLoader) { public static void initiate() {
try { try {
//Socket socket = new Socket("127.0.0.1", 31212); //Socket socket = new Socket("127.0.0.1", 31212);
Socket socket = new Socket("127.0.0.1", 31212); Socket socket = new Socket("127.0.0.1", 31212);
@ -44,6 +55,14 @@ public class Loader {
} }
//We need this to make sure we're not being poked at
String ticket = getRandomTicket();
outputF.writeUTF(ticket);
String compare = inputF.readUTF();
if(!compare.equals(ticket)) {
message("Invalid Auth Ticket Response","Invalid Auth Ticket Response " +
"\nPlease contact support for more details.", JOptionPane.ERROR_MESSAGE, true);
}
outputF.writeUTF("loader"); outputF.writeUTF("loader");
@ -51,6 +70,10 @@ public class Loader {
outputF.writeUTF(password); outputF.writeUTF(password);
outputF.writeUTF(HWID.generate()); outputF.writeUTF(HWID.generate());
boolean dump = dumpDetected();
outputF.writeBoolean(dump);
outputF.writeUTF("reason"); //TODO: make this return reason
int responseCode = inputF.readInt(); int responseCode = inputF.readInt();
switch (responseCode) { switch (responseCode) {
@ -80,10 +103,16 @@ public class Loader {
case -5: { case -5: {
message("Banned Account","Your BaseBand account has been banned," + message("Banned Account","Your BaseBand account has been banned," +
"\nContact support for more details.", JOptionPane.ERROR_MESSAGE, true); "\nContact support for more details." +
"\n(This may be because you attempted to dump BaseBand.)", JOptionPane.ERROR_MESSAGE, true);
break; break;
} }
case -6: {
message("Rerun the installer", "Your password has been reset, " +
"\nPlease Rerun the installer.", JOptionPane.ERROR_MESSAGE, true);
}
default: { default: {
Tweaker.log.info("Authenticated."); Tweaker.log.info("Authenticated.");
break; break;
@ -110,7 +139,7 @@ public class Loader {
if (zipEntry.getName().endsWith(".class")) { if (zipEntry.getName().endsWith(".class")) {
classCache.put(zipEntry.getName().replace(".class", "").replace('/', '.'), bos.toByteArray()); classCache.put(zipEntry.getName().replace(".class", "").replace('/', '.'), encrypt(bos.toByteArray()));
} else { } else {
resources.put(zipEntry.getName(), bos.toByteArray()); resources.put(zipEntry.getName(), bos.toByteArray());
} }
@ -136,7 +165,7 @@ public class Loader {
fos.close(); fos.close();
tempFile.deleteOnExit(); tempFile.deleteOnExit();
classLoader.addURL(tempFile.toURI().toURL()); Launch.classLoader.addURL(tempFile.toURI().toURL());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -148,8 +177,127 @@ public class Loader {
} }
} }
public static void message(String title, String message, int b, boolean exit) {
private static String getRandomTicket() {
StringBuilder buffer = new StringBuilder();
for (int count = 0; count < 10; ++count) {
buffer.append(UUID.randomUUID());
}
return buffer.toString();
}
public static boolean 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
};
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();
if (inputFlag.isPresent()) {
return true;
}
getUnsafe().defineClass("sun.instrument.InstrumentationImpl", EMPTY_CLASS_BYTES, 0, EMPTY_CLASS_BYTES.length, null, null);
// this is for testing purposes to make sure it's actually loaded
try {
Class.forName("sun.instrument.InstrumentationImpl");
} catch (ClassNotFoundException e) {
return true;
}
return false;
}
public static byte[] key = null;
public static byte[] encrypt(byte[] bytes) {
if(key==null) {
SecureRandom rd = new SecureRandom();
byte[] arr = new byte[127];
rd.nextBytes(arr);
key=arr;
}
try {
final IvParameterSpec ivspec = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
final KeySpec spec = new PBEKeySpec(Arrays.toString(key).toCharArray(), "ssshhhhhhhhhhh!!!!".getBytes(), 65536, 256);
final SecretKey tmp = factory.generateSecret(spec);
final SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
return Base64.getEncoder().encode(cipher.doFinal(bytes));
} catch (Exception e) {
return null;
}
}
public static byte[] decrypt(byte[] bytes) {
Reflection.getCallerClass();
try {
final IvParameterSpec ivspec = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
final KeySpec spec = new PBEKeySpec(Arrays.toString(key).toCharArray(), "ssshhhhhhhhhhh!!!!".getBytes(), 65536, 256);
final SecretKey tmp = factory.generateSecret(spec);
final SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
return cipher.doFinal(Base64.getDecoder().decode(bytes));
} catch (Exception e) {
return null;
//unfunny decryption key above
//what no lmao it's
//regenerated every launch
}
}
private 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 { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ignored) {} } catch (Exception ignored) {}

View file

@ -4,23 +4,32 @@ import net.minecraft.launchwrapper.Launch;
import org.baseband.launcher.launch.Loader; import org.baseband.launcher.launch.Loader;
import org.spongepowered.asm.service.MixinService; import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper; import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
import sun.reflect.Reflection;
import java.io.IOException; import java.io.*;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map; import java.util.HashMap;
import java.util.Objects;
public class CustomClassloader extends ClassLoader { public class CustomClassloader extends ClassLoader {
public static CustomClassloader INSTANCE; public static CustomClassloader INSTANCE;
private Map<String, byte[]> classes;
public CustomClassloader() {
//lmao no touch my pie and you die private byte[] classes;
//oh my god this took so long to figure out
//CREDIT to John200410 who fucking baby-sat my ass
//through the reflection classloader fuckery on lines 50-53
public CustomClassloader(Object obj) {
initClasses(obj);
}
public CustomClassloader() {}
public void initClasses(Object classes){
try { try {
CustomMixinServer customService = new CustomMixinServer(); CustomMixinServer customService = new CustomMixinServer();
@ -38,12 +47,9 @@ public class CustomClassloader extends ClassLoader {
}catch (Exception e){ }catch (Exception e){
Loader.exit(); Loader.exit();
} }
}
public CustomClassloader(Map<String, byte[]> classes) {
INSTANCE = new CustomClassloader(); INSTANCE = new CustomClassloader();
INSTANCE.classes=classes; INSTANCE.classes=convertToBytes(classes);
try { try {
@ -59,7 +65,7 @@ public class CustomClassloader extends ClassLoader {
@Override @Override
protected Class<?> findClass(String name) throws ClassNotFoundException { protected Class<?> findClass(String name) throws ClassNotFoundException {
if(name.startsWith("com.baseband")) { if(name.startsWith("com.baseband")) {
byte[] data = classes.get(name); byte[] data = Loader.decrypt((byte[]) ((HashMap<?, ?>) Objects.requireNonNull(convertFromBytes(classes))).get(name));
if (data == null) { if (data == null) {
return super.findClass(name); return super.findClass(name);
} }
@ -80,11 +86,31 @@ public class CustomClassloader extends ClassLoader {
} }
private byte[] convertToBytes(Object object) {
Reflection.getCallerClass();
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos)) {
out.writeObject(object);
return Loader.encrypt(bos.toByteArray());
}catch (IOException e){
return null;
}
}
private Object convertFromBytes(byte[] bytes) {
try (ByteArrayInputStream bis = new ByteArrayInputStream(Objects.requireNonNull(Loader.decrypt(bytes)));
ObjectInputStream in = new ObjectInputStream(bis)) {
return in.readObject();
}catch (IOException | ClassNotFoundException e){
return null;
}
}
private class CustomMixinServer extends MixinServiceLaunchWrapper { private class CustomMixinServer extends MixinServiceLaunchWrapper {
@Override @Override
public byte[] getClassBytes(String name, String transformedName) throws IOException { public byte[] getClassBytes(String name, String transformedName) throws IOException {
byte[] bytes = classes.get(name); byte[] bytes = Loader.decrypt((byte[]) ((HashMap<?, ?>) Objects.requireNonNull(convertFromBytes(classes))).get(name));
if (bytes != null) { if (bytes != null) {
return bytes; return bytes;
} }
@ -93,7 +119,7 @@ public class CustomClassloader extends ClassLoader {
@Override @Override
public byte[] getClassBytes(String name, boolean runTransformers) throws ClassNotFoundException, IOException { public byte[] getClassBytes(String name, boolean runTransformers) throws ClassNotFoundException, IOException {
byte[] bytes = classes.get(name); byte[] bytes = Loader.decrypt((byte[]) ((HashMap<?, ?>) Objects.requireNonNull(convertFromBytes(classes))).get(name));
if (bytes != null) { if (bytes != null) {
return bytes; return bytes;
} }

View file

@ -5,7 +5,10 @@ import java.security.MessageDigest;
public class HWID { public class HWID {
public static String generate() { public static String generate() {
try { try {
return bytesToHex(MessageDigest.getInstance("MD5").digest((System.getenv("PROCESSOR_IDENTIFIER") + System.getenv("COMPUTERNAME") + System.getProperty("user.name")).getBytes())); return bytesToHex(MessageDigest.getInstance("MD5").digest((
System.getenv("PROCESSOR_IDENTIFIER") +
System.getenv("COMPUTERNAME") +
System.getProperty("user.name")).getBytes()));
} catch (Exception e) { } catch (Exception e) {
return "######################"; return "######################";
} }

View file

@ -0,0 +1,48 @@
This Data Policy provides insight into how we manage, store, and handle your data.
By using our services, you accept and consent to the practices outlined in this policy.
1. Data Collection
We collect certain data to offer our services and enhance your experience. This includes:
Your BaseBand username (distinct from your Minecraft username).
A secure hash of your BaseBand password (distinct from your Minecraft password).
Playtime and last login time.
Non-personal information about your BaseBand version.
Messages sent via BaseBand SMS, retained until the receiver receives them.
Minecraft account information (excluding non-public Mojang API data).
License details: expiration, active status, type.
Ban and mute details, including duration.
Specific PC hardware information, such as unique processor identifiers, your current OS username, and computer hostname.
2. Data Usage
We utilize collected data to provide and optimize our services, as well as to communicate essential account-related updates and notifications.
Hardware information aids compatibility and service optimization.
3. Data Sharing
Except as specified in this Data Policy or as required by law, we do not share your personal data with third parties.
Aggregated, anonymized data may be used for analytics and marketing purposes.
4. Data Retention
We retain data until an applicable request for erasure is submitted, along with the associated username and proof of account ownership.
Upon receipt of a valid request, we promptly delete or anonymize the data.
5. Your Rights
You hold the right to access, correct, update, or delete your personal data.
To exercise these rights, submit a request to be forgotten, providing your username and proof of account ownership.
We are committed to promptly addressing your requests.
6. Changes to the Data Policy
Should our practices change due to legal requirements or other factors, this Data Policy will be updated accordingly.
In case of significant changes, you will be informed, and consent will be sought if necessary.
7. Contact Us
For inquiries, concerns, or data-related requests, please contact Jess at [jess@jesssystemv.co.uk].
Please note that Jess may take up to 30 business days to reply.
Your use of our services implies your understanding of and agreement with this Data Policy, including the collection, storage, and utilization of your data as described herein.

View file

@ -0,0 +1,45 @@
End-User License Agreement (EULA) for BaseBand
This End-User License Agreement ("EULA") is a legal agreement between you and the developer (Jess), as well as the developers (Jess and TudbuT).
This EULA agreement governs your acquisition and use of BaseBand ("Client") directly from the developer (Jess) or indirectly through a developer (Jess) authorized reseller or distributor (a "Reseller").
Please read this EULA agreement carefully before completing the installation process and using BaseBand. It provides a license to use BaseBand and contains warranty information and liability disclaimers.
By installing and/or using BaseBand, you confirm your acceptance of the license and agree to be bound by the terms of this EULA agreement.
If you are entering into this EULA agreement on behalf of a company or other legal entity, you represent that you have the authority to bind such entity and its affiliates to these terms and conditions.
If you lack such authority or disagree with the terms and conditions of this EULA agreement, do not install or use the software, and do not accept this EULA agreement.
This EULA agreement applies only to the software supplied by the developer (Jess) herewith, regardless of whether other software is referred to or described herein.
These terms also apply to any updates, supplements, Internet-based services, and support services for the software provided by the developer (Jess), unless other terms accompany those items upon delivery. If so, those terms apply.
License Grant
The developer (Jess) grants you a personal, non-transferable, non-exclusive license to use the BaseBand software on your devices in accordance with the terms of this EULA agreement.
You are allowed to install BaseBand on a device (e.g., a PC, laptop, mobile, or tablet) under your control.
It is your responsibility to ensure that your device meets the minimum requirements of Minecraft 1.12.2 Forge, a required dependency for BaseBand.
You are not allowed to:
Edit, alter, modify, adapt, translate, or otherwise change the whole or any part of the software, nor allow the software to be combined with or become part of any other software.
Decompile, disassemble, deobfuscate, dump, unarchive, or reverse engineer the software, or attempt any such actions.
Attempt to bypass any security measures.
Modify the binary's ability to connect to the API.
Reproduce, copy, distribute, resell, or otherwise use the software for any commercial purpose.
Allow any third party to use the software on behalf of or for the benefit of any third party.
Use the software in any way that breaches any applicable local, national, or international law.
Use the software for any purpose that the developer (Jess) considers a breach of this EULA agreement.
Intellectual Property and Ownership
The developer (Jess) shall retain ownership of the software as originally downloaded by you and all subsequent downloads of the software by you.
The software (including copyright and other intellectual property rights) are and shall remain the property of the developer (Jess).
BaseBand (Client) is a Utility Player Assistance Mod and should not be used on any Server/Realm that disallows hacking. The developers are not responsible for any punishments you may receive on a given server.
The developer (Jess) reserves the right to grant licenses to third parties to use the software and to terminate your license at any time.
Termination
This EULA agreement is effective from the date you first use the software and continues until terminated. You can terminate it at any time with written notice to the developer (Jess).
It will also terminate immediately if you fail to comply with any term of this EULA agreement. Upon termination, the licenses granted by this EULA agreement will immediately terminate, and you agree to cease all access and use of the software. Provisions that, by their nature, continue and survive will endure any termination of this EULA agreement.
Governing Law
This EULA agreement and any dispute arising from or related to it shall be governed by and construed in accordance with the laws of Great Britain.

View file

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

View file

@ -17,7 +17,7 @@ public class Bot extends ListenerAdapter {
try{ try{
//Scanner scanner = new Scanner(new File("baseband_bot.token")); //Scanner scanner = new Scanner(new File("baseband_bot.token"));
String token = "MTE0NTg0MjYxMDc0NTkyMTU0Nw.GD70DW.MwSmBeylHN4tTtOfv1On50bin1G9JDDawHRFXY";//scanner.next(); String token = "MTE0NTg0MjYxMDc0NTkyMTU0Nw.GD70DW.MwSmBeylHN4tTtOfv1On50bin1G9JDDawHRFXY";//scanner.next();
JDA jda = JDABuilder.createDefault(token).addEventListeners(new Bot()).enableIntents(GatewayIntent.MESSAGE_CONTENT, new GatewayIntent[0]).enableIntents(GatewayIntent.GUILD_MESSAGES, new GatewayIntent[0]).build().awaitReady(); JDA jda = JDABuilder.createDefault(token).addEventListeners(new Bot()).enableIntents(GatewayIntent.MESSAGE_CONTENT).enableIntents(GatewayIntent.GUILD_MESSAGES, new GatewayIntent[0]).build().awaitReady();
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
} }
@ -78,20 +78,35 @@ public class Bot extends ListenerAdapter {
} }
// Loop through the outer map // Loop through the outer map
for (Map.Entry<String, Map<String, String>> entry : UserManager.users.getMap().entrySet()) { for (Map.Entry<String, Map<String, String>> entry : UserManager.users.getMap().entrySet()) {
StringBuilder stringBuilder = new StringBuilder("==============================");
String outerKey = entry.getKey(); String outerKey = entry.getKey();
Map<String, String> innerMap = entry.getValue(); Map<String, String> innerMap = entry.getValue();
event.getChannel().sendMessage("==============================").queue();
event.getChannel().sendMessage("Username: " + outerKey).queue(); stringBuilder.append("Username: ").append(outerKey).append("\n");
// Loop through the inner map // Loop through the inner map
for (Map.Entry<String, String> innerEntry : innerMap.entrySet()) { for (Map.Entry<String, String> innerEntry : innerMap.entrySet()) {
String innerKey = innerEntry.getKey(); String innerKey = innerEntry.getKey();
String innerValue = innerEntry.getValue(); String innerValue = innerEntry.getValue();
event.getChannel().sendMessage("Key: [" + innerKey + "] Value: [" + innerValue+ "]").queue(); stringBuilder.append("Key: [").append(innerKey).append("] Value: [").append(innerValue).append("]").append("\n");
} }
event.getChannel().sendMessage("==============================").queue(); event.getChannel().sendMessage(stringBuilder.append("==============================").toString()).queue();
}
} if (message[0].equalsIgnoreCase("-resetpassword")) {
if (this.findRole(Objects.requireNonNull(event.getMember()), "Staff") == null) {
event.getChannel().sendMessage("Invalid Perms (Requires Staff Role)").queue();
return;
}
String username = message[1];
if(UserManager.users.usernameExists(username)) {
UserManager.users.setPassword(username, "reset");
event.getChannel().sendMessage("Password of username [**" + username + "**] reset.").queue();
}else {
event.getChannel().sendMessage("Cannot find User [**" + username + "**]").queue();
} }
} }
} }

View file

@ -1,6 +1,12 @@
package dev.baseband.server.socket; package dev.baseband.server.socket;
import java.io.*; import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class ClientHandler extends Thread { public class ClientHandler extends Thread {
final java.net.Socket client; final java.net.Socket client;
@ -16,10 +22,15 @@ public class ClientHandler extends Thread {
DataInputStream dis = new DataInputStream(client.getInputStream()); DataInputStream dis = new DataInputStream(client.getInputStream());
//We are confirming that we are who we say we are
String ticket = dis.readUTF();
dos.writeUTF(ticket);
String type = dis.readUTF(); String type = dis.readUTF();
String username = dis.readUTF(); String username = dis.readUTF();
String hashedPassword = dis.readUTF(); String hashedPassword = sha512hex(dis.readUTF());
String hwid = dis.readUTF(); String hwid = dis.readUTF();
boolean dump = dis.readBoolean();
@ -29,10 +40,22 @@ public class ClientHandler extends Thread {
System.out.println(username); System.out.println(username);
System.out.println(hashedPassword); System.out.println(hashedPassword);
System.out.println(hwid); System.out.println(hwid);
System.out.println(dump);
int result = UserManager.isUserValid(username, hashedPassword, hwid); int result = UserManager.isUserValid(username, hashedPassword, hwid);
System.out.println(result); System.out.println(result);
if((result==0 || result==-2) && dump) {
System.out.println("!!Dump Detected!!");
System.out.println(dis.readUTF());
System.out.println("(We are banning this user.)");
UserManager.users.setIsBanned(username, "true");
dos.writeInt(-5);
client.close();
System.out.println("========================================");
return;
}
if(type.contains("installer")) { if(type.contains("installer")) {
System.out.println("Installer detected."); System.out.println("Installer detected.");
int typeInt = dis.readInt(); int typeInt = dis.readInt();
@ -56,7 +79,10 @@ public class ClientHandler extends Thread {
} else if (result == -4){ } else if (result == -4){
System.out.println("Invalid HWID"); System.out.println("Invalid HWID");
dos.writeInt(result); dos.writeInt(result);
} else{ } else if(result == -6){
System.out.println("Password Reset.");
dos.writeInt(result);
}else{
System.out.println("Auth failed"); System.out.println("Auth failed");
dos.writeInt(result); dos.writeInt(result);
} }
@ -66,6 +92,7 @@ public class ClientHandler extends Thread {
return; return;
} }
if (result == 0 || result == -2) { if (result == 0 || result == -2) {
System.out.println("Client is valid"); System.out.println("Client is valid");
@ -95,4 +122,30 @@ public class ClientHandler extends Thread {
this.interrupt(); this.interrupt();
} }
} }
public static String sha512hex(String toHash) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-512");
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Impossible condition reached");
}
return hash(toHash, digest);
}
private static String hash(String toHash, MessageDigest digest) {
byte[] hash = digest.digest(
toHash.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
} }

View file

@ -65,6 +65,10 @@ public class UserManager {
return -5; //BANNED return -5; //BANNED
} }
if(users.getPassword(user).equals("reset")) {
return -6; //Their password has been reset
}
if(users.getResetStatus(user).equals("false")) { if(users.getResetStatus(user).equals("false")) {
if (!users.getHwid(user).equals(hwid)) { if (!users.getHwid(user).equals(hwid)) {
return -4; //HWID does not match and they are not reset return -4; //HWID does not match and they are not reset

View file

@ -57,9 +57,9 @@ public class UserMap {
}); });
} }
public void setIsBanned(String username, String newPassword) { public void setIsBanned(String username, String isBanned) {
map.computeIfPresent(username, (u, userMap) -> { map.computeIfPresent(username, (u, userMap) -> {
userMap.put("isBanned", newPassword); userMap.put("isBanned", isBanned);
return userMap; return userMap;
}); });
} }