From 02c2795ef5855e984ff63857c7b56fedd46f32ca Mon Sep 17 00:00:00 2001 From: Zaxar163 <35835496+Zaxar163@users.noreply.github.com> Date: Mon, 17 Dec 2018 18:34:24 +0300 Subject: [PATCH] Fixes writer (#105) * Optimizations of NodeTransformer. * AntiFernflower... * Node fast. * Full decomp. * Name fixes. * Fixed #99. * LaunchServer stopped entry fixed. * Fixed bug what I get at morning. * Obf is disabled now! * Added wrap. Fixed NeverDecomp. * Noverify option. * Final fix. --- .../ru/gravit/launchserver/LaunchServer.java | 20 ++--- .../ru/gravit/launchserver/ProguardConf.java | 18 ++-- .../gravit/launchserver/asm/AntiDecomp.java | 88 +++++++++++++++++++ .../launchserver/binary/BuildContext.java | 4 +- .../binary/JARLauncherBinary.java | 3 +- .../command/basic/ProguardCleanCommand.java | 6 +- .../manangers/BuildHookManager.java | 19 +++- .../manangers/NodeTransformer.java | 4 +- .../gravit/launchserver/defaults/config.cfg | 3 - .../gravit/launchserver/defaults/proguard.cfg | 4 +- .../launcher/ClientLauncherWrapper.java | 5 +- .../launcher/client/ClientLauncher.java | 4 +- modules | 2 +- 13 files changed, 139 insertions(+), 41 deletions(-) create mode 100644 LaunchServer/src/main/java/ru/gravit/launchserver/asm/AntiDecomp.java diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java index 1247f512..a5b5fd99 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java @@ -105,8 +105,6 @@ public static final class Config extends ConfigObject { public final String projectName; public final String whitelistRejectString; - - public final boolean genMappings; public final boolean isUsingWrapper; public final boolean isDownloadJava; @@ -150,7 +148,6 @@ private Config(BlockConfigEntry block, Path coredir, LaunchServer server) { block.getEntry("hwidHandlerConfig", BlockConfigEntry.class)); // Set misc config - genMappings = block.getEntryValue("proguardPrintMappings", BooleanConfigEntry.class); mirrors = block.getEntry("mirrors", ListConfigEntry.class); launch4j = new ExeConf(block.getEntry("launch4J", BlockConfigEntry.class)); buildPostTransform = new PostBuildTransformConf(block.getEntry("buildExtendedOperation", BlockConfigEntry.class), coredir); @@ -261,7 +258,8 @@ private PostBuildTransformConf(BlockConfigEntry block, Path coredir) { } } - public static void main(String... args) throws Throwable { + @SuppressWarnings("resource") + public static void main(String... args) throws Throwable { JVMHelper.checkStackTrace(LaunchServer.class); JVMHelper.verifySystemProperties(LaunchServer.class, true); LogHelper.addOutput(IOHelper.WORKING_DIR.resolve("LaunchServer.log")); @@ -271,9 +269,7 @@ public static void main(String... args) throws Throwable { // Start LaunchServer Instant start = Instant.now(); try { - try (LaunchServer lsrv = new LaunchServer(IOHelper.WORKING_DIR)) { - lsrv.run(); - } + new LaunchServer(IOHelper.WORKING_DIR).run(); } catch (Throwable exc) { LogHelper.error(exc); return; @@ -360,7 +356,6 @@ public LaunchServer(Path dir) throws IOException, InvalidKeySpecException { CommandHandler localCommandHandler; try { Class.forName("jline.Terminal"); - // JLine2 available localCommandHandler = new JLineCommandHandler(this); LogHelper.info("JLine2 terminal enabled"); @@ -382,7 +377,8 @@ public LaunchServer(Path dir) throws IOException, InvalidKeySpecException { KeyPair pair = SecurityHelper.genRSAKeyPair(); publicKey = (RSAPublicKey) pair.getPublic(); privateKey = (RSAPrivateKey) pair.getPrivate(); - + Files.deleteIfExists(publicKeyFile); + Files.deleteIfExists(privateKeyFile); // Write key pair files LogHelper.info("Writing RSA keypair files"); IOHelper.write(publicKeyFile, publicKey.getEncoded()); @@ -450,7 +446,11 @@ public LaunchServer(Path dir) throws IOException, InvalidKeySpecException { } private LauncherBinary binary() { - if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this); + try { + Class.forName("net.sf.launch4j.Builder"); + if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this); + } catch (ClassNotFoundException ignored) { + } return new EXELauncherBinary(this); } diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/ProguardConf.java b/LaunchServer/src/main/java/ru/gravit/launchserver/ProguardConf.java index 29e38b60..7342582c 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/ProguardConf.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/ProguardConf.java @@ -1,8 +1,8 @@ package ru.gravit.launchserver; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.file.Files; @@ -10,9 +10,13 @@ import java.security.SecureRandom; import java.util.ArrayList; +import ru.gravit.launcher.serialize.config.TextConfigReader; +import ru.gravit.launcher.serialize.config.TextConfigWriter; +import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry; import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.SecurityHelper; +import ru.gravit.utils.helper.UnpackHelper; public class ProguardConf { private static final String charsFirst = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; @@ -38,10 +42,10 @@ public ProguardConf(LaunchServer srv) { words = proguard.resolve("random.pro"); confStrs = new ArrayList<>(); prepare(false); - if (srv.config.genMappings) confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'"); + confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'"); confStrs.add("-obfuscationdictionary \'" + words.toFile().getName() + "\'"); confStrs.add("-injar \'" + srv.dir.toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + "-nonObf.jar\'"); - confStrs.add("-outjar \'" + srv.dir.toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + "-obfed.jar\'"); + confStrs.add("-outjar \'" + srv.dir.toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + "-obfPre.jar\'"); confStrs.add("-classobfuscationdictionary \'" + words.toFile().getName() + "\'"); confStrs.add(readConf()); @@ -50,16 +54,12 @@ public ProguardConf(LaunchServer srv) { private void genConfig(boolean force) throws IOException { if (IOHelper.exists(config) && !force) return; Files.deleteIfExists(config); - config.toFile().createNewFile(); - try (OutputStream out = IOHelper.newOutput(config); InputStream in = IOHelper.newInput(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/proguard.cfg"))) { - IOHelper.transfer(in, out); - } + UnpackHelper.unpack(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/proguard.cfg"), config); } public void genWords(boolean force) throws IOException { if (IOHelper.exists(words) && !force) return; Files.deleteIfExists(words); - words.toFile().createNewFile(); SecureRandom rand = SecurityHelper.newRandom(); rand.setSeed(SecureRandom.getSeed(32)); try (PrintWriter out = new PrintWriter(new OutputStreamWriter(IOHelper.newOutput(words), IOHelper.UNICODE_CHARSET))) { diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/asm/AntiDecomp.java b/LaunchServer/src/main/java/ru/gravit/launchserver/asm/AntiDecomp.java new file mode 100644 index 00000000..2ec6b426 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/asm/AntiDecomp.java @@ -0,0 +1,88 @@ +package ru.gravit.launchserver.asm; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.security.SecureRandom; +import java.util.Random; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.AdviceAdapter; + +public class AntiDecomp { + private static final Class[] exceptionsL = { + Throwable.class, Exception.class, Error.class, InternalError.class, RuntimeException.class, NullPointerException.class, + AssertionError.class, NoClassDefFoundError.class, IOException.class, NoSuchFieldException.class, SecurityException.class, InvocationTargetException.class + }; + private static class AObfClassVisitor extends ClassVisitor { + private Random r = new SecureRandom(); + private AObfClassVisitor(ClassVisitor classVisitor) { + super(Opcodes.ASM7, classVisitor); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + return new AdviceAdapter(Opcodes.ASM7, super.visitMethod(access, name, desc, signature, exceptions), access, + name, desc) { + + @Override + public void onMethodEnter() { + antiDecomp(); + } + + public void antiDecomp() { + Label lbl1 = this.newLabel(), lbl15 = this.newLabel(), + lbl2 = this.newLabel(), lbl3 = this.newLabel(), + lbl35 = this.newLabel(), lbl4 = this.newLabel(); + + // try-catch блок с lbl1 до lbl2 с переходом на lbl15 при java/lang/Exception + this.visitException(lbl1, lbl2, lbl15); + // try-catch блок с lbl3 до lbl4 с переходом на lbl3 при java/lang/Exception + this.visitException(lbl3, lbl4, lbl3); + + // lbl1: goto lbl2 + this.visitLabel(lbl1); + this.jumpLabel(lbl2); + // lbl15: pop + this.visitLabel(lbl15); + this.visitInsn(POP); + // lbl2: goto lbl35 + this.visitLabel(lbl2); + this.jumpLabel(lbl35); + // lbl3: pop + this.visitLabel(lbl3); + this.visitInsn(POP); + // lbl35: nop + this.visitLabel(lbl35); + this.visitInsn(NOP); + // lbl4: nop + this.visitLabel(lbl4); + this.visitInsn(NOP); + } + + public void visitException(Label st, Label en, Label h) { + super.visitTryCatchBlock(st, en, h, Type.getInternalName(exceptionsL[r.nextInt(exceptionsL.length-1)])); + } + + public void jumpLabel(Label to) { + super.visitJumpInsn(GOTO, to); + } + }; + } + } + + private AntiDecomp() { + } + + public static byte[] antiDecomp(final byte[] input, ClassMetadataReader reader) { + ClassReader cr = new ClassReader(input); + ClassWriter cw = new SafeClassWriter(reader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cr.accept(new AObfClassVisitor(cw), ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES); + return cw.toByteArray(); + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/BuildContext.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/BuildContext.java index 49a9e669..0e3028cf 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/BuildContext.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/BuildContext.java @@ -29,7 +29,7 @@ public void pushFile(String filename, InputStream inputStream) throws IOExceptio public void pushJarFile(ZipInputStream input) throws IOException { ZipEntry e = input.getNextEntry(); while (e != null) { - output.putNextEntry(e); + output.putNextEntry(IOHelper.newZipEntry(e)); IOHelper.transfer(input, output); e = input.getNextEntry(); } @@ -42,7 +42,7 @@ public void pushJarFile(ZipInputStream input, Set blacklist) throws IOEx e = input.getNextEntry(); continue; } - output.putNextEntry(e); + output.putNextEntry(IOHelper.newZipEntry(e)); IOHelper.transfer(input, output); e = input.getNextEntry(); } diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java index 8aef49b1..cbab0d08 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java @@ -40,6 +40,7 @@ import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm; import ru.gravit.utils.helper.UnpackHelper; +// TODO: exclusions impl public final class JARLauncherBinary extends LauncherBinary { private final class RuntimeDirVisitor extends SimpleFileVisitor { @@ -126,7 +127,7 @@ public JARLauncherBinary(LaunchServer server) throws IOException { runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR); guardDir = server.dir.resolve(Launcher.GUARD_DIR); initScriptFile = runtimeDir.resolve(Launcher.INIT_SCRIPT_FILE); - obfJar = server.dir.resolve(server.config.binaryName + "-obfed.jar"); + obfJar = server.dir.resolve(server.config.binaryName + "-obfPre.jar"); obfOutJar = server.config.buildPostTransform.enabled ? server.dir.resolve(server.config.binaryName + "-obf.jar") : syncBinaryFile; cleanJar = server.dir.resolve(server.config.binaryName + "-clean.jar"); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/command/basic/ProguardCleanCommand.java b/LaunchServer/src/main/java/ru/gravit/launchserver/command/basic/ProguardCleanCommand.java index 704f1c6d..b2dd5014 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/command/basic/ProguardCleanCommand.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/command/basic/ProguardCleanCommand.java @@ -1,5 +1,8 @@ package ru.gravit.launchserver.command.basic; +import java.io.IOException; +import java.nio.file.Files; + import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.command.Command; @@ -19,7 +22,8 @@ public String getUsageDescription() { } @Override - public void invoke(String... args) { + public void invoke(String... args) throws IOException { server.proguardConf.prepare(true); + Files.deleteIfExists(server.proguardConf.mappings); } } diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/BuildHookManager.java b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/BuildHookManager.java index 0a449d24..81c47339 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/BuildHookManager.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/BuildHookManager.java @@ -4,10 +4,12 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.function.BiFunction; import java.util.zip.ZipOutputStream; import ru.gravit.launcher.AutogenConfig; import ru.gravit.launcher.modules.TestClientModule; +import ru.gravit.launchserver.asm.ClassMetadataReader; import ru.gravit.launchserver.binary.BuildContext; import ru.gravit.launchserver.binary.JAConfigurator; import ru.gravit.launchserver.binary.JARLauncherBinary; @@ -28,6 +30,11 @@ public static interface Transformer { byte[] transform(byte[] input, String classname, JARLauncherBinary data); } + @FunctionalInterface + public static interface ReaderTransformer { + byte[] transform(byte[] input, String classname, ClassMetadataReader data); + } + private boolean BUILDRUNTIME; private final Set POST_HOOKS; private final Set POST_PROGUARDRUN_HOOKS; @@ -154,10 +161,6 @@ public void registerProGuardHook(Transformer hook) { POST_PROGUARD_HOOKS.add(hook); } - public boolean isNeedPostProguardHook() { - return POST_PROGUARD_HOOKS.size() > 1 || !POST_PROGUARDRUN_HOOKS.isEmpty() || !POST_PROGUARD_BUILDHOOKS.isEmpty() || !proguardNoder.getTransLst().isEmpty(); - } - public void registerPreHook(BuildHook hook) { PRE_HOOKS.add(hook); } @@ -165,4 +168,12 @@ public void registerPreHook(BuildHook hook) { public void setBuildRuntime(boolean runtime) { BUILDRUNTIME = runtime; } + + public static Transformer wrap(BiFunction func) { + return (code, name, binaryCls) -> func.apply(code, binaryCls.reader); + } + + public static Transformer wrap(ReaderTransformer func) { + return (code, name, binaryCls) -> func.transform(code, name, binaryCls.reader); + } } diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/NodeTransformer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/NodeTransformer.java index 3f713df9..47568683 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/NodeTransformer.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/NodeTransformer.java @@ -31,9 +31,9 @@ public NodeTransformer() { public byte[] transform(byte[] input, String classname, JARLauncherBinary data) { ClassReader cr = new ClassReader(input); ClassNode cn = new ClassNode(); - cr.accept(cn, ClassReader.SKIP_DEBUG); + cr.accept(cn, ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES); for (ClassNodeTransformer tr : transLst) tr.transform(cn, classname, data); - ClassWriter cw = new SafeClassWriter(data.reader, ClassWriter.COMPUTE_MAXS); + ClassWriter cw = new SafeClassWriter(data.reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); cn.accept(cw); return cw.toByteArray(); } diff --git a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg index 954f8d01..00249256 100644 --- a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg +++ b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg @@ -13,9 +13,6 @@ isDownloadJava: false; # White list testers whitelistRejectString: "Вас нет в белом списке"; -# Proguard -proguardPrintMappings: false; - # Auth handler authHandler: "textFile"; authHandlerConfig: { diff --git a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/proguard.cfg b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/proguard.cfg index c08bbda3..1776cd74 100644 --- a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/proguard.cfg +++ b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/proguard.cfg @@ -19,9 +19,9 @@ -keepattributes Signature -adaptresourcefilecontents META-INF/MANIFEST.MF --keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.** +-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**,org.slf4j.** --keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**,org.slf4j.**,oshi.jna.**,com.sun.jna.** { +-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**,org.slf4j.** { *; } diff --git a/Launcher/src/main/java/ru/gravit/launcher/ClientLauncherWrapper.java b/Launcher/src/main/java/ru/gravit/launcher/ClientLauncherWrapper.java index 7252244e..e287fdbd 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/ClientLauncherWrapper.java +++ b/Launcher/src/main/java/ru/gravit/launcher/ClientLauncherWrapper.java @@ -30,10 +30,7 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep args.add(javaBin.toString()); String pathLauncher = IOHelper.getCodeSource(ClientLauncher.class).toString(); args.add(JVMHelper.jvmProperty(LogHelper.DEBUG_PROPERTY, Boolean.toString(LogHelper.isDebugEnabled()))); - Collections.addAll(args, "-javaagent:".concat(pathLauncher)); - Collections.addAll(args, "-cp"); - Collections.addAll(args, pathLauncher); - Collections.addAll(args, LauncherEngine.class.getName()); + Collections.addAll(args, "-noverify", "-javaagent:".concat(pathLauncher), "-cp", pathLauncher, LauncherEngine.class.getName()); EnvHelper.addEnv(processBuilder); LogHelper.debug("Commandline: " + args); processBuilder.command(args); diff --git a/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java b/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java index 1eaba689..02045b81 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java +++ b/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java @@ -379,10 +379,10 @@ public static Process launch( Collections.addAll(args, "-Djava.library.path=".concat(params.clientDir.resolve(NATIVES_DIR).toString())); // Add Native Path Collections.addAll(args, "-javaagent:".concat(pathLauncher)); if(wrapper) - Collections.addAll(args, "-Djava.class.path=".concat(pathLauncher)); // Add Class Path + Collections.addAll(args, "-Djava.class.path=".concat(pathLauncher), "-noverify"); // Add Class Path else { - Collections.addAll(args, "-cp"); + Collections.addAll(args, "-noverify", "-cp"); Collections.addAll(args, pathLauncher); } Collections.addAll(args, ClientLauncher.class.getName()); diff --git a/modules b/modules index 79e24c86..c4705248 160000 --- a/modules +++ b/modules @@ -1 +1 @@ -Subproject commit 79e24c862b2324b7751f1520f9732eed31416c6d +Subproject commit c4705248d6e6576294a9ff62edd4dd263b682533