diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/asm/ConfigGenerator.java b/LaunchServer/src/main/java/pro/gravit/launchserver/asm/ConfigGenerator.java index ab66442c..05af2e3d 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/asm/ConfigGenerator.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/asm/ConfigGenerator.java @@ -7,6 +7,7 @@ import java.util.Base64; import java.util.List; +import java.util.Map; public class ConfigGenerator { protected static final String stringDesc = Type.getDescriptor(String.class); @@ -64,6 +65,23 @@ public void setByteArrayListField(String name, List b) { constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, configclass.name, name, "Ljava/util/List;")); } + public void setStringByteArrMapField(String name, Map b) { + constructor.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); + constructor.instructions.add(new TypeInsnNode(Opcodes.NEW, "java/util/HashMap")); + constructor.instructions.add(new InsnNode(Opcodes.DUP)); // +1 + constructor.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/HashMap", "", "()V")); + for (Map.Entry value : b.entrySet()) { + constructor.instructions.add(new InsnNode(Opcodes.DUP)); // +1-1 + constructor.instructions.add(NodeUtils.getSafeStringInsnList(value.getKey())); + constructor.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/Base64", "getDecoder", "()Ljava/util/Base64$Decoder;", false)); + constructor.instructions.add(NodeUtils.getSafeStringInsnList(Base64.getEncoder().encodeToString(value.getValue()))); + constructor.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/Base64$Decoder", "decode", base64DecDesc, false)); + constructor.instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true)); + constructor.instructions.add(new InsnNode(Opcodes.POP)); + } // haax! + constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, configclass.name, name, "Ljava/util/List;")); + } + public void setIntegerField(String name, int value) { constructor.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); constructor.instructions.add(NodeUtils.push(value)); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/JARLauncherBinary.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/JARLauncherBinary.java index 5bd5ea78..aec99498 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/JARLauncherBinary.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/JARLauncherBinary.java @@ -3,9 +3,6 @@ import pro.gravit.launcher.Launcher; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.binary.tasks.*; -import pro.gravit.utils.helper.CommonHelper; -import pro.gravit.utils.helper.IOHelper; -import pro.gravit.utils.helper.LogHelper; import java.io.IOException; import java.nio.file.Files; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/CertificateAutogenTask.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/CertificateAutogenTask.java index c597034f..feaddff3 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/CertificateAutogenTask.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/CertificateAutogenTask.java @@ -20,7 +20,6 @@ import java.math.BigInteger; import java.nio.file.Path; import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.time.LocalDate; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java index 83946c33..de4491d2 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java @@ -4,9 +4,8 @@ import org.objectweb.asm.tree.ClassNode; import pro.gravit.launcher.AutogenConfig; import pro.gravit.launcher.Launcher; -import pro.gravit.launcher.LauncherConfig; import pro.gravit.launcher.SecureAutogenConfig; -import pro.gravit.launcher.serialize.HOutput; +import pro.gravit.launcher.SimpleAutogenConfig; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.asm.ClassMetadataReader; import pro.gravit.launchserver.asm.ConfigGenerator; @@ -23,7 +22,6 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; import java.util.*; import java.util.jar.JarFile; import java.util.stream.Collectors; @@ -126,6 +124,9 @@ public Path process(Path inputJar) throws IOException { ClassNode cn1 = new ClassNode(); new ClassReader(IOHelper.getResourceBytes(SecureAutogenConfig.class.getName().replace('.', '/').concat(".class"))).accept(cn1, 0); ConfigGenerator secureConfigurator = new ConfigGenerator(cn1); + ClassNode cn2 = new ClassNode(); + new ClassReader(IOHelper.getResourceBytes(SimpleAutogenConfig.class.getName().replace('.', '/').concat(".class"))).accept(cn2, 0); + ConfigGenerator runtimeConfigurator = new ConfigGenerator(cn2); BuildContext context = new BuildContext(output, launcherConfigurator, this); server.buildHookManager.hook(context); launcherConfigurator.setStringField("address", server.config.netty.address); @@ -173,11 +174,12 @@ public Path process(Path inputJar) throws IOException { }); String zPath = launcherConfigurator.getZipEntryPath(); String sPath = secureConfigurator.getZipEntryPath(); + String rPath = runtimeConfigurator.getZipEntryPath(); try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(inputJar))) { ZipEntry e = input.getNextEntry(); while (e != null) { String filename = e.getName(); - if (server.buildHookManager.isContainsBlacklist(filename) || e.isDirectory() || zPath.equals(filename) || sPath.equals(filename)) { + if (server.buildHookManager.isContainsBlacklist(filename) || e.isDirectory() || zPath.equals(filename) || sPath.equals(filename) || rPath.equals(filename)) { e = input.getNextEntry(); continue; } @@ -209,26 +211,17 @@ public Path process(Path inputJar) throws IOException { output.putNextEntry(newZipEntry(ent.getKey().replace('.', '/').concat(".class"))); output.write(server.buildHookManager.classTransform(ent.getValue(), ent.getKey(), this)); } - // map for guard + // Create launcher config file Map runtime = new HashMap<>(256); if (server.buildHookManager.buildRuntime()) { - // Write launcher guard dir IOHelper.walk(server.launcherBinary.runtimeDir, new RuntimeDirVisitor(output, runtime), false); IOHelper.walk(server.launcherBinary.guardDir, new GuardDirVisitor(output, runtime), false); } - // Create launcher config file - byte[] launcherConfigBytes; - try (ByteArrayOutputStream configArray = IOHelper.newByteArrayOutput()) { - try (HOutput configOutput = new HOutput(configArray)) { - new LauncherConfig(server.config.netty.address, server.publicKey, runtime, server.config.projectName) - .write(configOutput); - } - launcherConfigBytes = configArray.toByteArray(); - } - + runtimeConfigurator.setStringByteArrMapField("entries", runtime); + runtimeConfigurator.setByteArrayField("key", server.publicKey.getEncoded()); // Write launcher config file - output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE)); - output.write(launcherConfigBytes); + output.putNextEntry(newZipEntry(rPath)); + output.write(runtimeConfigurator.getBytecode(reader)); ZipEntry e = newZipEntry(zPath); output.putNextEntry(e); output.write(launcherConfigurator.getBytecode(reader)); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/SignJarTask.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/SignJarTask.java index 44eadd98..d327150d 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/SignJarTask.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/SignJarTask.java @@ -1,17 +1,8 @@ package pro.gravit.launchserver.binary.tasks; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.X500NameBuilder; -import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSSignedDataGenerator; -import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.binary.SignerJar; import pro.gravit.launchserver.config.LaunchServerConfig; @@ -21,23 +12,12 @@ import java.io.File; import java.io.IOException; -import java.math.BigInteger; import java.nio.file.Path; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Date; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/exe/Launch4JTask.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/exe/Launch4JTask.java index 11ab9927..08d743fb 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/exe/Launch4JTask.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/exe/Launch4JTask.java @@ -4,7 +4,6 @@ import net.sf.launch4j.Log; import net.sf.launch4j.config.*; import pro.gravit.launchserver.LaunchServer; -import pro.gravit.launchserver.binary.EXEL4JLauncherBinary; import pro.gravit.launchserver.binary.tasks.LauncherBuildTask; import pro.gravit.utils.Version; import pro.gravit.utils.helper.IOHelper; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/Launcher.java b/LauncherAPI/src/main/java/pro/gravit/launcher/Launcher.java index 70dafc79..369b95ec 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/Launcher.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/Launcher.java @@ -2,7 +2,6 @@ import pro.gravit.launcher.managers.GsonManager; import pro.gravit.launcher.profiles.ClientProfile; -import pro.gravit.launcher.serialize.HInput; import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.LogHelper; import pro.gravit.utils.helper.SecurityHelper; @@ -18,7 +17,6 @@ import java.util.regex.Pattern; public final class Launcher { - // Authlib constants @LauncherAPI public static final String SKIN_URL_PROPERTY = "skinURL"; @@ -43,8 +41,6 @@ public final class Launcher { @LauncherAPI public static final String GUARD_DIR = "guard"; @LauncherAPI - public static final String CONFIG_FILE = "config.bin"; - @LauncherAPI public static ClientProfile profile; @LauncherAPI public static final String INIT_SCRIPT_FILE = "init.js"; @@ -59,8 +55,8 @@ public final class Launcher { public static LauncherConfig getConfig() { LauncherConfig config = CONFIG.get(); if (config == null) { - try (HInput input = new HInput(IOHelper.newInput(IOHelper.getResourceURL(CONFIG_FILE)))) { - config = new LauncherConfig(input); + try { + config = new LauncherConfig(); } catch (IOException | InvalidKeySpecException e) { throw new SecurityException(e); } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java b/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java index 037c541f..b7145540 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java @@ -1,10 +1,6 @@ package pro.gravit.launcher; -import pro.gravit.launcher.serialize.HInput; -import pro.gravit.launcher.serialize.HOutput; -import pro.gravit.launcher.serialize.stream.StreamObject; import pro.gravit.utils.helper.SecurityHelper; -import pro.gravit.utils.helper.VerifyHelper; import pro.gravit.utils.verify.LauncherTrustManager; import java.io.IOException; @@ -13,9 +9,10 @@ import java.security.spec.InvalidKeySpecException; import java.util.*; -public final class LauncherConfig extends StreamObject { +public final class LauncherConfig { private static final AutogenConfig config = new AutogenConfig(); private static final SecureAutogenConfig secureConfig = new SecureAutogenConfig(); + private static final SimpleAutogenConfig runtimeConfig = new SimpleAutogenConfig(); public static AutogenConfig getAutogenConfig() { @@ -45,9 +42,8 @@ public static AutogenConfig getAutogenConfig() { public final String secureCheckSalt; public final String passwordEncryptKey; - @LauncherAPI - public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException { - publicKey = SecurityHelper.toPublicECKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH)); + public LauncherConfig() throws IOException, InvalidKeySpecException { + publicKey = SecurityHelper.toPublicECKey(runtimeConfig.key); secureCheckHash = config.secureCheckHash; secureCheckSalt = config.secureCheckSalt; passwordEncryptKey = config.passwordEncryptKey; @@ -72,46 +68,7 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException else env = LauncherEnvironment.STD; Launcher.applyLauncherEnv(env); environment = env; - // Read signed runtime - int count = input.readLength(0); - Map localResources = new HashMap<>(count); - for (int i = 0; i < count; i++) { - String name = input.readString(255); - VerifyHelper.putIfAbsent(localResources, name, - input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH), - String.format("Duplicate runtime resource: '%s'", name)); - } - runtime = Collections.unmodifiableMap(localResources); - } - - @LauncherAPI - public LauncherConfig(String address, ECPublicKey publicKey, Map runtime, String projectName) { - this.address = address; - this.publicKey = publicKey; - this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime)); - this.projectName = projectName; - this.clientPort = 32148; - guardType = "no"; - isWarningMissArchJava = true; - isNettyEnabled = false; - environment = LauncherEnvironment.STD; - secureCheckSalt = null; - secureCheckHash = null; - passwordEncryptKey = null; - trustManager = null; - } - - @Override - public void write(HOutput output) throws IOException { - output.writeByteArray(publicKey.getEncoded(), SecurityHelper.CRYPTO_MAX_LENGTH); - - // Write signed runtime - Set> entrySet = runtime.entrySet(); - output.writeLength(entrySet.size(), 0); - for (Map.Entry entry : runtime.entrySet()) { - output.writeString(entry.getKey(), 255); - output.writeByteArray(entry.getValue(), SecurityHelper.CRYPTO_MAX_LENGTH); - } + runtime = Collections.unmodifiableMap(runtimeConfig.entries); } public enum LauncherEnvironment { diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/SimpleAutogenConfig.java b/LauncherAPI/src/main/java/pro/gravit/launcher/SimpleAutogenConfig.java new file mode 100644 index 00000000..4af0c720 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/SimpleAutogenConfig.java @@ -0,0 +1,13 @@ +package pro.gravit.launcher; + +import java.util.Map; + +public class SimpleAutogenConfig { + public final Map entries; + public final byte[] key; + + public SimpleAutogenConfig() { + entries = null; + key = null; + } +} diff --git a/LauncherCore/src/main/java/pro/gravit/utils/helper/CryptoHelper.java b/LauncherCore/src/main/java/pro/gravit/utils/helper/CryptoHelper.java index 7106fca5..3a843df7 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/helper/CryptoHelper.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/helper/CryptoHelper.java @@ -1,6 +1,5 @@ package pro.gravit.utils.helper; -import java.io.OutputStream; import java.util.Objects; import java.util.function.LongSupplier;