浏览器功能包

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

目前為 2022-10-22 提交的版本,檢視 最新版本

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

(function () {
    try {
        const timers = {
                "Timeout": {},
                "Interval": {}
            },
            setTimeout = window.setTimeout,
            setInterval = window.setInterval,
            clearTimeout = window.clearTimeout,
            clearInterval = window.clearInterval;
        window.setTimeout = function (handler, timeout, ...arguments) {
            const handle = setTimeout.apply(this, [handler, timeout].concat(arguments));
            timers["Timeout"][handle] = {
                "handler": handler,
                "timeout": timeout,
                "arguments": arguments
            };
            return handle;
        };
        window.setInterval = function (handler, timeout, ...arguments) {
            const handle = setInterval.apply(this, [handler, timeout].concat(arguments));
            timers["Interval"][handle] = {
                "handler": handler,
                "timeout": timeout,
                "arguments": arguments
            };
            return handle;
        };
        window.getAllTimeout = function () {
            return timers["Timeout"];
        };
        window.getAllInterval = function () {
            return timers["Interval"];
        };
        window.getTimeout = function (handle) {
            return timers["Timeout"][handle];
        };
        window.getInterval = function (handle) {
            return timers["Interval"][handle];
        };
        window.clearTimeout = function (handle) {
            clearTimeout.apply(this, arguments);
            delete timers["Timeout"][handle];
        };
        window.clearInterval = function (handle) {
            clearInterval.apply(this, arguments);
            delete timers["Interval"][handle];
        };
    } catch (e) {
        console.error(e.message);
    }

    // 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;
    })();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址