diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76948fe..c4a8a65 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,10 +8,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 + - name: Set up JDK 16 uses: actions/setup-java@v3 with: - java-version: '8' + java-version: '16' distribution: 'temurin' - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v1 diff --git a/agent/build.gradle b/agent/build.gradle new file mode 100644 index 0000000..9e20533 --- /dev/null +++ b/agent/build.gradle @@ -0,0 +1,12 @@ +dependencies { + implementation project(':core') +} + +jar { + manifest { + attributes([ + "Premain-Class": "io.dogboy.serializationisbad.agent.SerializationIsBadAgent", + "Can-Redefine-Classes": "true", + ]) + } +} diff --git a/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java b/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java new file mode 100644 index 0000000..fd1e571 --- /dev/null +++ b/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java @@ -0,0 +1,24 @@ +package io.dogboy.serializationisbad.agent; + +import io.dogboy.serializationisbad.core.Patches; +import io.dogboy.serializationisbad.core.SerializationIsBad; +import org.objectweb.asm.tree.ClassNode; + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.security.ProtectionDomain; + +public class SIBTransformer implements ClassFileTransformer { + @Override + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { + String classNameDots = className.replace('/', '.'); + + if (Patches.getPatchModuleForClass(classNameDots) == null) return classfileBuffer; + + SerializationIsBad.logger.info("Applying patches to " + classNameDots); + + ClassNode classNode = Patches.readClassNode(classfileBuffer); + Patches.applyPatches(classNameDots, classNode); + return Patches.writeClassNode(classNode); + } +} diff --git a/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java b/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java new file mode 100644 index 0000000..3d37f54 --- /dev/null +++ b/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java @@ -0,0 +1,15 @@ +package io.dogboy.serializationisbad.agent; + +import io.dogboy.serializationisbad.core.SerializationIsBad; + +import java.io.File; +import java.lang.instrument.Instrumentation; + +public class SerializationIsBadAgent { + + public static void premain(String agentArgs, Instrumentation inst) { + SerializationIsBad.init(new File(".")); + inst.addTransformer(new SIBTransformer()); + } + +} diff --git a/build.gradle b/build.gradle index c7b7149..034dfb4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,60 +1,32 @@ -buildscript { - repositories { - maven { url = 'https://maven.minecraftforge.net/' } - mavenCentral() - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:3.+' - } +plugins { + id 'java' } - -apply plugin: 'net.minecraftforge.gradle' -apply plugin: 'eclipse' -apply plugin: 'maven-publish' - -version = '1.1.1' -group = 'io.dogboy.serializationisbad' -archivesBaseName = 'serializationisbad' - -sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' -minecraft { - mappings channel: 'snapshot', version: '20171003-1.12' +subprojects { + apply plugin: 'java' - runs { - client { - workingDirectory project.file('run') + sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.7' - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - property 'forge.logging.console.level', 'debug' + repositories { + maven { + url = 'https://maven.minecraftforge.net' } - - server { - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - property 'forge.logging.console.level', 'debug' + maven { + url = 'https://libraries.minecraft.net' } } } -dependencies { - minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2860' -} - -jar { - exclude("cpw/mods/fml/relauncher/FMLInjectionData.class") +task bundleJar(type: Jar, dependsOn: subprojects.assemble) { + archivesBaseName = rootProject.name + from project(':core').configurations.archives.allArtifacts.files.collect { zipTree(it) } + from project(':legacyforge').configurations.archives.allArtifacts.files.collect { zipTree(it) } + from project(':modlauncher').configurations.archives.allArtifacts.files.collect { zipTree(it) } + from project(':agent').configurations.archives.allArtifacts.files.collect { zipTree(it) } manifest { - attributes([ - "Specification-Title": project.name, - "Specification-Vendor": "dogboy21", - "Specification-Version": "1", - "Implementation-Title": project.name, - "Implementation-Version": "${version}", - "Implementation-Vendor" :"dogboy21", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), - "FMLCorePlugin": "io.dogboy.serializationisbad.SerializationIsBad", - ]) + from subprojects.collect{ it.jar.manifest } } } -jar.finalizedBy('reobfJar') +build.dependsOn bundleJar diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 0000000..b68ad01 --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'java-library' + +dependencies { + implementation 'com.google.code.gson:gson:2.10.1' + api 'org.apache.logging.log4j:log4j-api:2.20.0' + api 'org.ow2.asm:asm-tree:9.5' +} + +jar { + manifest { + attributes([ + "Specification-Title": rootProject.name, + "Specification-Vendor": "dogboy21", + "Specification-Version": "1", + "Implementation-Title": rootProject.name, + "Implementation-Version": "${rootProject.version}", + "Implementation-Vendor" : "dogboy21", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + ]) + } +} diff --git a/src/main/java/io/dogboy/serializationisbad/ClassFilteringObjectInputStream.java b/core/src/main/java/io/dogboy/serializationisbad/core/ClassFilteringObjectInputStream.java similarity index 78% rename from src/main/java/io/dogboy/serializationisbad/ClassFilteringObjectInputStream.java rename to core/src/main/java/io/dogboy/serializationisbad/core/ClassFilteringObjectInputStream.java index 6573ae3..d86ccbc 100644 --- a/src/main/java/io/dogboy/serializationisbad/ClassFilteringObjectInputStream.java +++ b/core/src/main/java/io/dogboy/serializationisbad/core/ClassFilteringObjectInputStream.java @@ -1,6 +1,6 @@ -package io.dogboy.serializationisbad; +package io.dogboy.serializationisbad.core; -import io.dogboy.serializationisbad.config.PatchModule; +import io.dogboy.serializationisbad.core.config.PatchModule; import java.io.IOException; import java.io.InputStream; @@ -24,12 +24,12 @@ private boolean isClassAllowed(String className) { className = className.substring(1, className.length() - 1); } - if (SerializationIsBad.config.getClassAllowlist().contains(className) + if (SerializationIsBad.getInstance().getConfig().getClassAllowlist().contains(className) || this.patchModule.getClassAllowlist().contains(className)) { return true; } - Set allowedPackages = new HashSet<>(SerializationIsBad.config.getPackageAllowlist()); + Set allowedPackages = new HashSet<>(SerializationIsBad.getInstance().getConfig().getPackageAllowlist()); allowedPackages.addAll(this.patchModule.getPackageAllowlist()); for (String allowedPackage : allowedPackages) { @@ -47,7 +47,8 @@ protected Class resolveClass(ObjectStreamClass desc) throws IOException, Clas if (!this.isClassAllowed(desc.getName())) { SerializationIsBad.logger.warn("Tried to resolve class " + desc.getName() + ", which is not allowed to be deserialized"); - if (SerializationIsBad.config.isExecuteBlocking()) throw new ClassNotFoundException("Class " + desc.getName() + " is not allowed to be deserialized"); + if (SerializationIsBad.getInstance().getConfig().isExecuteBlocking()) + throw new ClassNotFoundException("Class " + desc.getName() + " is not allowed to be deserialized"); } return super.resolveClass(desc); diff --git a/src/main/java/io/dogboy/serializationisbad/SIBTransformer.java b/core/src/main/java/io/dogboy/serializationisbad/core/Patches.java similarity index 56% rename from src/main/java/io/dogboy/serializationisbad/SIBTransformer.java rename to core/src/main/java/io/dogboy/serializationisbad/core/Patches.java index 9f92182..29490ae 100644 --- a/src/main/java/io/dogboy/serializationisbad/SIBTransformer.java +++ b/core/src/main/java/io/dogboy/serializationisbad/core/Patches.java @@ -1,6 +1,6 @@ -package io.dogboy.serializationisbad; +package io.dogboy.serializationisbad.core; -import net.minecraft.launchwrapper.IClassTransformer; +import io.dogboy.serializationisbad.core.config.PatchModule; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; @@ -12,46 +12,58 @@ import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.TypeInsnNode; -public class SIBTransformer implements IClassTransformer { - @Override - public byte[] transform(String name, String transformedName, byte[] basicClass) { - if (Patches.getPatchModuleForClass(transformedName) == null) return basicClass; +public class Patches { - SerializationIsBad.logger.info("Applying patches to " + transformedName); + public static PatchModule getPatchModuleForClass(String className) { + for (PatchModule patchModule : SerializationIsBad.getInstance().getConfig().getPatchModules()) { + if (patchModule.getClassesToPatch().contains(className)) { + return patchModule; + } + } + + return null; + } + public static ClassNode readClassNode(byte[] classBytecode) { ClassNode classNode = new ClassNode(); - ClassReader classReader = new ClassReader(basicClass); + ClassReader classReader = new ClassReader(classBytecode); classReader.accept(classNode, 0); + return classNode; + } + public static byte[] writeClassNode(ClassNode classNode) { + ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + classNode.accept(writer); + return writer.toByteArray(); + } + + public static void applyPatches(String className, ClassNode classNode) { for (MethodNode methodNode : classNode.methods) { InsnList instructions = methodNode.instructions; for (int i = 0; i < instructions.size(); i++) { AbstractInsnNode instruction = instructions.get(i); if (instruction.getOpcode() == Opcodes.NEW && instruction instanceof TypeInsnNode && "java/io/ObjectInputStream".equals(((TypeInsnNode) instruction).desc)) { - ((TypeInsnNode) instruction).desc = "io/dogboy/serializationisbad/ClassFilteringObjectInputStream"; + ((TypeInsnNode) instruction).desc = "io/dogboy/serializationisbad/core/ClassFilteringObjectInputStream"; - SerializationIsBad.logger.info("(1/2) Redirecting ObjectInputStream to ClassFilteringObjectInputStream in method " + methodNode.name); + SerializationIsBad.logger.info(" (1/2) Redirecting ObjectInputStream to ClassFilteringObjectInputStream in method " + methodNode.name); } else if (instruction.getOpcode() == Opcodes.INVOKESPECIAL && instruction instanceof MethodInsnNode && "java/io/ObjectInputStream".equals(((MethodInsnNode) instruction).owner) && "".equals(((MethodInsnNode) instruction).name)) { - ((MethodInsnNode) instruction).owner = "io/dogboy/serializationisbad/ClassFilteringObjectInputStream"; - ((MethodInsnNode) instruction).desc = "(Ljava/io/InputStream;Lio/dogboy/serializationisbad/config/PatchModule;)V"; + ((MethodInsnNode) instruction).owner = "io/dogboy/serializationisbad/core/ClassFilteringObjectInputStream"; + ((MethodInsnNode) instruction).desc = "(Ljava/io/InputStream;Lio/dogboy/serializationisbad/core/config/PatchModule;)V"; InsnList additionalInstructions = new InsnList(); - additionalInstructions.add(new LdcInsnNode(transformedName)); - additionalInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "io/dogboy/serializationisbad/Patches", - "getPatchModuleForClass", "(Ljava/lang/String;)Lio/dogboy/serializationisbad/config/PatchModule;", false)); + additionalInstructions.add(new LdcInsnNode(className)); + additionalInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "io/dogboy/serializationisbad/core/Patches", + "getPatchModuleForClass", "(Ljava/lang/String;)Lio/dogboy/serializationisbad/core/config/PatchModule;", false)); instructions.insertBefore(instruction, additionalInstructions); - SerializationIsBad.logger.info("(2/2) Redirecting ObjectInputStream to ClassFilteringObjectInputStream in method " + methodNode.name); + SerializationIsBad.logger.info(" (2/2) Redirecting ObjectInputStream to ClassFilteringObjectInputStream in method " + methodNode.name); } } } - - ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); - classNode.accept(writer); - return writer.toByteArray(); } + } diff --git a/core/src/main/java/io/dogboy/serializationisbad/core/SerializationIsBad.java b/core/src/main/java/io/dogboy/serializationisbad/core/SerializationIsBad.java new file mode 100644 index 0000000..2ffe639 --- /dev/null +++ b/core/src/main/java/io/dogboy/serializationisbad/core/SerializationIsBad.java @@ -0,0 +1,80 @@ +package io.dogboy.serializationisbad.core; + +import com.google.gson.Gson; +import io.dogboy.serializationisbad.core.config.SIBConfig; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +public class SerializationIsBad { + public static final Logger logger = LogManager.getLogger(SerializationIsBad.class); + private static SerializationIsBad instance; + private static boolean agentActive = false; + + public static SerializationIsBad getInstance() { + return SerializationIsBad.instance; + } + + public static void init(File minecraftDir) { + if (SerializationIsBad.instance != null) { + SerializationIsBad.logger.warn("Attempted to initialize SerializationIsBad twice, skipping"); + return; + } + + String implementationType = SerializationIsBad.getImplementationType(); + if (implementationType.equals("agent")) { + SerializationIsBad.agentActive = true; + } + SerializationIsBad.logger.info("Initializing SerializationIsBad, implementation type: " + implementationType); + SerializationIsBad.instance = new SerializationIsBad(minecraftDir); + } + + private final SIBConfig config; + + private SerializationIsBad(File minecraftDir) { + this.config = SerializationIsBad.readConfig(minecraftDir); + + SerializationIsBad.logger.info("Loaded config file"); + SerializationIsBad.logger.info(" Blocking Enabled: " + this.config.isExecuteBlocking()); + SerializationIsBad.logger.info(" Loaded Patch Modules: " + this.config.getPatchModules().size()); + } + + public SIBConfig getConfig() { + return this.config; + } + + private static SIBConfig readConfig(File minecraftDir) { + File configFile = new File(new File(minecraftDir, "config"), "serializationisbad.json"); + + if (configFile.isFile()) { + Gson gson = new Gson(); + try (FileInputStream fileInputStream = new FileInputStream(configFile)) { + return gson.fromJson(new InputStreamReader(fileInputStream, StandardCharsets.UTF_8), + SIBConfig.class); + } catch (Exception e) { + SerializationIsBad.logger.error("Failed to load config file", e); + } + } + + return new SIBConfig(); + } + + private static String getImplementationType() { + for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { + if (stackTraceElement.getClassName().startsWith("io.dogboy.serializationisbad.") + && !stackTraceElement.getClassName().startsWith("io.dogboy.serializationisbad.core.")) { + return stackTraceElement.getClassName().split("[.]")[3]; + } + } + + return "unknown"; + } + + public static boolean isAgentActive() { + return SerializationIsBad.agentActive; + } +} diff --git a/src/main/java/io/dogboy/serializationisbad/config/PatchModule.java b/core/src/main/java/io/dogboy/serializationisbad/core/config/PatchModule.java similarity index 95% rename from src/main/java/io/dogboy/serializationisbad/config/PatchModule.java rename to core/src/main/java/io/dogboy/serializationisbad/core/config/PatchModule.java index 1fcc311..f5500b2 100644 --- a/src/main/java/io/dogboy/serializationisbad/config/PatchModule.java +++ b/core/src/main/java/io/dogboy/serializationisbad/core/config/PatchModule.java @@ -1,4 +1,4 @@ -package io.dogboy.serializationisbad.config; +package io.dogboy.serializationisbad.core.config; import java.util.HashSet; import java.util.Set; diff --git a/src/main/java/io/dogboy/serializationisbad/config/SIBConfig.java b/core/src/main/java/io/dogboy/serializationisbad/core/config/SIBConfig.java similarity index 96% rename from src/main/java/io/dogboy/serializationisbad/config/SIBConfig.java rename to core/src/main/java/io/dogboy/serializationisbad/core/config/SIBConfig.java index 2b891db..d29f338 100644 --- a/src/main/java/io/dogboy/serializationisbad/config/SIBConfig.java +++ b/core/src/main/java/io/dogboy/serializationisbad/core/config/SIBConfig.java @@ -1,4 +1,4 @@ -package io.dogboy.serializationisbad.config; +package io.dogboy.serializationisbad.core.config; import java.util.ArrayList; import java.util.HashSet; diff --git a/gradle.properties b/gradle.properties index 878bf1f..eee28fe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,3 @@ -# Sets default memory used for gradle commands. Can be overridden by user or command line properties. -# This is required to provide enough memory for the Minecraft decompilation process. -org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false \ No newline at end of file +group=io.dogboy.serializationisbad +name=serializationisbad +version=1.2 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265e..0d4a951 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 949819d..84a0b92 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip diff --git a/legacyforge/build.gradle b/legacyforge/build.gradle new file mode 100644 index 0000000..c968766 --- /dev/null +++ b/legacyforge/build.gradle @@ -0,0 +1,15 @@ +dependencies { + implementation project(':core') + implementation 'net.minecraft:launchwrapper:1.12' +} + +jar { + exclude("cpw/mods/fml/relauncher/FMLInjectionData.class") + exclude("net/minecraftforge/fml/relauncher/FMLInjectionData.class") + + manifest { + attributes([ + "FMLCorePlugin": "io.dogboy.serializationisbad.legacyforge.SerializationIsBadCoreMod", + ]) + } +} diff --git a/src/main/java/cpw/mods/fml/relauncher/FMLInjectionData.java b/legacyforge/src/main/java/cpw/mods/fml/relauncher/FMLInjectionData.java similarity index 100% rename from src/main/java/cpw/mods/fml/relauncher/FMLInjectionData.java rename to legacyforge/src/main/java/cpw/mods/fml/relauncher/FMLInjectionData.java diff --git a/src/main/java/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java b/legacyforge/src/main/java/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java similarity index 100% rename from src/main/java/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java rename to legacyforge/src/main/java/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java diff --git a/legacyforge/src/main/java/io/dogboy/serializationisbad/legacyforge/SIBTransformer.java b/legacyforge/src/main/java/io/dogboy/serializationisbad/legacyforge/SIBTransformer.java new file mode 100644 index 0000000..b82bc3d --- /dev/null +++ b/legacyforge/src/main/java/io/dogboy/serializationisbad/legacyforge/SIBTransformer.java @@ -0,0 +1,19 @@ +package io.dogboy.serializationisbad.legacyforge; + +import io.dogboy.serializationisbad.core.Patches; +import io.dogboy.serializationisbad.core.SerializationIsBad; +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.tree.ClassNode; + +public class SIBTransformer implements IClassTransformer { + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (Patches.getPatchModuleForClass(transformedName) == null) return basicClass; + + SerializationIsBad.logger.info("Applying patches to " + transformedName); + + ClassNode classNode = Patches.readClassNode(basicClass); + Patches.applyPatches(transformedName, classNode); + return Patches.writeClassNode(classNode); + } +} diff --git a/legacyforge/src/main/java/io/dogboy/serializationisbad/legacyforge/SerializationIsBadCoreMod.java b/legacyforge/src/main/java/io/dogboy/serializationisbad/legacyforge/SerializationIsBadCoreMod.java new file mode 100644 index 0000000..a6b3a4d --- /dev/null +++ b/legacyforge/src/main/java/io/dogboy/serializationisbad/legacyforge/SerializationIsBadCoreMod.java @@ -0,0 +1,55 @@ +package io.dogboy.serializationisbad.legacyforge; + +import io.dogboy.serializationisbad.core.SerializationIsBad; + +import java.io.File; +import java.util.Map; + +@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name(SerializationIsBadCoreMod.modId) +@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions("io.dogboy.serializationisbad") +@cpw.mods.fml.relauncher.IFMLLoadingPlugin.Name(SerializationIsBadCoreMod.modId) +@cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions("io.dogboy.serializationisbad") +public class SerializationIsBadCoreMod implements net.minecraftforge.fml.relauncher.IFMLLoadingPlugin, cpw.mods.fml.relauncher.IFMLLoadingPlugin { + public static final String modId = "serializationisbad"; + + public SerializationIsBadCoreMod() { + if (SerializationIsBad.isAgentActive()) return; + + File minecraftHome = SerializationIsBadCoreMod.getMinecraftHome(); + SerializationIsBad.init(minecraftHome); + } + + @Override + public String[] getASMTransformerClass() { + if (SerializationIsBad.isAgentActive()) return new String[0]; + + return new String[]{ SIBTransformer.class.getCanonicalName() }; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) { } + + @Override + public String getAccessTransformerClass() { + return null; + } + + private static File getMinecraftHome() { + try { + return (File) net.minecraftforge.fml.relauncher.FMLInjectionData.data()[6]; + } catch (Throwable e) { + return (File) cpw.mods.fml.relauncher.FMLInjectionData.data()[6]; + } + } + +} diff --git a/legacyforge/src/main/java/net/minecraftforge/fml/relauncher/FMLInjectionData.java b/legacyforge/src/main/java/net/minecraftforge/fml/relauncher/FMLInjectionData.java new file mode 100644 index 0000000..1536e73 --- /dev/null +++ b/legacyforge/src/main/java/net/minecraftforge/fml/relauncher/FMLInjectionData.java @@ -0,0 +1,21 @@ +/* + * Forge Mod Loader + * Copyright (c) 2012-2013 cpw. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v2.1 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * Contributors: + * cpw - implementation + */ + +package net.minecraftforge.fml.relauncher; + + +public class FMLInjectionData +{ + public static Object[] data() { + throw new RuntimeException("Dummy implementation"); + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java b/legacyforge/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java similarity index 98% rename from src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java rename to legacyforge/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java index 40df6a8..69bfb62 100644 --- a/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java +++ b/legacyforge/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java @@ -19,7 +19,6 @@ package net.minecraftforge.fml.relauncher; -import javax.annotation.Nullable; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -61,7 +60,6 @@ public interface IFMLLoadingPlugin * minecraft class loading * TODO: implement crash ;) */ - @Nullable String getSetupClass(); /** diff --git a/modlauncher/build.gradle b/modlauncher/build.gradle new file mode 100644 index 0000000..5db3ab6 --- /dev/null +++ b/modlauncher/build.gradle @@ -0,0 +1,6 @@ +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' + +dependencies { + implementation project(':core') + implementation 'cpw.mods:modlauncher:8.0.0' +} diff --git a/modlauncher/src/main/java/io/dogboy/serializationisbad/modlauncher/SIBTransformer.java b/modlauncher/src/main/java/io/dogboy/serializationisbad/modlauncher/SIBTransformer.java new file mode 100644 index 0000000..14437db --- /dev/null +++ b/modlauncher/src/main/java/io/dogboy/serializationisbad/modlauncher/SIBTransformer.java @@ -0,0 +1,38 @@ +package io.dogboy.serializationisbad.modlauncher; + +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.ITransformerVotingContext; +import cpw.mods.modlauncher.api.TransformerVoteResult; +import io.dogboy.serializationisbad.core.Patches; +import io.dogboy.serializationisbad.core.config.PatchModule; +import org.objectweb.asm.tree.ClassNode; + +import java.util.Set; +import java.util.stream.Collectors; + +public class SIBTransformer implements ITransformer { + private final PatchModule patchModule; + + public SIBTransformer(PatchModule patchModule) { + this.patchModule = patchModule; + } + + @Override + public ClassNode transform(ClassNode input, ITransformerVotingContext context) { + Patches.applyPatches(input.name, input); + return input; + } + + @Override + public TransformerVoteResult castVote(ITransformerVotingContext context) { + return TransformerVoteResult.YES; + } + + @Override + public Set targets() { + return this.patchModule.getClassesToPatch().stream() + .map(Target::targetClass) + .collect(Collectors.toSet()); + } + +} diff --git a/modlauncher/src/main/java/io/dogboy/serializationisbad/modlauncher/SerializationIsBadTransformationService.java b/modlauncher/src/main/java/io/dogboy/serializationisbad/modlauncher/SerializationIsBadTransformationService.java new file mode 100644 index 0000000..0bac2f2 --- /dev/null +++ b/modlauncher/src/main/java/io/dogboy/serializationisbad/modlauncher/SerializationIsBadTransformationService.java @@ -0,0 +1,76 @@ +package io.dogboy.serializationisbad.modlauncher; + +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ITransformationService; +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.IncompatibleEnvironmentException; +import io.dogboy.serializationisbad.core.SerializationIsBad; + +import java.net.URL; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public class SerializationIsBadTransformationService implements ITransformationService { + + @Override + public String name() { + return "serializationisbad"; + } + + @Override + public void initialize(IEnvironment environment) { + if (SerializationIsBad.isAgentActive()) return; + + Path minecraftDir = environment.getProperty(IEnvironment.Keys.GAMEDIR.get()) + .orElseThrow(() -> new RuntimeException("No game path found")); + + SerializationIsBad.init(minecraftDir.toFile()); + } + + @Override + public void onLoad(IEnvironment env, Set otherServices) throws IncompatibleEnvironmentException { } + + @Override + public List transformers() { + if (SerializationIsBad.isAgentActive()) return Collections.emptyList(); + + return SerializationIsBad.getInstance().getConfig().getPatchModules().stream() + .map(SIBTransformer::new) + .collect(Collectors.toList()); + } + + @Override + public void beginScanning(IEnvironment environment) { } + + @Override + public Map.Entry, Supplier>>> additionalClassesLocator() { + if (SerializationIsBad.isAgentActive()) return null; + + return new Map.Entry, Supplier>>>() { + @Override + public Set getKey() { + return new HashSet<>(Arrays.asList("io.dogboy.serializationisbad.")); + } + + @Override + public Supplier>> getValue() { + return () -> str -> Optional.ofNullable(SerializationIsBadTransformationService.class.getResource("/" + str)); + } + + @Override + public Supplier>> setValue(Supplier>> value) { + throw new UnsupportedOperationException(); + } + }; + } + +} diff --git a/modlauncher/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/modlauncher/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService new file mode 100644 index 0000000..72a6291 --- /dev/null +++ b/modlauncher/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService @@ -0,0 +1 @@ +io.dogboy.serializationisbad.modlauncher.SerializationIsBadTransformationService \ No newline at end of file diff --git a/serializationisbad.json b/serializationisbad.json index 09d1388..a696b31 100644 --- a/serializationisbad.json +++ b/serializationisbad.json @@ -3,7 +3,8 @@ "patchModules": [ { "classesToPatch": [ - "net.bdew.lib.network.SerializedMessageCodec" + "net.bdew.lib.network.SerializedMessageCodec", + "net.bdew.lib.network.NetChannel" ], "classAllowlist": [], "packageAllowlist": [ @@ -66,6 +67,24 @@ "immersive_armors" ] }, + { + "classesToPatch": [ + "immersive_aircraft.cobalt.network.Message" + ], + "classAllowlist": [], + "packageAllowlist": [ + "immersive_aircraft" + ] + }, + { + "classesToPatch": [ + "immersive_paintings.cobalt.network.Message" + ], + "classAllowlist": [], + "packageAllowlist": [ + "immersive_paintings" + ] + }, { "classesToPatch": [ "gcewing.projectblue.BaseNBTChannel$NBTCodec" @@ -110,6 +129,217 @@ "packageAllowlist": [ "com.mattdahepic" ] + }, + { + "classesToPatch": [ + "com.iconmaster.aec.network.TransferConfigsPacket" + ], + "classAllowlist": [], + "packageAllowlist": [ + "com.iconmaster.aec" + ] + }, + { + "classesToPatch": [ + "net.tslat.aoa3.common.packet.leaderboard.PacketLeaderboardStats", + "net.tslat.aoa3.common.packet.leaderboard.PacketIndividualLeaderboardStats" + ], + "classAllowlist": [], + "packageAllowlist": [ + "net.tslat.aoa3" + ] + }, + { + "classesToPatch": [ + "pl.asie.lib.util.Base64" + ], + "classAllowlist": [], + "packageAllowlist": [ + "pl.asie" + ] + }, + { + "classesToPatch": [ + "arrowsplus.core.forge.PacketHandler" + ], + "classAllowlist": [], + "packageAllowlist": [ + "arrowsplus" + ] + }, + { + "classesToPatch": [ + "hellfirepvp.astralsorcery.common.network.packet.server.PktSyncConfig" + ], + "classAllowlist": [], + "packageAllowlist": [ + "hellfirepvp.astralsorcery" + ] + }, + { + "classesToPatch": [ + "mal.carbonization.network.MultiblockFurnaceMessageServer" + ], + "classAllowlist": [], + "packageAllowlist": [ + "mal.carbonization" + ] + }, + { + "classesToPatch": [ + "p455w0rd.capes.packet.PacketClientAddFriend", + "p455w0rd.capes.packet.PacketClientRemoveFriend", + "p455w0rd.capes.packet.PacketClientUpdateFriend", + "p455w0rd.capes.packet.PacketServerFriendSync", + "p455w0rd.capes.packet.PacketServerPlayerSync", + "p455w0rd.capes.packet.PacketServerTextureURLSync" + ], + "classAllowlist": [], + "packageAllowlist": [ + "p455w0rd.capes" + ] + }, + { + "classesToPatch": [ + "gcewing.sg.base.ForgeNBTNetworking$BasePacketHandler", + "gcewing.sg.BaseNBTChannel$NBTCodec", + "gcewing.sg.BaseNBTChannel$BasePacketHandler" + ], + "classAllowlist": [], + "packageAllowlist": [ + "gcewing.sg" + ] + }, + { + "classesToPatch": [ + "com.zerren.extrafirma.core.network.PacketHandler" + ], + "classAllowlist": [], + "packageAllowlist": [ + "com.zerren.extrafirma" + ] + }, + { + "classesToPatch": [ + "journeymap.common.network.impl.Message" + ], + "classAllowlist": [], + "packageAllowlist": [ + "journeymap" + ] + }, + { + "classesToPatch": [ + "com.polipo.bookshelf.net.MyMessage" + ], + "classAllowlist": [], + "packageAllowlist": [ + "com.polipo.bookshelf" + ] + }, + { + "classesToPatch": [ + "mca.PacketHandler", + "mca.core.forge.PacketHandler" + ], + "classAllowlist": [], + "packageAllowlist": [ + "mca" + ] + }, + { + "classesToPatch": [ + "logisticspipes.network.abstractpackets.GenericPacket", + "logisticspipes.network.packets.debuggui.DebugInfoUpdate", + "logisticspipes.network.packets.debuggui.DebugTargetResponse", + "logisticspipes.network.packets.debuggui.DebugTypePacket", + "logisticspipes.network.packets.routingdebug.RoutingUpdateTargetResponse" + ], + "classAllowlist": [], + "packageAllowlist": [ + "logisticspipes" + ] + }, + { + "classesToPatch": [ + "aeronicamc.mods.mxtune.network.NetworkSerializedHelper" + ], + "classAllowlist": [], + "packageAllowlist": [ + "aeronicamc.mods.mxtune" + ] + }, + { + "classesToPatch": [ + "p455w0rd.p455w0rdsthings.network.PacketConfigSync" + ], + "classAllowlist": [], + "packageAllowlist": [ + "p455w0rd.p455w0rdsthings" + ] + }, + { + "classesToPatch": [ + "radixcore.modules.RadixNettyIO" + ], + "classAllowlist": [], + "packageAllowlist": [ + "radixcore" + ] + }, + { + "classesToPatch": [ + "net.smart.moving.SmartMovingPacketStream" + ], + "classAllowlist": [], + "packageAllowlist": [ + "net.smart.moving" + ] + }, + { + "classesToPatch": [ + "svenhjol.strange.scrolls.message.ClientQuestList" + ], + "classAllowlist": [], + "packageAllowlist": [ + "svenhjol.strange" + ] + }, + { + "classesToPatch": [ + "com.supermartijn642.configlib.ConfigSyncPacket" + ], + "classAllowlist": [], + "packageAllowlist": [ + "com.supermartijn642" + ] + }, + { + "classesToPatch": [ + "vazkii.tinkerer.common.network.PacketManager" + ], + "classAllowlist": [], + "packageAllowlist": [ + "vazkii.tinkerer" + ] + }, + { + "classesToPatch": [ + "p455w0rd.tanaddons.network.PacketConfigSync" + ], + "classAllowlist": [], + "packageAllowlist": [ + "p455w0rd.tanaddons" + ] + }, + { + "classesToPatch": [ + "tterrag.core.common.config.PacketConfigSync" + ], + "classAllowlist": [], + "packageAllowlist": [ + "tterrag" + ] } ], "classAllowlist": [ diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..3500300 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include 'core', 'legacyforge', 'modlauncher', 'agent' diff --git a/src/main/java/io/dogboy/serializationisbad/Patches.java b/src/main/java/io/dogboy/serializationisbad/Patches.java deleted file mode 100644 index 9509c2e..0000000 --- a/src/main/java/io/dogboy/serializationisbad/Patches.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.dogboy.serializationisbad; - -import io.dogboy.serializationisbad.config.PatchModule; - -public class Patches { - public static PatchModule getPatchModuleForClass(String className) { - return SerializationIsBad.config.getPatchModules().stream() - .filter(patchModule -> patchModule.getClassesToPatch().contains(className)) - .findFirst() - .orElse(null); - } -} diff --git a/src/main/java/io/dogboy/serializationisbad/SerializationIsBad.java b/src/main/java/io/dogboy/serializationisbad/SerializationIsBad.java deleted file mode 100644 index 8a8813c..0000000 --- a/src/main/java/io/dogboy/serializationisbad/SerializationIsBad.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.dogboy.serializationisbad; - -import com.google.gson.Gson; -import io.dogboy.serializationisbad.config.SIBConfig; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.annotation.Nullable; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Map; - -@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name(SerializationIsBad.modId) -@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions("io.dogboy.serializationisbad") -@cpw.mods.fml.relauncher.IFMLLoadingPlugin.Name(SerializationIsBad.modId) -@cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions("io.dogboy.serializationisbad") -public class SerializationIsBad implements net.minecraftforge.fml.relauncher.IFMLLoadingPlugin, cpw.mods.fml.relauncher.IFMLLoadingPlugin { - public static final String modId = "serializationisbad"; - static final Logger logger = LogManager.getLogger(SerializationIsBad.class); - static SIBConfig config = new SIBConfig(); - - public SerializationIsBad() { - File minecraftHome = SerializationIsBad.getMinecraftHome(); - File configFile = new File(new File(minecraftHome, "config"), "serializationisbad.json"); - - if (configFile.isFile()) { - Gson gson = new Gson(); - try (FileInputStream fileInputStream = new FileInputStream(configFile)) { - SerializationIsBad.config = gson.fromJson(new InputStreamReader(fileInputStream, StandardCharsets.UTF_8), - SIBConfig.class); - - SerializationIsBad.logger.info("Loaded config file"); - SerializationIsBad.logger.info(" Blocking Enabled: " + SerializationIsBad.config.isExecuteBlocking()); - SerializationIsBad.logger.info(" Loaded Patch Modules: " + SerializationIsBad.config.getPatchModules().size()); - } catch (Exception e) { - SerializationIsBad.logger.error("Failed to load config file", e); - } - } - } - - @Override - public String[] getASMTransformerClass() { - return new String[]{ SIBTransformer.class.getCanonicalName() }; - } - - @Override - public String getModContainerClass() { - return null; - } - - @Nullable - @Override - public String getSetupClass() { - return null; - } - - @Override - public void injectData(Map data) { - - } - - @Override - public String getAccessTransformerClass() { - return null; - } - - private static File getMinecraftHome() { - try { - return (File) net.minecraftforge.fml.relauncher.FMLInjectionData.data()[6]; - } catch (Throwable e) { - return (File) cpw.mods.fml.relauncher.FMLInjectionData.data()[6]; - } - } - -}