浏览器功能包

修改浏览器的一些配置,使脚本可以作弊

当前为 2022-10-19 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         浏览器功能包
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  修改浏览器的一些配置,使脚本可以作弊
// @author       Tenfond
// @match        *://*/*
// @grant        none
// @license      AGPL-3.0
// @run-at       document-start
// ==/UserScript==

(function () {
    // event 可信任事件
    (function () {
        function tamper(event) {
            return {
                "isTrusted": true,
                get altitudeAngle() {
                    return event["altitudeAngle"];
                },
                get azimuthAngle() {
                    return event["azimuthAngle"];
                },
                "getCoalescedEvents": function getCoalescedEvents() {
                    return event["getCoalescedEvents"].apply(event, arguments);
                },
                "getPredictedEvents": function getPredictedEvents() {
                    return event["getPredictedEvents"].apply(event, arguments);
                },
                get height() {
                    return event["height"];
                },
                get isPrimary() {
                    return event["isPrimary"];
                },
                get pointerId() {
                    return event["pointerId"];
                },
                get pointerType() {
                    return event["pointerType"];
                },
                get pressure() {
                    return event["pressure"];
                },
                get tangentialPressure() {
                    return event["tangentialPressure"];
                },
                get tiltX() {
                    return event["tiltX"];
                },
                get tiltY() {
                    return event["tiltY"];
                },
                get twist() {
                    return event["twist"];
                },
                get width() {
                    return event["width"];
                },
                "constructor": event["constructor"],
                "__proto__": event["__proto__"],
                get altKey() {
                    return event["altKey"];
                },
                get bubbles() {
                    return event["bubbles"];
                },
                get button() {
                    return event["button"];
                },
                get buttons() {
                    return event["buttons"];
                },
                get cancelBubble() {
                    return event["cancelBubble"];
                },
                get cancelable() {
                    return event["cancelable"];
                },
                get clientX() {
                    return event["clientX"];
                },
                get clientY() {
                    return event["clientY"];
                },
                get composed() {
                    return event["composed"];
                },
                get ctrlKey() {
                    return event["ctrlKey"];
                },
                get currentTarget() {
                    return event["currentTarget"];
                },
                get defaultPrevented() {
                    return event["defaultPrevented"];
                },
                get detail() {
                    return event["detail"];
                },
                get eventPhase() {
                    return event["eventPhase"];
                },
                get fromElement() {
                    return event["fromElement"];
                },
                get layerX() {
                    return event["layerX"];
                },
                get layerY() {
                    return event["layerY"];
                },
                get metaKey() {
                    return event["metaKey"];
                },
                get movementX() {
                    return event["movementX"];
                },
                get movementY() {
                    return event["movementY"];
                },
                get offsetX() {
                    return event["offsetX"];
                },
                get offsetY() {
                    return event["offsetY"];
                },
                get pageX() {
                    return event["pageX"];
                },
                get pageY() {
                    return event["pageY"];
                },
                get path() {
                    return event["path"];
                },
                get relatedTarget() {
                    return event["relatedTarget"];
                },
                get returnValue() {
                    return event["returnValue"];
                },
                get screenX() {
                    return event["screenX"];
                },
                get screenY() {
                    return event["screenY"];
                },
                get shiftKey() {
                    return event["shiftKey"];
                },
                get sourceCapabilities() {
                    return event["sourceCapabilities"]
                },
                get srcElement() {
                    return event["srcElement"];
                },
                get target() {
                    return event["target"];
                },
                get timeStamp() {
                    return event["timeStamp"];
                },
                get toElement() {
                    return event["toElement"];
                },
                get type() {
                    return event["type"];
                },
                get view() {
                    return event["view"];
                },
                get which() {
                    return event["which"];
                },
                get x() {
                    return event["x"];
                },
                get y() {
                    return event["y"];
                },
                "composedPath": function composedPath() {
                    return event["composedPath"].apply(event, arguments);
                },
                "preventDefault": function preventDefault() {
                    return event["preventDefault"].apply(event, arguments);
                },
                "stopImmediatePropagation": function stopImmediatePropagation() {
                    return event["stopImmediatePropagation"].apply(event, arguments);
                },
                "stopPropagation": function stopPropagation() {
                    return event["stopPropagation"].apply(event, arguments);
                }
            };
        }

        try {
            const addEventListener = EventTarget.prototype.addEventListener;
            Object.defineProperty(EventTarget.prototype, "addEventListener", {
                value: function (type, callback, options = false) {
                    return addEventListener.apply(this, [type, type === "click" ? function () {
                        if (arguments.length > 0 && arguments[0].constructor.name === "PointerEvent")
                            arguments[0] = tamper(arguments[0]);
                        return callback.apply(this, arguments);
                    } : callback, options]);
                },
                writable: false,
                enumerable: true,
                configurable: false
            });
        } catch (e) {
            console.error(e.message);
        }
    })();

    // 定义 location.hashCode 获取 href的hash值
    (function () {
        try {
            Object.defineProperty(location, "hashCode", {
                enumerable: true,
                configurable: false,
                get: function () {
                    let code = 0;
                    for (const v of location.href) {
                        code += (code << 7) + v.charCodeAt(0);
                    }
                    // 返回值在 JavaScript 中的取值范围 [-2147483648,4294967294]
                    return code;
                }
            });
        } catch (e) {
            console.error(e.message);
        }
        let hashCode = location.hashCode, onchange = null;
        try {
            Object.defineProperty(location, "onchange", {
                enumerable: true,
                configurable: false,
                get: function () {
                    return onchange;
                },
                set: function (handler) {
                    if (typeof handler === "function" || Boolean(handler) === false) {
                        onchange = handler;
                    } else {
                        console.error("Uncaught (in onchange) TypeError: " + handler + " is not a function.")
                    }
                }
            });
            setInterval(function () {
                if (hashCode !== location.hashCode) {
                    hashCode = location.hashCode;
                    if (typeof onchange === "function") onchange();
                }
            }, 500);
        } catch (e) {
            console.error(e.message);
        }
    })();

    window.searchToJSON = function searchToJSON(search) {
        if (search) {
            return JSON.parse("{\"" + decodeURIComponent(search.substring(1)
                .replace(new RegExp("\"", "g"), '\\"')
                .replace(new RegExp("&", "g"), '","')
                .replace(new RegExp("=", "g"), '":"')) + "\"}");
        } else {
            return null;
        }
    }

    window.hrefToLocation = function hrefToLocation(href) {
        let location = {href: href}, c = 0, start = 0, port, search;
        for (let i = 0; i < href.length; i++) {
            if (href[i] === "/") {
                if (++c === 1) {
                    location.protocol = href.substring(start, i);
                } else if (c === 3) {
                    location.host = href.substring(start, i);
                    location.origin = href.substring(0, i);
                    if (port) {
                        location.port = href.substring(port, i);
                    } else {
                        location.hostname = location.host;
                        location.port = "";
                    }
                }
                if (c <= 3) {
                    start = i + 1;
                }
            } else if (href[i] === ":" && c === 2) {
                location.hostname = href.substring(start + 1, i);
                port = i + 1;
            } else if (href[i] === "?" && !search) {
                location.pathname = href.substring(start - 1, i);
                search = i;
            } else if (href[i] === "#" && !location.hash) {
                location.hash = href.substring(i);
                if (search) {
                    location.search = href.substring(search, i);
                } else {
                    location.search = "";
                    location.pathname = href.substring(start - 1, i);
                }
                break;
            }
        }
        if (typeof location.host === "undefined") {
            if (c < 2) {
                location.host = location.hostname = location.port = location.origin = "";
            } else if (c === 2) {
                location.host = href.substring(start);
                location.origin = href;
                if (typeof location.hostname === "undefined") {
                    location.hostname = location.host;
                    location.port = "";
                } else {
                    location.port = href.substring(port);
                }
            }
            location.pathname = location.hash = "";
        } else if (typeof location.pathname === "undefined") {
            location.pathname = href.substring(start - 1);
            location.search = location.hash = "";
        } else if (typeof location.search === "undefined") {
            if (search) {
                location.search = href.substring(search);
            } else {
                location.search = "";
            }
            location.hash = "";
        } else if (typeof location.hash === "undefined") {
            location.hash = "";
        }
        return location;
    }

    window.xmlHttpRequest = function xmlHttpRequest(handler = {}) {
        function xhrToArgs(xhr) {
            if (xhr.constructor.name === "XMLHttpRequest") return {
                // "onabort": xhr["onabort"],
                // "onerror": xhr["onerror"],
                // "onload": xhr["onload"],
                // "onloadend": xhr["onloadend"],
                // "onloadstart": xhr["onloadstart"],
                // "onprogress": xhr["onprogress"],
                // "onreadystatechange": xhr["onreadystatechange"],
                // "ontimeout": xhr["ontimeout"],
                "abort": function () {
                    return xhr["abort"]();
                },
                "finalUrl": xhr["responseURL"],
                "responseHeaders": (function () {
                    const headers = {};
                    xhr["getAllResponseHeaders"]().split("\r\n").forEach(function (header) {
                        header = header.split(": ");
                        headers[header[0]] = header[1];
                    });
                    return headers;
                })(),
                "getResponseHeader": function (name) {
                    return xhr["getResponseHeader"](name);
                },
                "overrideMimeType": function (mime) {
                    return xhr["overrideMimeType"](mime);
                },
                "responseType": xhr["responseType"],
                "response": xhr["response"],
                "responseText": (function () {
                    try {
                        return xhr["responseText"];
                    } catch (e) {
                        console.error(e.message);
                        return e;
                    }
                })(),
                "responseXML": (function () {
                    try {
                        return xhr["responseXML"];
                    } catch (e) {
                        console.error(e.message);
                        return e;
                    }
                })(),
                "readyState": xhr["readyState"],
                "status": xhr["status"],
                "statusText": xhr["statusText"],
                "timeout": xhr["timeout"],
                // "upload": xhr["upload"],
                // "withCredentials": xhr["withCredentials"]
            }; else return xhr.constructor.name;
        }

        if (typeof handler === "string") handler = {url: handler};
        const request = new XMLHttpRequest();
        if (handler.onreadystatechange) request.onreadystatechange = function (event) {
            return handler.onreadystatechange(xhrToArgs(request), event);
        };
        request.open(handler.method ? handler.method.toUpperCase() : "GET", handler.url ? handler.url : location.href, handler.async ? handler.async : true, handler.user ? handler.user : null, handler.password ? handler.password : null);
        if (handler.headers) for (let header in handler.headers) request.setRequestHeader(header, handler.headers[header]);
        if (handler.onabort) request.onabort = function (event) {
            return handler.onabort(xhrToArgs(request), event);
        };
        if (handler.onerror) request.onerror = function (event) {
            return handler.onerror(xhrToArgs(request), event);
        };
        if (handler.onload) request.onload = function (event) {
            return handler.onload(xhrToArgs(request), event);
        };
        if (handler.onloadend) request.onloadend = function (event) {
            return handler.onloadend(xhrToArgs(request), event);
        };
        if (handler.onloadstart) request.onloadstart = function (event) {
            return handler.onloadstart(xhrToArgs(request), event);
        };
        if (handler.onprogress) request.onprogress = function (event) {
            return handler.onprogress(xhrToArgs(request), event);
        };
        if (handler.ontimeout) request.ontimeout = function (event) {
            return handler.ontimeout(xhrToArgs(request), event);
        };
        if (handler.responseType) request.responseType = handler.responseType;
        if (handler.overrideMimeType) request.setRequestHeader("Content-Type", handler.overrideMimeType);
        if (handler.data) {
            request.send(JSON.stringify(handler.data));
        } else {
            request.send();
        }
        return request;
    }

    window.ready = function ready(handler, readyState = "interactive") {
        // "loading": 表示文档还在加载中,即处于“正在加载”状态。
        // "interactive": 文档已经结束了“正在加载”状态,DOM 元素可以被访问。但是像图像,样式表和框架等资源依然还在加载。
        // "complete": 页面所有内容都已被完全加载。
        let intervalId = setInterval(function (states = ["loading", "interactive", "complete"]) {
            if (states.indexOf(document.readyState.toLowerCase()) >= states.indexOf(readyState.toLowerCase())) {
                clearInterval(intervalId);
                if (typeof handler === "function") {
                    handler();
                } else {
                    console.error("Uncaught (in ready) TypeError: " + handler + " is not a function.");
                }
            }
        });
    }

    /**
     梅森旋转算法中用到的变量如下所示:
     w:长度 生成的随机数的二进制长度
     n:寄存器长度 参与旋转的随机数个数(旋转的深度)
     m:周期参数,用作第三阶段的偏移量 旋转算法参与旋转的中间项
     r:低位掩码/低位要提取的位数 内存界限值 2 的 r 次方 - 1 x⃗ (u)kx→k(u) 和 x⃗ (l)k+1x→k+1(l) 的切分位置
     a:旋转矩阵的参数 旋转算法异或基数 矩阵 AA 的最后一行
     f:初始化梅森旋转链所需参数 旋转链异或值膨化量
     u,s,t,l: 整数参数,移位运算的移动距离
     d,b,c: 比特遮罩
     s,t:TGFSR的位移量
     b,c:TGFSR的掩码
     u,d,l:额外梅森旋转所需的掩码和位移量

     MT19937-32的参数列表如下:
     (w, n, m, r) = (32, 624, 397, 31)
     a = 9908B0DF(16)
     f = 1812433253
     (u, d) = (11, FFFFFFFF16)
     (s, b) = (7, 9D2C568016)
     (t, c) = (15, EFC6000016)
     l = 18
     */
    window.MT = (function () {
        // 新方案定义私有变量。修复部分浏览器不支持 # 定义private私有变量
        const $n = Symbol(), $m = Symbol(), $r = Symbol(),
            $a = Symbol(),
            $u = Symbol(), $d = Symbol(),
            $s = Symbol(), $b = Symbol(),
            $t = Symbol(), $c = Symbol(),
            $l = Symbol(),
            $index = Symbol(), $LinkedList = Symbol();

        // 旋转算法处理旋转链
        function generate(MT) {
            for (let i = 0n; i < MT[$n]; i++) {
                const lower_mask = -(1n << MT[$r]);
                const upper_mask = ~lower_mask;
                const y = (MT[$LinkedList][i] & upper_mask) + (MT[$LinkedList][(i + 1n) % MT[$n]] & lower_mask);
                let yA = y >> 1n;
                if ((y % 2n) !== 0n) {
                    yA = yA ^ MT[$a];
                }
                MT[$LinkedList][i] = MT[$LinkedList][(i + MT[$m]) % MT[$n]] ^ yA;
            }
        }

        class MT {
            constructor(
                seed = Date.now(),
                w = 32, n = 624, m = 397, r = 31,
                a = 0x9908B0DF, f = 1812433253,
                u = 11, d = 0xFFFFFFFF,
                s = 7, b = 0x9D2C5680,
                t = 15, c = 0xEFC60000,
                l = 18) {

                w = BigInt(w);
                this[$n] = BigInt(n);
                this[$m] = BigInt(m);
                this[$r] = BigInt(r);

                this[$a] = BigInt(a);
                f = BigInt(f);

                this[$u] = BigInt(u);
                this[$d] = BigInt(d);

                this[$s] = BigInt(s);
                this[$b] = BigInt(b);

                this[$t] = BigInt(t);
                this[$c] = BigInt(c);

                this[$l] = BigInt(l);

                this[$index] = 0n;
                this[$LinkedList] = [BigInt(seed)];

                // 对数组其他元素进行初始化
                for (let i = 1n; i < this[$n]; i++) {
                    this[$LinkedList][i] = (f * (this[$LinkedList][i - 1n] ^ (this[$LinkedList][i - 1n] >> (w - 2n))) + i & (1n << w) - 1n);
                }
            }

            // 获取随机数
            next() {
                if (this[$index] === 0n) generate(this);
                let y = this[$LinkedList][this[$index]];
                y = (y ^ ((y >> this[$u]) & this[$d]));
                y = (y ^ ((y << this[$s]) & this[$b]));
                y = (y ^ ((y << this[$t]) & this[$c]));
                y = (y ^ (y >> this[$l]));
                this[$index] = (this[$index] + 1n) % this[$n];
                if (y <= 9007199254740992n) y = parseInt(y.toString());
                return y;
            }
        }

        return MT;
    })();
// 未经许可禁止抄袭算法,可以私用。
    window.Key = (function () {
        // 定义private私有变量
        const $pwd = Symbol();

        // 自定义加密算法,以防数据包被破解。
        class Key {
            // _pwd;        // 火狐v68版本貌似不支持这种方式声明变量。

            constructor(pwd = "Tenfond") {
                // num,密码偏移量
                // key,排列长度偏移量
                // charCode,防止内存频繁运动,定义在外部
                let key = 7n;
                if (typeof pwd === "string") {
                    for (let i = 0; i < pwd.length; i++) {
                        key = key * 31n + BigInt(pwd[i].charCodeAt(0));
                    }
                    pwd = key;
                    key = key & 0xFFFFFFFFFFFFn;
                } else if ((typeof pwd).match(new RegExp("(number|'bigint')"))) {
                    // 如果密码是数值型就使用此方法作为 密码偏移量 和 排列长度偏移量
                    pwd = BigInt(Math.round(pwd));
                    key = (key * 31n + pwd) & 0xFFFFFFFFFFFFn;
                } else {
                    // 如果类型不匹配就直接提出错误
                    console.error("Unsupported type '" + (typeof pwd) + "'. It only supports 'string' 'number' 'bigint'.");
                }
                // 让排列长度偏移量取第一个数字。加上密码转换成字符字符串的方式
                this[$pwd] = (pwd >= 0n ? pwd % 8n + 2n : -(pwd % 8n) + 2n).toString() + key.toString(36);
            }

            encrypt(string) {
                if (typeof string === "string" && string.length > 0) {
                    // subStart 排列长度的起始位置。subLength 排列长度。
                    let subStart = string.length, subLength = parseInt(this[$pwd][0]),
                        // encryptPool 加密池,即去除的排列长度存放在这里。result 加密后的结果。
                        encryptPool = [], result = "";
                    // stringKey 加密种子。
                    const MTSeed = new MT(subStart + parseInt(this[$pwd].substring(1), 36));
                    // 获取加密池。
                    while (subStart > subLength) {
                        subStart -= subLength;
                        encryptPool.push(string.substring(subStart, subStart + subLength));
                    }
                    encryptPool.push(string.substring(0, subStart));
                    // 对加密池进行加密,并将加密的字符的结果放入 result 中。
                    for (let i = 0, j; i < subLength; i++) {
                        for (j = 0; j < encryptPool.length; j++) {
                            const char = encryptPool[j][i];
                            if (char) {
                                let key = (char.charCodeAt(0) + MTSeed.next()) % 0x100000000;
                                key = [Math.floor(key / 0x10000), key % 0x10000];
                                result += i * j % 2 === 0 ? String.fromCharCode(key[0]) + String.fromCharCode(key[1]) : String.fromCharCode(key[1]) + String.fromCharCode(key[0]);
                            } else {
                                break;
                            }
                        }
                    }
                    // 返回加密结果
                    return result;
                } else {
                    // 如果加密字符串不存在就返回string
                    return string;
                }
            }

            /* 假设有7个字符

             加密前 - 排列
             ( 1 )  ( 2  3  4 )  ( 5  6  7 )

             加密中 - 排列
             ︵   ︵   ︵
             5    2    1
             6    3   ︶
             7    4
             ︶   ︶
             加密后 - 排列
             ( 5  2  1 )  ( 6  3 )  ( 7  4 )

             解密中 - 排列
             ︵   ︵   ︵
             5    6   7
             2    3   4
             1   ︶   ︶
             ︶

             解密后 - 排列
             1  2  3  4  5  6  7
            */

            decrypt(string) {
                if (typeof string === "string" && string.length > 0) {
                    // subStart 排列长度的起始位置。desubLength 反向取加密池的长度。
                    let subStart = 0,
                        desubLength = Math.ceil(string.length / 2 / parseInt(this[$pwd][0])),
                        // decryptPool 解密池。result 解密后的结果。
                        decryptPool = [], result = "";
                    // stringKey 加密种子。
                    const MTSeed = new MT(string.length / 2 + parseInt(this[$pwd].substring(1), 36));
                    (function (MT, desubLength) {
                        //NullCount 加密池中没有空位的池数
                        const NullCount = string.length / 2 % parseInt(MT[$pwd][0]);
                        // 获取解密池
                        while (string.length / 2 - subStart > desubLength) {
                            decryptPool.push(string.substring(subStart * 2, (subStart + desubLength) * 2));
                            subStart += desubLength;
                            if (decryptPool.length === NullCount) desubLength--;
                        }
                        decryptPool.push(string.substring(subStart * 2));
                    })(this, desubLength);
                    // 对解密池进行解密 并将解密结果 加入到 result(结果) 中
                    string = [];
                    for (let i = 0, j; i < decryptPool.length; i++) {
                        for (j = 0; j < desubLength; j++) {
                            const char = i * j % 2 === 0 ?
                                decryptPool[i][j * 2] + decryptPool[i][j * 2 + 1] :
                                decryptPool[i][j * 2 + 1] + decryptPool[i][j * 2];
                            if (char) {
                                if (typeof string[j] === "undefined") string[j] = [];
                                string[j][i] = String.fromCharCode((char.charCodeAt(0) * 65536 + char.charCodeAt(1) + 0x100000000 - MTSeed.next()) % 65536);
                            }
                        }
                    }
                    for (let i = string.length - 1; i >= 0; i--) {
                        result += string[i].join("");
                    }
                    // 返回解密结果
                    return result;
                } else {
                    // 如果解密字符串不存在就返回string
                    return string;
                }
            }

            // encrypt 既可以用作加密 也可以用作解密,decrypt 既可以用作解密 也可以用作加密。
        }

        return Key;
    })();
})();