From 82df3d0c46711e574b37d5dd3f60b70449b8d2e5 Mon Sep 17 00:00:00 2001 From: LAX1DUDE Date: Sun, 17 Jul 2022 23:48:26 -0700 Subject: [PATCH] added more client protection --- .../lax1dude/eaglercraft/EaglerProfile.java | 4 - .../java/net/lax1dude/eaglercraft/Client.java | 71 +++++++++----- .../adapter/EaglerAdapterImpl2.java | 79 ++++++++-------- .../adapter/teavm/SelfDefence.java | 94 +++++++++++++++++++ 4 files changed, 181 insertions(+), 67 deletions(-) create mode 100644 src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/SelfDefence.java diff --git a/src/main/java/net/lax1dude/eaglercraft/EaglerProfile.java b/src/main/java/net/lax1dude/eaglercraft/EaglerProfile.java index e0b274f..4985a05 100644 --- a/src/main/java/net/lax1dude/eaglercraft/EaglerProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/EaglerProfile.java @@ -40,8 +40,6 @@ public class EaglerProfile { public static int customCapeId; public static int newSkinNotificationIndex = 0; - - public static String myChannel; public static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, -9, -9, 1, 64*64*4, -9 }; public static final int[] CAPE_DATA_SIZE = new int[] { 32*32*4, -9, 1 }; @@ -219,7 +217,6 @@ public class EaglerProfile { }while(username.length() > 16); presetSkinId = rand.nextInt(GuiScreenEditProfile.defaultOptions.length); - myChannel = username + "_" + (100 + rand.nextInt(900)); customSkinId = -1; } @@ -234,7 +231,6 @@ public class EaglerProfile { if(newSkinNotificationIndex == 0) { newSkinNotificationIndex = GuiScreenEditProfile.newDefaultNotice; } - myChannel = username + "_" + (100 + rand.nextInt(900)); NBTTagCompound n = LocalStorageManager.profileSettingsStorage.getCompoundTag("skins"); for(Object s : NBTTagCompound.getTagMap(n).keySet()) { String s2 = (String)s; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/Client.java b/src/teavm/java/net/lax1dude/eaglercraft/Client.java index 80714be..94edc2e 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/Client.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/Client.java @@ -95,39 +95,37 @@ public class Client { str.append("eaglercraft.minecraft = \"1.5.2\"\n"); str.append("eaglercraft.brand = \"eagtek\"\n"); str.append("eaglercraft.username = \"").append(EaglerProfile.username).append("\"\n"); - str.append("eaglercraft.channel = \"").append(EaglerProfile.myChannel).append("\"\n"); str.append('\n'); shortenMinecraftOpts(); - addArray(str, "window.minecraftOpts"); + addArray(str, "minecraftOpts"); str.append('\n'); - addDebug(str, "window.navigator.userAgent"); - addDebug(str, "window.navigator.vendor"); - addDebug(str, "window.navigator.language"); - addDebug(str, "window.navigator.hardwareConcurrency"); - addDebug(str, "window.navigator.deviceMemory"); - addDebug(str, "window.navigator.platform"); - addDebug(str, "window.navigator.product"); + addDebugNav(str, "userAgent"); + addDebugNav(str, "vendor"); + addDebugNav(str, "language"); + addDebugNav(str, "hardwareConcurrency"); + addDebugNav(str, "deviceMemory"); + addDebugNav(str, "platform"); + addDebugNav(str, "product"); str.append('\n'); str.append("rootElement.clientWidth = ").append(rootElement.getClientWidth()).append('\n'); str.append("rootElement.clientHeight = ").append(rootElement.getClientHeight()).append('\n'); - addDebug(str, "window.innerWidth"); - addDebug(str, "window.innerHeight"); - addDebug(str, "window.outerWidth"); - addDebug(str, "window.outerHeight"); - addDebug(str, "window.devicePixelRatio"); - addDebug(str, "window.screen.availWidth"); - addDebug(str, "window.screen.availHeight"); - addDebug(str, "window.screen.colorDepth"); - addDebug(str, "window.screen.pixelDepth"); + addDebug(str, "innerWidth"); + addDebug(str, "innerHeight"); + addDebug(str, "outerWidth"); + addDebug(str, "outerHeight"); + addDebug(str, "devicePixelRatio"); + addDebugScreen(str, "availWidth"); + addDebugScreen(str, "availHeight"); + addDebugScreen(str, "colorDepth"); + addDebugScreen(str, "pixelDepth"); str.append('\n'); - addDebug(str, "window.currentContext"); + addDebug(str, "currentContext"); str.append('\n'); - addDebug(str, "window.location.href"); - addArray(str, "window.location.ancestorOrigins"); + addDebugLocation(str, "href"); str.append("\n----- Begin Minecraft Config -----\n"); str.append(LocalStorageManager.dumpConfiguration()); str.append("\n----- End Minecraft Config -----\n\n"); - addDebug(str, "window.minecraftServer"); + addDebug(str, "minecraftServer"); String s = rootElement.getAttribute("style"); rootElement.setAttribute("style", (s == null ? "" : s) + "position:relative;"); @@ -144,21 +142,42 @@ public class Client { } } - @JSBody(params = { "v" }, script = "try { return \"\"+window.eval(v); } catch(e) { return \"\"; }") + @JSBody(params = { "v" }, script = "try { return \"\"+window[v]; } catch(e) { return \"\"; }") private static native String getString(String var); + @JSBody(params = { "v" }, script = "try { return \"\"+window.navigator[v]; } catch(e) { return \"\"; }") + private static native String getStringNav(String var); + + @JSBody(params = { "v" }, script = "try { return \"\"+window.screen[v]; } catch(e) { return \"\"; }") + private static native String getStringScreen(String var); + + @JSBody(params = { "v" }, script = "try { return \"\"+window.location[v]; } catch(e) { return \"\"; }") + private static native String getStringLocation(String var); + @JSBody(params = { }, script = "for(var i = 0; i < window.minecraftOpts.length; ++i) { if(window.minecraftOpts[i].length > 2048) window.minecraftOpts[i] = \"[\" + Math.floor(window.minecraftOpts[i].length * 0.001) + \"k characters]\"; }") private static native void shortenMinecraftOpts(); private static void addDebug(StringBuilder str, String var) { - str.append(var).append(" = ").append(getString(var)).append('\n'); + str.append("window.").append(var).append(" = ").append(getString(var)).append('\n'); + } + + private static void addDebugNav(StringBuilder str, String var) { + str.append("window.navigator.").append(var).append(" = ").append(getStringNav(var)).append('\n'); + } + + private static void addDebugScreen(StringBuilder str, String var) { + str.append("window.screen.").append(var).append(" = ").append(getStringScreen(var)).append('\n'); + } + + private static void addDebugLocation(StringBuilder str, String var) { + str.append("window.location.").append(var).append(" = ").append(getStringLocation(var)).append('\n'); } private static void addArray(StringBuilder str, String var) { - str.append(var).append(" = ").append(getArray(var)).append('\n'); + str.append("window.").append(var).append(" = ").append(getArray(var)).append('\n'); } - @JSBody(params = { "v" }, script = "try { return JSON.stringify(window.eval(v)); } catch(e) { return \"[\\\"\\\"]\"; }") + @JSBody(params = { "v" }, script = "try { return (typeof window[v] !== \"undefined\") ? JSON.stringify(window[v]) : \"[\\\"\\\"]\"; } catch(e) { return \"[\\\"\\\"]\"; }") private static native String getArray(String var); } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java index 839a2ff..eaba5a6 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java @@ -60,6 +60,7 @@ import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery; import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray; import net.minecraft.src.MathHelper; import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftVoiceClient; +import net.lax1dude.eaglercraft.adapter.teavm.SelfDefence; import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext; import static net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext.*; @@ -136,9 +137,6 @@ public class EaglerAdapterImpl2 { }); request.send(); } - - @JSBody(params = { "obj" }, script = "window.currentContext = obj;") - private static native int setContextVar(JSObject obj); @JSBody(params = { "v", "s" }, script = "window[v] = s;") public static native void setDebugVar(String v, String s); @@ -168,8 +166,8 @@ public class EaglerAdapterImpl2 { return identifier; } - @JSBody(params = { "v" }, script = "try { return \"\"+window.eval(v); } catch(e) { return \"\"; }") - private static native String getString(String var); + @JSBody(params = { "v" }, script = "try { return \"\"+window.navigator[v]; } catch(e) { return \"\"; }") + private static native String getNavString(String var); public static void onWindowUnload() { LocalStorageManager.saveStorageA(); @@ -193,9 +191,9 @@ public class EaglerAdapterImpl2 { win = Window.current(); doc = win.getDocument(); canvas = (HTMLCanvasElement)doc.createElement("canvas"); - canvas.setAttribute("id", "deevis589723589"); canvas.setWidth(parent.getClientWidth()); canvas.setHeight(parent.getClientHeight()); + SelfDefence.init(canvas); rootElement.appendChild(canvas); renderingCanvas = (HTMLCanvasElement)doc.createElement("canvas"); renderingCanvas.setWidth(canvas.getWidth()); @@ -203,9 +201,8 @@ public class EaglerAdapterImpl2 { frameBuffer = (CanvasRenderingContext2D) canvas.getContext("2d"); webgl = (WebGL2RenderingContext) renderingCanvas.getContext("webgl2", youEagler()); if(webgl == null) { - throw new RuntimeException("WebGL 2.0 is not supported in your browser ("+getString("window.navigator.userAgent")+")"); + throw new RuntimeException("WebGL 2.0 is not supported in your browser ("+getNavString("userAgent")+")"); } - setContextVar(webgl); //String agent = getString("window.navigator.userAgent").toLowerCase(); //if(agent.contains("windows")) isAnisotropicPatched = false; @@ -302,31 +299,7 @@ public class EaglerAdapterImpl2 { } }); onBeforeCloseRegister(); - execute("window.eagsFileChooser = {\r\n" + - "inputElement: null,\r\n" + - "openFileChooser: function(ext, mime){\r\n" + - "el = window.eagsFileChooser.inputElement = document.createElement(\"input\");\r\n" + - "el.type = \"file\";\r\n" + - "el.multiple = false;\r\n" + - "el.addEventListener(\"change\", function(evt){\r\n" + - "var f = window.eagsFileChooser.inputElement.files;\r\n" + - "if(f.length == 0){\r\n" + - "window.eagsFileChooser.getFileChooserResult = null;\r\n" + - "}else{\r\n" + - "(async function(){\r\n" + - "window.eagsFileChooser.getFileChooserResult = await f[0].arrayBuffer();\r\n" + - "window.eagsFileChooser.getFileChooserResultName = f[0].name;\r\n" + - "})();\r\n" + - "}\r\n" + - "});\r\n" + - "window.eagsFileChooser.getFileChooserResult = null;\r\n" + - "window.eagsFileChooser.getFileChooserResultName = null;\r\n" + - "el.accept = mime;\r\n" + - "el.click();\r\n" + - "},\r\n" + - "getFileChooserResult: null,\r\n" + - "getFileChooserResultName: null\r\n" + - "};"); + initFileChooser(); EarlyLoadScreen.paintScreen(); @@ -375,6 +348,34 @@ public class EaglerAdapterImpl2 { @JSBody(params = { }, script = "return window.startVoiceClient();") private static native EaglercraftVoiceClient startVoiceClient(); + @JSBody(params = { }, script = + "window.eagsFileChooser = {\r\n" + + "inputElement: null,\r\n" + + "openFileChooser: function(ext, mime){\r\n" + + "var el = window.eagsFileChooser.inputElement = document.createElement(\"input\");\r\n" + + "el.type = \"file\";\r\n" + + "el.multiple = false;\r\n" + + "el.addEventListener(\"change\", function(evt){\r\n" + + "var f = window.eagsFileChooser.inputElement.files;\r\n" + + "if(f.length == 0){\r\n" + + "window.eagsFileChooser.getFileChooserResult = null;\r\n" + + "}else{\r\n" + + "(async function(){\r\n" + + "window.eagsFileChooser.getFileChooserResult = await f[0].arrayBuffer();\r\n" + + "window.eagsFileChooser.getFileChooserResultName = f[0].name;\r\n" + + "})();\r\n" + + "}\r\n" + + "});\r\n" + + "window.eagsFileChooser.getFileChooserResult = null;\r\n" + + "window.eagsFileChooser.getFileChooserResultName = null;\r\n" + + "el.accept = mime;\r\n" + + "el.click();\r\n" + + "},\r\n" + + "getFileChooserResult: null,\r\n" + + "getFileChooserResultName: null\r\n" + + "};") + private static native void initFileChooser(); + public static final void destroyContext() { } @@ -388,6 +389,13 @@ public class EaglerAdapterImpl2 { win.removeEventListener("keyup", keyup); win.removeEventListener("keypress", keypress); win.removeEventListener("wheel", wheel); + String screenImg = canvas.toDataURL("image/png"); + canvas.delete(); + HTMLImageElement newImage = (HTMLImageElement) doc.createElement("img"); + newImage.setSrc(screenImg); + newImage.setWidth(parent.getClientWidth()); + newImage.setHeight(parent.getClientHeight()); + parent.appendChild(newImage); } private static LinkedList mouseEvents = new LinkedList(); @@ -891,7 +899,7 @@ public class EaglerAdapterImpl2 { return __wglGetTexParameterf(webgl, p1); } public static final boolean isWindows() { - return getString("window.navigator.platform").toLowerCase().contains("win"); + return getNavString("platform").toLowerCase().contains("win"); } private static HTMLCanvasElement imageLoadCanvas = null; @@ -1803,9 +1811,6 @@ public class EaglerAdapterImpl2 { public static final void redirectTo(String url) { Window.current().getLocation().setFullURL(url); } - - @JSBody(params = { "str" }, script = "window.eval(str);") - private static native void execute(String str); @JSBody(params = { }, script = "window.onbeforeunload = function(){javaMethods.get('net.lax1dude.eaglercraft.adapter.EaglerAdapterImpl2.onWindowUnload()V').invoke();return false;};") private static native void onBeforeCloseRegister(); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/SelfDefence.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/SelfDefence.java new file mode 100644 index 0000000..950d30a --- /dev/null +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/SelfDefence.java @@ -0,0 +1,94 @@ +package net.lax1dude.eaglercraft.adapter.teavm; + +import java.util.ArrayList; +import java.util.List; + +import org.teavm.jso.JSBody; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; +import org.teavm.jso.browser.TimerHandler; +import org.teavm.jso.browser.Window; +import org.teavm.jso.core.JSArrayReader; +import org.teavm.jso.dom.html.HTMLCanvasElement; +import org.teavm.jso.dom.html.HTMLDocument; +import org.teavm.jso.dom.html.HTMLIFrameElement; +import org.teavm.jso.dom.xml.Element; +import org.teavm.jso.dom.xml.NodeList; + +public class SelfDefence { + + private static HTMLCanvasElement canvas = null; + + @JSFunctor + private static interface NewWindowCallback extends JSObject { + void call(Window newWindow); + } + + @JSBody(params = { "cb" }, script = "const ccb = cb; const _open = window.open; window.open = (url,name,params) => { var rw = _open(url,name,params); ccb(rw); return rw; }") + private static native void injectWindowCapture(NewWindowCallback callback); + + private static final List capturedChildWindows = new ArrayList(); + + public static void init(HTMLCanvasElement legitCanvas) { + canvas = legitCanvas; + for(int i = 0; i < 15; ++i) { + Window.setTimeout(new TimerHandler() { + + @Override + public void onTimer() { + Window.setTimeout(this, (long)(Math.random() * 25000l)); + run(Window.current()); + for(int i = 0, l = capturedChildWindows.size(); i < l; ++i) { + run(capturedChildWindows.get(i)); + } + } + + }, (long)(Math.random() * 25000l)); + } + injectWindowCapture(new NewWindowCallback() { + @Override + public void call(Window newWindow) { + capturedChildWindows.add(newWindow); + } + }); + } + + private static void run(Window win) { + try { + run0(win); + }catch(Throwable t) { + } + } + + private static void run0(Window win) { + run(win.getDocument()); + JSArrayReader frms = win.getFrames(); + for(int i = 0, l = frms.getLength(); i < l; ++i) { + HTMLIFrameElement frm = frms.get(i); + if(checkFrame(frm)) { + run(frm.getContentWindow()); + } + } + } + + @JSBody(params = { "frm" }, script = "try { var g = frm.contentWindow; g[\"fuck_off\"] = \"dick\"; return g[\"fuck_off\"] === \"dick\"; } catch (e) { return false; }") + private static native boolean checkFrame(HTMLIFrameElement frame); + + private static void run(HTMLDocument doc) { + try { + run0(doc); + }catch(Throwable t) { + } + } + + private static void run0(HTMLDocument doc) { + NodeList els = doc.getElementsByTagName("canvas"); + for(int i = 0, l = els.getLength(); i < l; ++i) { + HTMLCanvasElement canv = (HTMLCanvasElement) els.get(i); + if(canvas != canv) { + canv.delete(); + } + } + } + +}