diff --git a/noname/util/sandbox.js b/noname/util/sandbox.js index a0c66c97d..ae00c0fcb 100644 --- a/noname/util/sandbox.js +++ b/noname/util/sandbox.js @@ -3,7 +3,7 @@ const FILE_URL = import.meta.url; /** @typedef {any} Window */ // 方便开关确定沙盒的问题喵 -const SANDBOX_ENABLED = false; +const SANDBOX_ENABLED = true; // 暴露方法Symbol,用于类之间通信 const SandboxExposer = Symbol("Sandbox.Exposer"); // 实例暴露 @@ -3269,15 +3269,16 @@ class Sandbox { const executingScope = Sandbox.#executingScope[Sandbox.#executingScope.length - 1]; const scope = inheritScope && executingScope || thiz.#scope; - const contextName = Sandbox.#makeName("__context_", scope); - const argsName = Sandbox.#makeName("__args_", scope); + const contextName = Sandbox.#makeName("_", scope); + const argsName = Sandbox.#makeName("_", scope); + const applyName = Sandbox.#makeName("_", scope); const parameters = paramList ? paramList.join(", ") : ""; const writeContextAction = { exists: 0, extend: 1, all: 2 }[writeContext] || 0; let argumentList; - const raw = new thiz.#domainFunction("_", `with(_){with(window){with(${contextName}){return(()=>{"use strict";return(function(${parameters}){\n// 沙盒代码起始\n${code}\n// 沙盒代码结束\n}).call(${contextName}.this,...${argsName})})()}}}`); + const raw = new thiz.#domainFunction("_", `with(_){with(window){with(${contextName}){return(()=>{"use strict";return(${applyName}(function(${parameters}){\n// 沙盒代码起始\n${code}\n// 沙盒代码结束\n},${contextName}.this,${argsName}))})()}}}`); const domain = thiz.#domain; const domainWindow = thiz.#domainWindow; @@ -3295,6 +3296,8 @@ class Sandbox { return marshalledContext; case argsName: return argumentList; + case applyName: + return Reflect.apply; } // 防止逃逸 diff --git a/noname/util/security.js b/noname/util/security.js index 1dcf660a2..79c71b02e 100644 --- a/noname/util/security.js +++ b/noname/util/security.js @@ -1,7 +1,12 @@ import { Sandbox, Domain, Marshal, Monitor, AccessAction, Rule, SANDBOX_ENABLED } from "./sandbox.js"; // 是否强制所有模式下使用沙盒 -const SANDBOX_FORCED = false; +const SANDBOX_FORCED = true; +// 是否启用自动测试 +const SANDBOX_AUTOTEST = true; +// 是否禁用自动测试延迟 +// 这将放弃渲染,在游戏结束前无响应 +const SANDBOX_AUTOTEST_NODELAY = false; const TRUSTED_IPS = Object.freeze([ "47.99.105.222", @@ -289,8 +294,6 @@ function initSecurity({ }) { if (initialized) throw "security 已经被初始化过了"; - if (!SANDBOX_ENABLED) - return; topVariables.lib = lib; topVariables.game = game; @@ -300,6 +303,9 @@ function initSecurity({ topVariables._status = _status; topVariables.gnc = gnc; + if (!SANDBOX_ENABLED) + return; + loadPolyfills(); // @ts-ignore @@ -332,6 +338,14 @@ function initSecurity({ ...Object.values(game.promises), defaultEval, window.require, + window.process, + window.module, + window.exports, + window.cordova, + // @ts-ignore + window.NonameAndroidBridge, + // @ts-ignore + window.noname_shijianInterfaces, window, ]; @@ -399,6 +413,44 @@ function initSecurity({ // }) // .start(); + if (SANDBOX_AUTOTEST) { + // 一个测试循环喵 + if (SANDBOX_AUTOTEST_NODELAY) { + game.resume = () => { }; + game.pause = () => { }; + } + game.delay = game.delayx = () => { }; + game.asyncDelay = game.asyncDelayx = async () => { }; + + Reflect.defineProperty(lib.element.GameEvent.prototype, "animate", { + get: () => undefined, + set() { }, + enumerable: false, + configurable: false, + }); + + if (!lib.videos) + lib.videos = []; + + game.over = function (...args) { + if (_status.over) return; + _status.over = true; + setTimeout(() => { + if (!_status.auto) + return; + + const count = parseInt(localStorage.getItem("__sandboxTestCount") || "0"); + localStorage.setItem("__sandboxTestCount", String(count + 1)); + + localStorage.setItem( + lib.configprefix + "directstart", "true"); + game.reload(); + }, SANDBOX_AUTOTEST_NODELAY ? 5000 : 1000); + }; + + lib.arenaReady.push(() => ui.click.auto()); + } + initialized = true; } @@ -464,17 +516,30 @@ function getIsolateds(sandbox) { * ``` */ function loadPolyfills() { + function isNativeDescriptor(descriptor) { + if (typeof descriptor.value == "function" + && !nativePattern.test(descriptor.value.toString())) + return false; + if (typeof descriptor.get == "function" + && !nativePattern.test(descriptor.get.toString())) + return false; + if (typeof descriptor.set == "function" + && !nativePattern.test(descriptor.set.toString())) + return false; + + return true; + } + function copyDescriptors(top, box) { for (const key of Reflect.ownKeys(top)) { const descriptor = Reflect.getOwnPropertyDescriptor(top, key); if (!descriptor - || typeof descriptor.value !== "function") + || (typeof descriptor.value !== "function" + && !descriptor.get && !descriptor.set)) continue; - const body = descriptor.value.toString(); - - if (nativePattern.test(body)) + if (isNativeDescriptor(descriptor)) continue; box[key] = descriptor;