mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-04-01 22:14:01 +03:00
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.
This commit is contained in:
parent
1366f6587e
commit
b20ac37c0b
13 changed files with 139 additions and 41 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<String> blacklist) throws IOEx
|
|||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
output.putNextEntry(e);
|
||||
output.putNextEntry(IOHelper.newZipEntry(e));
|
||||
IOHelper.transfer(input, output);
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
|
|
|
@ -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<Path> {
|
||||
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<BuildHook> POST_HOOKS;
|
||||
private final Set<Runnable> 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<byte[], ClassMetadataReader, byte[]> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -13,9 +13,6 @@ isDownloadJava: false;
|
|||
# White list testers
|
||||
whitelistRejectString: "Вас нет в белом списке";
|
||||
|
||||
# Proguard
|
||||
proguardPrintMappings: false;
|
||||
|
||||
# Auth handler
|
||||
authHandler: "textFile";
|
||||
authHandlerConfig: {
|
||||
|
|
|
@ -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.** {
|
||||
*;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
2
modules
2
modules
|
@ -1 +1 @@
|
|||
Subproject commit 79e24c862b2324b7751f1520f9732eed31416c6d
|
||||
Subproject commit c4705248d6e6576294a9ff62edd4dd263b682533
|
Loading…
Reference in a new issue