mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
[FIX] Удалил JavaAssist из JAConfigurator - для возможности сложной обфускации.
This commit is contained in:
parent
898a3dd85d
commit
e8ba2cc557
4 changed files with 98 additions and 115 deletions
|
@ -1,109 +1,100 @@
|
||||||
package pro.gravit.launchserver.binary;
|
package pro.gravit.launchserver.binary;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.FieldInsnNode;
|
||||||
|
import org.objectweb.asm.tree.InsnList;
|
||||||
|
import org.objectweb.asm.tree.InsnNode;
|
||||||
|
import org.objectweb.asm.tree.IntInsnNode;
|
||||||
|
import org.objectweb.asm.tree.LdcInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
import org.objectweb.asm.tree.TypeInsnNode;
|
||||||
|
|
||||||
import javassist.CannotCompileException;
|
import org.objectweb.asm.Type;
|
||||||
import javassist.ClassPool;
|
|
||||||
import javassist.CtClass;
|
import pro.gravit.launcher.AutogenConfig;
|
||||||
import javassist.CtConstructor;
|
|
||||||
import javassist.CtMethod;
|
|
||||||
import javassist.NotFoundException;
|
|
||||||
import pro.gravit.launcher.LauncherConfig;
|
import pro.gravit.launcher.LauncherConfig;
|
||||||
import pro.gravit.launchserver.binary.tasks.MainBuildTask;
|
import pro.gravit.launcher.modules.Module;
|
||||||
|
import pro.gravit.launcher.modules.ModulesManager;
|
||||||
|
import pro.gravit.launchserver.asm.ClassMetadataReader;
|
||||||
|
import pro.gravit.launchserver.asm.SafeClassWriter;
|
||||||
|
|
||||||
public class JAConfigurator implements AutoCloseable {
|
public class JAConfigurator {
|
||||||
public ClassPool pool;
|
private static final String modulesManagerName = Type.getInternalName(ModulesManager.class);
|
||||||
public CtClass ctClass;
|
private static final String registerModDesc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Module.class));
|
||||||
public CtConstructor ctConstructor;
|
private static final String autoGenConfigName = Type.getInternalName(AutogenConfig.class);
|
||||||
public CtMethod initModuleMethod;
|
private static final String stringName = Type.getInternalName(String.class);
|
||||||
String classname;
|
private final ClassNode configclass;
|
||||||
StringBuilder body;
|
private final MethodNode constructor;
|
||||||
StringBuilder moduleBody;
|
private final MethodNode initModuleMethod;
|
||||||
int autoincrement;
|
|
||||||
|
|
||||||
public JAConfigurator(String configclass, MainBuildTask jarLauncherBinary) throws NotFoundException {
|
public JAConfigurator(ClassNode configclass) {
|
||||||
pool = new ClassPool(false);
|
this.configclass = configclass;
|
||||||
pool.appendSystemPath();
|
constructor = configclass.methods.stream().filter(e -> "<init>".equals(e.name)).findFirst().get();
|
||||||
classname = configclass;
|
constructor.instructions = new InsnList();
|
||||||
ctClass = pool.get(classname);
|
initModuleMethod = configclass.methods.stream().filter(e -> "initModules".equals(e.name)).findFirst().get();
|
||||||
ctConstructor = ctClass.getDeclaredConstructor(null);
|
initModuleMethod.instructions = new InsnList();
|
||||||
initModuleMethod = ctClass.getDeclaredMethod("initModules");
|
|
||||||
body = new StringBuilder("{ isInitModules = false; ");
|
|
||||||
moduleBody = new StringBuilder("{ isInitModules = true; ");
|
|
||||||
autoincrement = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addModuleClass(String fullName) {
|
public void addModuleClass(String fullName) {
|
||||||
moduleBody.append("pro.gravit.launcher.modules.Module mod");
|
initModuleMethod.instructions.insert(new MethodInsnNode(Opcodes.INVOKEINTERFACE, modulesManagerName, "registerModule", registerModDesc));
|
||||||
moduleBody.append(autoincrement);
|
initModuleMethod.instructions.insert(new MethodInsnNode(Opcodes.INVOKESPECIAL, fullName.replace('.', '/'), "<init>", "()V"));
|
||||||
moduleBody.append(" = new ");
|
initModuleMethod.instructions.insert(new TypeInsnNode(Opcodes.NEW, fullName.replace('.', '/')));
|
||||||
moduleBody.append(fullName);
|
|
||||||
moduleBody.append("();");
|
|
||||||
moduleBody.append("pro.gravit.launcher.Launcher.modulesManager.registerModule( mod");
|
|
||||||
moduleBody.append(autoincrement);
|
|
||||||
moduleBody.append(");");
|
|
||||||
autoincrement++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public byte[] getBytecode(ClassMetadataReader reader) {
|
||||||
public void close() {
|
ClassWriter cw = new SafeClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
|
||||||
ctClass.defrost();
|
configclass.accept(cw);
|
||||||
}
|
return cw.toByteArray();
|
||||||
|
|
||||||
public CtClass getCtClass() {
|
|
||||||
return ctClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytecode() throws IOException, CannotCompileException {
|
|
||||||
return ctClass.toBytecode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compile() throws CannotCompileException {
|
|
||||||
body.append("}");
|
|
||||||
moduleBody.append("}");
|
|
||||||
ctConstructor.setBody(body.toString());
|
|
||||||
initModuleMethod.insertAfter(moduleBody.toString());
|
|
||||||
if (ctClass.isFrozen()) ctClass.defrost();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getZipEntryPath() {
|
public String getZipEntryPath() {
|
||||||
return classname.replace('.', '/').concat(".class");
|
return configclass.name.concat(".class");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAddress(String address) {
|
public void setAddress(String address) {
|
||||||
body.append("this.address = \"");
|
constructor.instructions.add(new LdcInsnNode(address));
|
||||||
body.append(address);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "address", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProjectName(String name) {
|
public void setProjectName(String name) {
|
||||||
body.append("this.projectname = \"");
|
constructor.instructions.add(new LdcInsnNode(name));
|
||||||
body.append(name);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "projectname", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecretKey(String key) {
|
public void setSecretKey(String key) {
|
||||||
body.append("this.secretKeyClient = \"");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append(key);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "secretKeyClient", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOemUnlockKey(String key) {
|
public void setOemUnlockKey(String key) {
|
||||||
body.append("this.oemUnlockKey = \"");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append(key);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "oemUnlockKey", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGuardType(String key) {
|
public void setGuardType(String key) {
|
||||||
body.append("this.guardType = \"");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append(key);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardType", stringName));
|
||||||
body.append("\";");
|
}
|
||||||
|
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5)
|
||||||
|
constructor.instructions.add(new InsnNode(Opcodes.ICONST_0 + value));
|
||||||
|
else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
||||||
|
constructor.instructions.add(new IntInsnNode(Opcodes.BIPUSH, value));
|
||||||
|
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||||
|
constructor.instructions.add(new IntInsnNode(Opcodes.SIPUSH, value));
|
||||||
|
else
|
||||||
|
constructor.instructions.add(new LdcInsnNode(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
||||||
int i = 2;
|
int i = 2;
|
||||||
switch (env) {
|
|
||||||
|
|
||||||
|
switch (env) {
|
||||||
case DEV:
|
case DEV:
|
||||||
i = 0;
|
i = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -117,36 +108,35 @@ public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
||||||
i = 3;
|
i = 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
body.append("this.env = ");
|
push(i);
|
||||||
body.append(i);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "env", Type.INT_TYPE.getInternalName()));
|
||||||
body.append(";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClientPort(int port) {
|
public void setClientPort(int port) {
|
||||||
body.append("this.clientPort = ");
|
push(port);
|
||||||
body.append(port);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "clientPort", Type.INT_TYPE.getInternalName()));
|
||||||
body.append(";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWarningMissArchJava(boolean b) {
|
public void setWarningMissArchJava(boolean b) {
|
||||||
body.append("this.isWarningMissArchJava = ");
|
constructor.instructions.add(new InsnNode(b ? Opcodes.ICONST_1 : Opcodes.ICONST_0));
|
||||||
body.append(b ? "true" : "false");
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "isWarningMissArchJava", Type.BOOLEAN_TYPE.getInternalName()));
|
||||||
body.append(";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGuardLicense(String name, String key, String encryptKey) {
|
public void setGuardLicense(String name, String key, String encryptKey) {
|
||||||
body.append("this.guardLicenseName = \"");
|
constructor.instructions.add(new LdcInsnNode(name));
|
||||||
body.append(name);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseName", stringName));
|
||||||
body.append("\";");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append("this.guardLicenseKey = \"");
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseKey", stringName));
|
||||||
body.append(key);
|
constructor.instructions.add(new LdcInsnNode(encryptKey));
|
||||||
body.append("\";");
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseEncryptKey", stringName));
|
||||||
body.append("this.guardLicenseEncryptKey = \"");
|
|
||||||
body.append(encryptKey);
|
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassPool getPool() {
|
public void nullGuardLicense() {
|
||||||
return pool;
|
constructor.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseName", stringName));
|
||||||
|
constructor.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseKey", stringName));
|
||||||
|
constructor.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseEncryptKey", stringName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,9 @@
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import javassist.CannotCompileException;
|
import org.objectweb.asm.ClassReader;
|
||||||
import javassist.NotFoundException;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
import pro.gravit.launcher.AutogenConfig;
|
import pro.gravit.launcher.AutogenConfig;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.LauncherConfig;
|
import pro.gravit.launcher.LauncherConfig;
|
||||||
|
@ -115,22 +116,17 @@ public String getName() {
|
||||||
@Override
|
@Override
|
||||||
public Path process(Path inputJar) throws IOException {
|
public Path process(Path inputJar) throws IOException {
|
||||||
Path outputJar = server.launcherBinary.nextPath("main");
|
Path outputJar = server.launcherBinary.nextPath("main");
|
||||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(outputJar));
|
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(outputJar))) {
|
||||||
JAConfigurator jaConfigurator = new JAConfigurator(AutogenConfig.class.getName(), this)) {
|
ClassNode cn = new ClassNode();
|
||||||
jaConfigurator.pool.insertClassPath(inputJar.toFile().getAbsolutePath());
|
new ClassReader(IOHelper.getResourceBytes(AutogenConfig.class.getName().replace('.', '/').concat(".class"))).accept(cn, 0);
|
||||||
server.launcherBinary.coreLibs.stream().map(e -> e.toFile().getAbsolutePath())
|
JAConfigurator jaConfigurator = new JAConfigurator(cn);
|
||||||
.forEach(t -> {
|
|
||||||
try {
|
|
||||||
jaConfigurator.pool.appendClassPath(t);
|
|
||||||
} catch (NotFoundException e2) {
|
|
||||||
LogHelper.error(e2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
BuildContext context = new BuildContext(output, jaConfigurator, this);
|
BuildContext context = new BuildContext(output, jaConfigurator, this);
|
||||||
server.buildHookManager.hook(context);
|
server.buildHookManager.hook(context);
|
||||||
jaConfigurator.setAddress(server.config.netty.address);
|
jaConfigurator.setAddress(server.config.netty.address);
|
||||||
if (server.config.guardLicense != null)
|
if (server.config.guardLicense != null)
|
||||||
jaConfigurator.setGuardLicense(server.config.guardLicense.name, server.config.guardLicense.key, server.config.guardLicense.encryptKey);
|
jaConfigurator.setGuardLicense(server.config.guardLicense.name, server.config.guardLicense.key, server.config.guardLicense.encryptKey);
|
||||||
|
else
|
||||||
|
jaConfigurator.nullGuardLicense();
|
||||||
jaConfigurator.setProjectName(server.config.projectName);
|
jaConfigurator.setProjectName(server.config.projectName);
|
||||||
jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey());
|
jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey());
|
||||||
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
||||||
|
@ -148,11 +144,12 @@ public Path process(Path inputJar) throws IOException {
|
||||||
LogHelper.error(e1);
|
LogHelper.error(e1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
String zPath = jaConfigurator.getZipEntryPath();
|
||||||
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(inputJar))) {
|
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(inputJar))) {
|
||||||
ZipEntry e = input.getNextEntry();
|
ZipEntry e = input.getNextEntry();
|
||||||
while (e != null) {
|
while (e != null) {
|
||||||
String filename = e.getName();
|
String filename = e.getName();
|
||||||
if (server.buildHookManager.isContainsBlacklist(filename) || e.isDirectory()) {
|
if (server.buildHookManager.isContainsBlacklist(filename) || e.isDirectory() || zPath.equals(filename)) {
|
||||||
e = input.getNextEntry();
|
e = input.getNextEntry();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -204,12 +201,9 @@ public Path process(Path inputJar) throws IOException {
|
||||||
// Write launcher config file
|
// Write launcher config file
|
||||||
output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE));
|
output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE));
|
||||||
output.write(launcherConfigBytes);
|
output.write(launcherConfigBytes);
|
||||||
ZipEntry e = newZipEntry(jaConfigurator.getZipEntryPath());
|
ZipEntry e = newZipEntry(zPath);
|
||||||
output.putNextEntry(e);
|
output.putNextEntry(e);
|
||||||
jaConfigurator.compile();
|
output.write(jaConfigurator.getBytecode(reader));
|
||||||
output.write(jaConfigurator.getBytecode());
|
|
||||||
} catch (CannotCompileException | NotFoundException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
}
|
||||||
reader.close();
|
reader.close();
|
||||||
return outputJar;
|
return outputJar;
|
||||||
|
|
|
@ -4,8 +4,6 @@ public class AutogenConfig {
|
||||||
public String projectname;
|
public String projectname;
|
||||||
public String address;
|
public String address;
|
||||||
public int clientPort;
|
public int clientPort;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private boolean isInitModules;
|
|
||||||
public String guardType;
|
public String guardType;
|
||||||
public String secretKeyClient;
|
public String secretKeyClient;
|
||||||
public String oemUnlockKey;
|
public String oemUnlockKey;
|
||||||
|
@ -23,5 +21,6 @@ public class AutogenConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initModules() {
|
public void initModules() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
modules
2
modules
|
@ -1 +1 @@
|
||||||
Subproject commit f6831f4df4633b9ba67edc194580833c7a19ce51
|
Subproject commit 36559441ba26db3cc71818bd8a93b6464f7f00e0
|
Loading…
Reference in a new issue