Anti-Fingerprinting Shield Plus

Spoofs browser fingerprint data: canvas, WebGL, audio, language, timezone, userAgent, screen size, memory, and more. Spoofed values persist across tabs and expire after 30 minutes to simulate session behavior realistically. Top-frame only execution for stealth and compatibility.

目前為 2025-05-03 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Anti-Fingerprinting Shield Plus
// @namespace    https://365devnet.eu/userscripts
// @version      4.5
// @description  Spoofs browser fingerprint data: canvas, WebGL, audio, language, timezone, userAgent, screen size, memory, and more. Spoofed values persist across tabs and expire after 30 minutes to simulate session behavior realistically. Top-frame only execution for stealth and compatibility.
// @author       Richard B
// @match        *://*/*
// @run-at       document-start
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  if (window.top !== window.self) return;

  const DEBUG_MODE = true;
  const SESSION_TIMEOUT_MINUTES = 30;
  const sessionExpiryKey = '__afs_last_seen';
  const now = Date.now();

  const isExpired = () => {
    const lastSeen = parseInt(localStorage.getItem(sessionExpiryKey), 10);
    return isNaN(lastSeen) || now - lastSeen > SESSION_TIMEOUT_MINUTES * 60 * 1000;
  };

  if (isExpired()) {
    clearStoredSpoofedValues();
    if (DEBUG_MODE) console.log(`[AFS+] New session started (values expired after ${SESSION_TIMEOUT_MINUTES} minutes)`);
  }
  localStorage.setItem(sessionExpiryKey, now.toString());

  const sessionId = getOrCreatePersistent('__afs_session_id', () =>
    Math.random().toString(36).substring(2, 10)
  );

  if (DEBUG_MODE) console.log(`[AFS+] Anti-Fingerprinting Shield v4.5 started. Session ID: ${sessionId}`);

  const platforms = ['Win32', 'Linux x86_64', 'MacIntel', 'FreeBSD'];
  const languages = ['en-US', 'nl-NL', 'fr-FR', 'de-DE', 'sv-SE'];
  const timezones = ['UTC', 'Europe/Amsterdam', 'America/New_York', 'Asia/Tokyo'];
  const userAgents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
  ];
  const cores = [2, 4, 6, 8];
  const memorySizes = [2, 4, 8];
  const screenWidths = [1920, 1680, 1366];
  const screenHeights = [1080, 1050, 768];

  const spoofed = {
    platform: getOrCreatePersistent('platform', () => pick(platforms)),
    language: getOrCreatePersistent('language', () => pick(languages)),
    languages: () => [spoofed.language, 'en'],
    timezone: getOrCreatePersistent('timezone', () => pick(timezones)),
    userAgent: getOrCreatePersistent('userAgent', () => pick(userAgents)),
    cores: parseInt(getOrCreatePersistent('cores', () => pick(cores))),
    memory: parseInt(getOrCreatePersistent('memory', () => pick(memorySizes))),
    screenWidth: parseInt(getOrCreatePersistent('screenWidth', () => pick(screenWidths))),
    screenHeight: parseInt(getOrCreatePersistent('screenHeight', () => pick(screenHeights))),
    vendor: 'SpoofedVendor',
    doNotTrack: Math.random() > 0.5 ? '1' : '0'
  };

  function pick(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
  }

  function getOrCreatePersistent(key, generator) {
    const fullKey = '__afs_' + key;
    let value = localStorage.getItem(fullKey);
    if (!value) {
      value = generator();
      localStorage.setItem(fullKey, value);
    }
    return value;
  }

  function clearStoredSpoofedValues() {
    Object.keys(localStorage)
      .filter(key => key.startsWith('__afs_'))
      .forEach(key => localStorage.removeItem(key));
  }

  function spoof(obj, prop, valueFn) {
    try {
      Object.defineProperty(obj, prop, {
        get: valueFn,
        configurable: true
      });
    } catch (e) {}
  }

  spoof(navigator, 'language', () => spoofed.language);
  spoof(navigator, 'languages', () => spoofed.languages());
  spoof(navigator, 'platform', () => spoofed.platform);
  spoof(navigator, 'userAgent', () => spoofed.userAgent);
  spoof(navigator, 'hardwareConcurrency', () => spoofed.cores);
  spoof(navigator, 'deviceMemory', () => spoofed.memory);
  spoof(navigator, 'vendor', () => spoofed.vendor);
  spoof(navigator, 'doNotTrack', () => spoofed.doNotTrack);
  spoof(navigator, 'maxTouchPoints', () => 1);
  spoof(navigator, 'plugins', () => []);
  spoof(navigator, 'mimeTypes', () => ({ length: 0 }));
  spoof(navigator, 'mediaDevices', () => ({ enumerateDevices: () => Promise.resolve([]) }));
  spoof(navigator, 'webdriver', () => false);
  spoof(navigator, 'connection', () => ({ downlink: 10, effectiveType: '4g', rtt: 50, saveData: false }));
  spoof(navigator, 'mediaCapabilities', () => undefined);
  spoof(navigator, 'mediaSession', () => undefined);

  if (navigator.permissions && navigator.permissions.query) {
    const originalQuery = navigator.permissions.query;
    navigator.permissions.query = function (params) {
      if (params.name === 'notifications') {
        return Promise.resolve({ state: 'denied' });
      }
      return originalQuery.call(this, params);
    };
  }

  spoof(window.screen, 'width', () => spoofed.screenWidth);
  spoof(window.screen, 'height', () => spoofed.screenHeight);
  spoof(window, 'innerWidth', () => spoofed.screenWidth);
  spoof(window, 'innerHeight', () => spoofed.screenHeight - 40);

  try {
    const original = Intl.DateTimeFormat.prototype.resolvedOptions;
    Intl.DateTimeFormat.prototype.resolvedOptions = function () {
      const options = original.call(this);
      options.timeZone = spoofed.timezone;
      return options;
    };
  } catch (e) {}

  spoof(Date.prototype, 'getTimezoneOffset', () => {
    const offsetMap = { 'UTC': 0, 'Europe/Amsterdam': -120, 'America/New_York': 300, 'Asia/Tokyo': -540 };
    return offsetMap[spoofed.timezone] || 0;
  });

  const AudioContext = window.AudioContext || window.webkitAudioContext;
  if (AudioContext) {
    spoof(AudioContext.prototype, 'sampleRate', () => 44100);
    if (AnalyserNode.prototype.getFloatFrequencyData) {
      const original = AnalyserNode.prototype.getFloatFrequencyData;
      AnalyserNode.prototype.getFloatFrequencyData = function (arr) {
        original.call(this, arr);
        for (let i = 0; i < arr.length; i++) {
          arr[i] += Math.random() * 0.1;
        }
      };
    }
  }

  const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
  CanvasRenderingContext2D.prototype.getImageData = function (x, y, w, h) {
    const data = originalGetImageData.call(this, x, y, w, h);
    for (let i = 0; i < data.data.length; i += 4) {
      data.data[i] += Math.floor(Math.random() * 3);
      data.data[i + 1] += Math.floor(Math.random() * 3);
      data.data[i + 2] += Math.floor(Math.random() * 3);
    }
    return data;
  };

  const originalGL = WebGLRenderingContext.prototype.getParameter;
  WebGLRenderingContext.prototype.getParameter = function (param) {
    const spoofMap = { 37445: 'FakeVendor Inc.', 37446: 'Virtual GPU Renderer', 3379: 4096, 35661: 8 };
    return spoofMap[param] || originalGL.call(this, param);
  };

  WebGLRenderingContext.prototype.getShaderPrecisionFormat = function () {
    return { rangeMin: 127, rangeMax: 127, precision: 23 };
  };

  performance.now = () => Math.floor(performance.timeOrigin + Math.random() * 100);

  navigator.storage.estimate = () => Promise.resolve({ usage: 5242880, quota: 1073741824 });

  window.RTCPeerConnection = undefined;
  window.webkitRTCPeerConnection = undefined;
  window.Bluetooth = undefined;
  delete navigator.getBattery;
  delete navigator.bluetooth;

  window.DeviceMotionEvent = undefined;
  window.DeviceOrientationEvent = undefined;

  window.addEventListener('devicemotion', e => e.stopImmediatePropagation(), true);
  window.addEventListener('deviceorientation', e => e.stopImmediatePropagation(), true);

  window.addEventListener('beforeunload', e => {
    e.stopImmediatePropagation();
    e.preventDefault();
    return undefined;
  }, true);

  if (DEBUG_MODE) {
    console.group(`[AFS+] Spoofed Fingerprint for Session: ${sessionId}`);
    console.log('User Agent     :', spoofed.userAgent);
    console.log('Platform       :', spoofed.platform);
    console.log('Language       :', spoofed.language);
    console.log('Languages      :', spoofed.languages().join(', '));
    console.log('Timezone       :', spoofed.timezone);
    console.log('CPU Cores      :', spoofed.cores);
    console.log('Device Memory  :', spoofed.memory);
    console.log('Screen Width   :', spoofed.screenWidth);
    console.log('Screen Height  :', spoofed.screenHeight);
    console.log('Vendor         :', spoofed.vendor);
    console.log('DNT            :', spoofed.doNotTrack);
    console.groupEnd();
  }
})();