From 75e781d08e2096d56dd90c6640e400b42a6c79b1 Mon Sep 17 00:00:00 2001 From: Zaxar163 <35835496+Zaxar163@users.noreply.github.com> Date: Fri, 12 Apr 2019 23:22:24 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=84=D0=B8=D0=BA=D1=81=D0=B8?= =?UTF-8?q?=D0=BB=20ASM.=20=D0=A2=D1=80=D0=B5=D0=B1=D1=83=D0=B5=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D1=82=D0=B5=D1=81=D1=82!=20(#216)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [FIX] ASM bundling. * Revert "[FIX] Agent работает." This reverts commit 76a9c07a4802bae69907e1c27f021d10b3c5a345. * Revert "[FIX] Удалена sm часть LauncherAgent" This reverts commit 54c7526a66a6bb3397e62c32794ffc42e3da061f. * [FIX] Закрываем ресурсы в LauncherAgent. * [FIX] Не загруженный java.awt.Robot. * [FIX] getRAM работает на OpenJDK 11+ * [FIX] Жуткий RequestAuthHandler. * [FIX] Грамматика английского языка в RequestAuthHandler. * [ANY] Опять RequestAuthHandler ошибки в грамматике. --- LaunchServer/build.gradle | 3 +- .../auth/handler/RequestAuthHandler.java | 109 +++++++---------- Launcher/build.gradle | 15 ++- .../ru/gravit/launcher/LauncherAgent.java | 110 ++++++++++++++++++ .../launcher/client/ClientLauncher.java | 2 +- build.gradle | 4 + .../ru/gravit/utils/helper/JVMHelper.java | 13 ++- 7 files changed, 184 insertions(+), 72 deletions(-) diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 503d2d56..3bae29c2 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -30,7 +30,8 @@ jar { dependsOn parent.childProjects.Launcher.tasks.build from { configurations.pack.collect { it.isDirectory() ? it : zipTree(it) } } - from(parent.childProjects.Launcher.tasks.jar.archivePath, parent.childProjects.Launcher.tasks.genRuntimeJS.archivePath) + from(parent.childProjects.Launcher.tasks.shadowJar.archivePath) + from(parent.childProjects.Launcher.tasks.genRuntimeJS.archivePath) manifest.attributes("Main-Class": mainClassName, "Premain-Class": mainAgentName, "Can-Redefine-Classes": "true", diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/RequestAuthHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/RequestAuthHandler.java index 1b705bfb..5b7a1152 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/RequestAuthHandler.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/RequestAuthHandler.java @@ -1,5 +1,6 @@ package ru.gravit.launchserver.auth.handler; +import ru.gravit.utils.helper.CommonHelper; import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.LogHelper; @@ -8,103 +9,81 @@ import java.util.UUID; public final class RequestAuthHandler extends CachedAuthHandler { - private String url; - private String secretKey; + private String usernameFetch; + private String uuidFetch; - private String typeLine; - private String uuidLine; - private String usernameLine; - private String accessTokenLine; - private String serverIDLine; - private String secretKeyLine; + private String updateAuth; + private String updateServerID; - private String TypeFetchByUUID; - private String TypeFetchByUsername; - private String TypeSetAccessTokenAndUUID; - private String TypeSetServerID; - private String splitSymbol; + private String splitSymbol = ":"; + private String goodResponse = "OK"; @Override public void init() { - if (url == null) - LogHelper.error("[Verify][AuthHandler] url cannot be null"); - if (secretKey == null) - LogHelper.error("[Verify][AuthHandler] secretKey cannot be null"); - // Default - if (typeLine == null) - typeLine = "type"; - if (uuidLine == null) - uuidLine = "uuid"; - if (usernameLine == null) - usernameLine = "username"; - if (accessTokenLine == null) - accessTokenLine = "accessToken"; - if (serverIDLine == null) - serverIDLine = "serverID"; - if (secretKeyLine == null) - secretKeyLine = "secretKey"; - if (TypeFetchByUUID == null) - TypeFetchByUUID = "FetchByUUID"; - if (TypeFetchByUsername == null) - TypeFetchByUsername = "FetchByUsername"; - if (TypeSetAccessTokenAndUUID == null) - TypeSetAccessTokenAndUUID = "SetAccessTokenAndUUID"; - if (TypeSetServerID == null) - TypeSetServerID = "SetServerID"; - if (splitSymbol == null) - splitSymbol = ":"; + if (usernameFetch == null) + LogHelper.error("[Verify][AuthHandler] usernameFetch cannot be null"); + if (uuidFetch == null) + LogHelper.error("[Verify][AuthHandler] uuidFetch cannot be null"); + if (updateAuth == null) + LogHelper.error("[Verify][AuthHandler] updateAuth cannot be null"); + if (updateServerID == null) + LogHelper.error("[Verify][AuthHandler] updateServerID cannot be null"); } @Override protected Entry fetchEntry(UUID uuid) throws IOException { - String response = IOHelper.request(new URL(url + "?" + IOHelper.urlEncode(typeLine) + "=" + TypeFetchByUUID + "&" + secretKeyLine + "=" + IOHelper.urlEncode(secretKey) + "&" + IOHelper.urlEncode(uuidLine) + "=" + IOHelper.urlEncode(uuid.toString()))); + String response = IOHelper.request(new URL(CommonHelper.replace(uuidFetch, "uuid", IOHelper.urlEncode(uuid.toString())))); String[] parts = response.split(splitSymbol); String username = parts[0]; String accessToken = parts[1]; String serverID = parts[2]; - LogHelper.debug("[AuthHandler] Getted username: " + username); - LogHelper.debug("[AuthHandler] Getted accessToken: " + accessToken); - LogHelper.debug("[AuthHandler] Getted serverID: " + serverID); - LogHelper.debug("[AuthHandler] Getted UUID: " + uuid); - return query(uuid, username, accessToken, serverID); + if (LogHelper.isDebugEnabled()) { + LogHelper.debug("[AuthHandler] Got username: " + username); + LogHelper.debug("[AuthHandler] Got accessToken: " + accessToken); + LogHelper.debug("[AuthHandler] Got serverID: " + serverID); + LogHelper.debug("[AuthHandler] Got UUID: " + uuid); + } + return new Entry(uuid, username, accessToken, serverID); } @Override protected Entry fetchEntry(String username) throws IOException { - String response = IOHelper.request(new URL(url + "?" + IOHelper.urlEncode(typeLine) + "=" + TypeFetchByUsername + "&" + secretKeyLine + "=" + IOHelper.urlEncode(secretKey) + "&" + IOHelper.urlEncode(usernameLine) + "=" + IOHelper.urlEncode(username))); + String response = IOHelper.request(new URL(CommonHelper.replace(usernameFetch, "user", IOHelper.urlEncode(username)))); String[] parts = response.split(splitSymbol); UUID uuid = UUID.fromString(parts[0]); String accessToken = parts[1]; String serverID = parts[2]; - LogHelper.debug("[AuthHandler] Getted username: " + username); - LogHelper.debug("[AuthHandler] Getted accessToken: " + accessToken); - LogHelper.debug("[AuthHandler] Getted serverID: " + serverID); - LogHelper.debug("[AuthHandler] Getted UUID: " + uuid); - return query(uuid, username, accessToken, serverID); - } - - private Entry query(UUID uuid, String username, String accessToken, String serverID) { + if (LogHelper.isDebugEnabled()) { + LogHelper.debug("[AuthHandler] Got username: " + username); + LogHelper.debug("[AuthHandler] Got accessToken: " + accessToken); + LogHelper.debug("[AuthHandler] Got serverID: " + serverID); + LogHelper.debug("[AuthHandler] Got UUID: " + uuid); + } return new Entry(uuid, username, accessToken, serverID); } @Override protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException { - String response = IOHelper.request(new URL(url + "?" + IOHelper.urlEncode(typeLine) + "=" + TypeSetAccessTokenAndUUID + "&" + secretKeyLine + "=" + IOHelper.urlEncode(secretKey) + "&" + IOHelper.urlEncode(uuidLine) + "=" + IOHelper.urlEncode(uuid.toString()) + "&" + IOHelper.urlEncode(accessTokenLine) + "=" + IOHelper.urlEncode(accessToken) + "&" + IOHelper.urlEncode(usernameLine) + "=" + IOHelper.urlEncode(username))); - LogHelper.debug("[AuthHandler] Set accessToken: " + accessToken); - LogHelper.debug("[AuthHandler] Set UUID: " + uuid); - LogHelper.debug("[AuthHandler] For this username: " + username); - return response.equals("OK"); + String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "user", IOHelper.urlEncode(username), "uuid", IOHelper.urlEncode(uuid.toString()), "token", IOHelper.urlEncode(accessToken)))); + if (LogHelper.isDebugEnabled()) { + LogHelper.debug("[AuthHandler] Set accessToken: " + accessToken); + LogHelper.debug("[AuthHandler] Set UUID: " + uuid); + LogHelper.debug("[AuthHandler] For this username: " + username); + } + return goodResponse.equals(response); } @Override protected boolean updateServerID(UUID uuid, String serverID) throws IOException { - String response = IOHelper.request(new URL(url + "?" + IOHelper.urlEncode(typeLine) + "=" + TypeSetServerID + "&" + secretKeyLine + "=" + IOHelper.urlEncode(secretKey) + "&" + IOHelper.urlEncode(uuidLine) + "=" + IOHelper.urlEncode(uuid.toString()) + "&" + IOHelper.urlEncode(serverIDLine) + "=" + IOHelper.urlEncode(serverID))); - LogHelper.debug("[AuthHandler] Set serverID: " + serverID); - LogHelper.debug("[AuthHandler] For this UUID: " + uuid); - return response.equals("OK"); + String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "serverid", IOHelper.urlEncode(serverID), "uuid", IOHelper.urlEncode(uuid.toString())))); + if (LogHelper.isDebugEnabled()) { + LogHelper.debug("[AuthHandler] Set serverID: " + serverID); + LogHelper.debug("[AuthHandler] For this UUID: " + uuid); + } + return goodResponse.equals(response); } @Override public void close() { } -} \ No newline at end of file +} diff --git a/Launcher/build.gradle b/Launcher/build.gradle index 37d84cdb..11fa5a06 100644 --- a/Launcher/build.gradle +++ b/Launcher/build.gradle @@ -1,3 +1,5 @@ +apply plugin: 'com.github.johnrengelman.shadow' + String mainClassName = "ru.gravit.launcher.ClientLauncherWrapper" String mainAgentName = "ru.gravit.launcher.LauncherAgent" @@ -17,7 +19,7 @@ } jar { - from { configurations.pack.collect { it.isDirectory() ? it : zipTree(it) } } + classifier = 'clean' manifest.attributes("Main-Class": mainClassName, "Premain-Class": mainAgentName, "Can-Redefine-Classes": "true", @@ -25,11 +27,18 @@ "Can-Set-Native-Method-Prefix": "true") } +shadowJar { + classifier = null + relocate 'org.objectweb.asm', 'ru.gravit.repackage.org.objectweb.asm' + configurations = [project.configurations.pack] + exclude 'module-info.class' +} + dependencies { pack project(':LauncherAPI') // Not error on obf. bundle 'com.github.oshi:oshi-core:3.13.0' - compileOnly 'org.ow2.asm:asm-all:5.0.3' bundle 'com.jfoenix:jfoenix:8.0.8' + pack 'org.ow2.asm:asm-tree:7.1' } task genRuntimeJS(type: Zip) { @@ -44,4 +53,4 @@ task dumpLibs(type: Copy) { } -build.dependsOn tasks.genRuntimeJS, tasks.dumpLibs +build.dependsOn tasks.genRuntimeJS, tasks.dumpLibs, tasks.shadowJar diff --git a/Launcher/src/main/java/ru/gravit/launcher/LauncherAgent.java b/Launcher/src/main/java/ru/gravit/launcher/LauncherAgent.java index 877f018f..6578562e 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/LauncherAgent.java +++ b/Launcher/src/main/java/ru/gravit/launcher/LauncherAgent.java @@ -43,9 +43,119 @@ public static void premain(String agentArgument, Instrumentation instrumentation if (trimmedArg.contains("r")) rt = false; } } + if (rt || pb) replaceClasses(pb, rt); } public static boolean isStarted() { return isAgentStarted; } + + /** + * @author https://github.com/Konloch/JVM-Sandbox + * Replaces the Runtime class via instrumentation, transforms the class via ASM + */ + private static void replaceClasses(boolean pb, boolean rt) { + java.awt.Robot.class.getName(); + for(Class c : inst.getAllLoadedClasses()) { + if(rt && c.getName().equals("java.lang.Runtime")) { + try { + inst.redefineClasses(new java.lang.instrument.ClassDefinition(java.lang.Runtime.class, transformClass(c.getName(), getClassFile(c)))); + } catch(Exception e) { + e.printStackTrace(); + } + } + if(pb && c.getName().equals("java.lang.ProcessBuilder")) { + try { + inst.redefineClasses(new java.lang.instrument.ClassDefinition(java.lang.ProcessBuilder.class, transformClass(c.getName(), getClassFile(c)))); + } catch(Exception e) { + e.printStackTrace(); + } + } + if(c.getName().equals("java.awt.Robot")) { + try { + inst.redefineClasses(new java.lang.instrument.ClassDefinition(java.lang.ProcessBuilder.class, transformClass(c.getName(), getClassFile(c)))); + } catch(Exception e) { + e.printStackTrace(); + } + } + } + } + + /** + * @author https://github.com/Konloch/JVM-Sandbox + * Use ASM to modify the byte array + */ + private static byte[] transformClass(String className, byte[] classBytes) { + if (className.equals("java.lang.Runtime")) { + ClassReader cr=new ClassReader(classBytes); + ClassNode cn=new ClassNode(); + cr.accept(cn,ClassReader.EXPAND_FRAMES); + + for (Object o : cn.methods.toArray()) { + MethodNode m = (MethodNode) o; + if(m.name.equals("exec")) { + m.instructions.insert(new InsnNode(ARETURN)); + m.instructions.insert(new InsnNode(ACONST_NULL)); + } + } + ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + return cw.toByteArray(); + } else if (className.equals("java.lang.ProcessBuilder")) { + ClassReader cr=new ClassReader(classBytes); + ClassNode cn=new ClassNode(); + cr.accept(cn,ClassReader.EXPAND_FRAMES); + + for (Object o : cn.methods.toArray()) { + MethodNode m = (MethodNode) o; + if(m.name.equals("start")) { + m.instructions.insert(new InsnNode(ARETURN)); + m.instructions.insert(new InsnNode(ACONST_NULL)); + } + } + ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + return cw.toByteArray(); + } else if (className.equals("java.awt.Robot")) { + ClassReader cr=new ClassReader(classBytes); + ClassNode cn=new ClassNode(); + cr.accept(cn,ClassReader.EXPAND_FRAMES); + + for (Object o : cn.methods.toArray()) { + MethodNode m = (MethodNode) o; + if( m.name.equals("createScreenCapture") || m.name.equals("getPixelColor") || + m.name.equals("keyPress") || m.name.equals("keyRelease") || + m.name.equals("mouseMove") || m.name.equals("mousePress") || + m.name.equals("mouseWheel")) + { + m.instructions.insert(new InsnNode(ARETURN)); + m.instructions.insert(new InsnNode(ACONST_NULL)); + } + } + ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + return cw.toByteArray(); + } + return classBytes; + } + + /** + * @author https://github.com/Konloch/JVM-Sandbox + * Do not remove this method. Do not to cause classloading! + * Grab the byte array from the loaded Class object + * @param clazz + * @return array, respending this class in bytecode. + * @throws IOException + */ + private static byte[] getClassFile(Class clazz) throws IOException { + try (InputStream is = clazz.getResourceAsStream( "/" + clazz.getName().replace('.', '/') + ".class"); + ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + int r = 0; + byte[] buffer = new byte[8192]; + while((r=is.read(buffer))>=0) { + baos.write(buffer, 0, r); + } + return baos.toByteArray(); + } + } } 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 f83de1c2..d62ae452 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java +++ b/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java @@ -355,7 +355,7 @@ public static Process launch( Collections.addAll(context.args, profile.getJvmArgs()); profile.pushOptionalJvmArgs(context.args); Collections.addAll(context.args, "-Djava.library.path=".concat(params.clientDir.resolve(NATIVES_DIR).toString())); // Add Native Path - Collections.addAll(context.args, "-javaagent:".concat(pathLauncher).concat("=pr")); + Collections.addAll(context.args, "-javaagent:".concat(pathLauncher)); LauncherGuardManager.guard.addCustomParams(context); Collections.addAll(context.args, ClientLauncher.class.getName()); diff --git a/build.gradle b/build.gradle index 02d6daae..c2439fbf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,7 @@ +plugins { + id 'com.github.johnrengelman.shadow' version '5.0.0' apply false +} + configure(subprojects.findAll { it.name != 'modules' && it.name != 'Radon' }) { apply plugin: 'idea' apply plugin: 'eclipse' diff --git a/libLauncher/src/main/java/ru/gravit/utils/helper/JVMHelper.java b/libLauncher/src/main/java/ru/gravit/utils/helper/JVMHelper.java index ecbb33d7..e4e2510b 100644 --- a/libLauncher/src/main/java/ru/gravit/utils/helper/JVMHelper.java +++ b/libLauncher/src/main/java/ru/gravit/utils/helper/JVMHelper.java @@ -7,6 +7,8 @@ import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; @@ -136,8 +138,15 @@ public static String getEnvPropertyCaseSensitive(String name) { } private static int getRAMAmount() { - // TODO Normal fix. - int physicalRam = (int) (((com.sun.management.OperatingSystemMXBean) OPERATING_SYSTEM_MXBEAN).getTotalPhysicalMemorySize() >> 20); + int physicalRam = 1024; + try { + final Method getTotalPhysicalMemorySize = OPERATING_SYSTEM_MXBEAN.getClass().getDeclaredMethod("getTotalPhysicalMemorySize"); + getTotalPhysicalMemorySize.setAccessible(true); + physicalRam = (int) ((long)getTotalPhysicalMemorySize.invoke(OPERATING_SYSTEM_MXBEAN) >> 20); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException + | SecurityException e) { + throw new Error(e); + } return Math.min(physicalRam, OS_BITS == 32 ? 1536 : 32768); // Limit 32-bit OS to 1536 MiB, and 64-bit OS to 32768 MiB (because it's enough) }