by Proze

Full browser fingerprinting evasion suite.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        by Proze
// @namespace   Violentmonkey Scripts
// @match       *://*/*
// @grant       none
// @run-at      document-start
// @version     10.0
// @author      .*
// @description Full browser fingerprinting evasion suite.
// @license     MIT
// ==/UserScript==

(function() {
    'use strict';

    const D = {
        os: [
            { n: "Windows NT 10.0; Win64; x64", p: "Win32", v: "Google Inc.", m: "desktop" },
            { n: "Windows NT 10.0; WOW64", p: "Win32", v: "Google Inc.", m: "desktop" },
            { n: "Macintosh; Intel Mac OS X 10_15_7", p: "MacIntel", v: "Apple Computer, Inc.", m: "desktop" },
            { n: "Macintosh; Intel Mac OS X 12_3_1", p: "MacIntel", v: "Apple Computer, Inc.", m: "desktop" },
            { n: "X11; Linux x86_64", p: "Linux x86_64", v: "Google Inc.", m: "desktop" },
            { n: "Linux; Android 13; SM-S908B", p: "Linux armv8l", v: "Google Inc.", m: "mobile" },
            { n: "Linux; Android 12; Pixel 6 Pro", p: "Linux armv8l", v: "Google Inc.", m: "mobile" },
            { n: "iPhone; CPU iPhone OS 16_0 like Mac OS X", p: "iPhone", v: "Apple Computer, Inc.", m: "mobile" },
            { n: "iPad; CPU OS 15_4 like Mac OS X", p: "iPad", v: "Apple Computer, Inc.", m: "mobile" }
        ],
        browser: [
            "Chrome/108.0.0.0", "Chrome/109.0.0.0", "Chrome/110.0.0.0",
            "Safari/605.1.15", "Firefox/109.0", "Firefox/108.0"
        ],
        gpu: [
            "ANGLE (NVIDIA, NVIDIA GeForce RTX 3090 Direct3D11 vs_5_0 ps_5_0, D3D11)",
            "ANGLE (NVIDIA, NVIDIA GeForce RTX 3080 Direct3D11 vs_5_0 ps_5_0, D3D11)",
            "ANGLE (NVIDIA, NVIDIA GeForce GTX 1080 Ti Direct3D11 vs_5_0 ps_5_0, D3D11)",
            "ANGLE (AMD, AMD Radeon RX 6900 XT Direct3D11 vs_5_0 ps_5_0, D3D11)",
            "ANGLE (Intel, Intel(R) Iris(R) Xe Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)",
            "Apple GPU", "Apple A15 GPU", "Apple A16 GPU", "Adreno (TM) 730", "Mali-G710 MC10"
        ],
        tz: [
            { z: "America/New_York", o: 300, l: "en-US" }, { z: "America/Los_Angeles", o: 480, l: "en-US" },
            { z: "Europe/London", o: 0, l: "en-GB" }, { z: "Europe/Berlin", o: -60, l: "de-DE" },
            { z: "Asia/Tokyo", o: -540, l: "ja-JP" }, { z: "Asia/Singapore", o: -480, l: "en-SG" }
        ]
    };

    function r(a) { return a[Math.floor(Math.random() * a.length)]; }
    function ri(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
    function rf() { return Math.random() * 0.0000001; }

    const sOS = r(D.os);
    const sBr = r(D.browser);
    const sUA = `Mozilla/5.0 (${sOS.n}) AppleWebKit/537.36 (KHTML, like Gecko) ${sBr} Safari/537.36`;
    const sGpu = r(D.gpu);
    const sTz = r(D.tz);
    const sW = sOS.m === "mobile" ? ri(360, 430) : ri(1366, 2560);
    const sH = sOS.m === "mobile" ? ri(640, 932) : ri(768, 1440);
    const sDPR = sOS.m === "mobile" ? ri(2, 3) : 1;
    const sMem = [4, 8, 12, 16, 32][ri(0, 4)];
    const sCon = [4, 6, 8, 12, 16, 24][ri(0, 5)];
    const sBat = Math.random();
    const sChg = Math.random() > 0.5;

    function inject(scope) {
        function def(o, p, v) {
            try { Object.defineProperty(scope.Object.getPrototypeOf(o), p, { get: () => v, configurable: true, enumerable: true }); } catch(e) {}
            try { Object.defineProperty(o, p, { get: () => v, configurable: true, enumerable: true }); } catch(e) {}
        }

        def(scope.navigator, 'userAgent', sUA);
        def(scope.navigator, 'appVersion', sUA.replace('Mozilla/', ''));
        def(scope.navigator, 'platform', sOS.p);
        def(scope.navigator, 'vendor', sOS.v);
        def(scope.navigator, 'hardwareConcurrency', sCon);
        def(scope.navigator, 'deviceMemory', sMem);
        def(scope.navigator, 'maxTouchPoints', sOS.m === "mobile" ? ri(2, 5) : 0);
        def(scope.navigator, 'webdriver', false);
        def(scope.navigator, 'doNotTrack', "1");
        def(scope.navigator, 'language', sTz.l);
        def(scope.navigator, 'languages', [sTz.l, 'en-US']);
        
        if (scope.navigator.plugins) {
            def(scope.navigator, 'plugins', []);
            def(scope.navigator, 'mimeTypes', []);
        }

        def(scope.screen, 'width', sW);
        def(scope.screen, 'height', sH);
        def(scope.screen, 'availWidth', sW);
        def(scope.screen, 'availHeight', sH - 40);
        def(scope.screen, 'colorDepth', 24);
        def(scope.screen, 'pixelDepth', 24);
        
        def(scope.window, 'devicePixelRatio', sDPR);
        def(scope.window, 'innerWidth', sW);
        def(scope.window, 'innerHeight', sH);
        def(scope.window, 'outerWidth', sW);
        def(scope.window, 'outerHeight', sH);

        try {
            const gP = scope.WebGLRenderingContext.prototype.getParameter;
            scope.WebGLRenderingContext.prototype.getParameter = function(p) {
                if (p === 37445) return "Google Inc. (NVIDIA)";
                if (p === 37446) return sGpu;
                return gP.apply(this, arguments);
            };
        } catch(e) {}

        try {
            const tDU = scope.HTMLCanvasElement.prototype.toDataURL;
            scope.HTMLCanvasElement.prototype.toDataURL = function() {
                const c = this.getContext('2d');
                if (c) {
                    const w = this.width;
                    const h = this.height;
                    const d = c.getImageData(0, 0, w, h);
                    for (let i = 0; i < d.data.length; i += 4) {
                        if (i % ri(500, 2000) === 0) d.data[i] = d.data[i] + (Math.random() > 0.5 ? 1 : -1);
                    }
                    c.putImageData(d, 0, 0);
                }
                return tDU.apply(this, arguments);
            };
        } catch(e) {}

        try {
            const oAC = scope.AudioContext || scope.webkitAudioContext;
            if (oAC) {
                const oAn = oAC.prototype.createAnalyser;
                oAC.prototype.createAnalyser = function() {
                    const a = oAn.apply(this, arguments);
                    const oG = a.getFloatFrequencyData;
                    a.getFloatFrequencyData = function(arr) {
                        const r = oG.apply(this, arguments);
                        for (let i = 0; i < arr.length; i += 10) arr[i] += (Math.random() * 0.1) - 0.05;
                        return r;
                    };
                    return a;
                };
            }
        } catch(e) {}

        try {
            const oRTC = scope.RTCPeerConnection || scope.webkitRTCPeerConnection || scope.mozRTCPeerConnection;
            if (oRTC) {
                scope.RTCPeerConnection = function(c) {
                    if (c && c.iceServers) c.iceServers = [];
                    const p = new oRTC(c);
                    const oO = p.createOffer;
                    p.createOffer = function(o) { return oO.call(this, o).then(f => f); };
                    return p;
                };
                scope.RTCPeerConnection.prototype = oRTC.prototype;
            }
        } catch(e) {}

        try {
            const mTxt = scope.CanvasRenderingContext2D.prototype.measureText;
            scope.CanvasRenderingContext2D.prototype.measureText = function(t) {
                const m = mTxt.apply(this, arguments);
                const n = (Math.random() * 0.01) - 0.005;
                try { Object.defineProperty(m, 'width', { get: () => m.width + n }); } catch(e) { m.width = m.width + n; }
                return m;
            };
        } catch(e) {}

        try {
            const oBCR = scope.Element.prototype.getBoundingClientRect;
            scope.Element.prototype.getBoundingClientRect = function() {
                const r = oBCR.apply(this, arguments);
                const n = rf();
                return { x: r.x + n, y: r.y + n, width: r.width + n, height: r.height + n, top: r.top + n, right: r.right + n, bottom: r.bottom + n, left: r.left + n, toJSON: () => this };
            };
        } catch(e) {}

        try {
            const oNow = scope.performance.now;
            scope.performance.now = function() { return oNow.apply(this) + (Math.random() * 0.02); };
        } catch(e) {}

        if (scope.navigator.getBattery) {
            scope.navigator.getBattery = () => Promise.resolve({ charging: sChg, chargingTime: sChg ? ri(100, 5000) : Infinity, dischargingTime: sChg ? Infinity : ri(100, 50000), level: sBat, addEventListener: () => {}, removeEventListener: () => {} });
        }

        if (scope.navigator.permissions) {
            scope.navigator.permissions.query = p => Promise.resolve({ state: 'prompt', onchange: null });
        }

        const oIntl = scope.Intl.DateTimeFormat;
        scope.Intl.DateTimeFormat = function(l, o) {
            if (!o) o = {};
            if (!o.timeZone) o.timeZone = sTz.z;
            return new oIntl(l, o);
        };
        scope.Intl.DateTimeFormat.prototype = oIntl.prototype;
    }

    inject(window);

    const observer = new MutationObserver(mutations => {
        mutations.forEach(m => {
            m.addedNodes.forEach(n => {
                if (n.tagName === 'IFRAME') {
                    try {
                        if (n.contentWindow) inject(n.contentWindow);
                        n.addEventListener('load', () => inject(n.contentWindow));
                    } catch(e) {}
                }
            });
        });
    });
    observer.observe(document.documentElement, { childList: true, subtree: true });

    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;

})();