您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
模拟macOS, Android, iOS, Windows, Linux,iPadOS
// ==UserScript== // @name 户晨风检测设备欺骗 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 模拟macOS, Android, iOS, Windows, Linux,iPadOS // @author beiying1337 // @match https://hcf2023.top/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; const originalUserAgent = navigator.userAgent; const originalPlatform = navigator.platform; const originalMaxTouchPoints = navigator.maxTouchPoints; // Store original properties for reset const originalProps = {}; ['userAgent', 'platform', 'maxTouchPoints', 'vendor', 'product', 'appVersion', 'appName', 'cookieEnabled', 'deviceMemory', 'hardwareConcurrency', 'language', 'languages', 'onLine', 'oscpu', 'plugins', 'productSub', 'serviceWorker', 'storage', 'webdriver', 'webkitTemporaryStorage', 'webkitPersistentStorage', 'xr'].forEach(prop => { if (Object.getOwnPropertyDescriptor(Navigator.prototype, prop)) { originalProps[prop] = Object.getOwnPropertyDescriptor(Navigator.prototype, prop).get ? navigator[prop] : null; } else if (navigator[prop] !== undefined) { originalProps[prop] = navigator[prop]; } }); // Add devicePixelRatio to originalProps originalProps.devicePixelRatio = window.devicePixelRatio; // Add screen dimensions to originalProps originalProps.screen = { width: window.screen.width, height: window.screen.height }; // Store original window properties for reset const originalWindowProps = {}; ['ApplePaySession', 'safari', 'DeviceMotionEvent', 'NDEFReader'].forEach(prop => { if (window[prop] !== undefined) { originalWindowProps[prop] = window[prop]; } }); // Store original CSS.supports for reset const originalCSSSupports = CSS.supports; // Store original getContext for WebGL proxy const originalGetContext = HTMLCanvasElement.prototype.getContext; // Store original matchMedia for proxy const originalMatchMedia = window.matchMedia; let currentSimulatedDevice = localStorage.getItem('simulatedDevice') || 'reset'; // Track current simulation and load from localStorage const deviceConfigs = { 'macos': { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', platform: 'MacIntel', maxTouchPoints: 0, // Navigator properties vendor: 'Google Inc.', product: 'Gecko', appVersion: '5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', appName: 'Netscape', oscpu: 'Intel Mac OS X', // Window properties ApplePaySession: true, safari: { pushNotification: () => {} }, // Mock safari.pushNotification DeviceMotionEvent: undefined, // No requestPermission on desktop NDEFReader: undefined, // CSS.supports webkitTouchCallout: false, webkitOverflowScrolling: false, // WebGL webglVendor: 'Apple Inc.', webglRenderer: 'Apple GPU', // MatchMedia pointerCoarse: false, pointerFine: true, hover: true, // Other navigator APIs webSerial: true, webHID: true, webUSB: true, getInstalledRelatedApps: undefined, // Explicitly disable for macOS standalone: undefined, // Not applicable for desktop }, 'android': { userAgent: 'Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36', platform: 'Android', maxTouchPoints: 5, vendor: 'Google Inc.', product: 'Gecko', appVersion: '5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36', appName: 'Netscape', oscpu: 'Linux armv8l', ApplePaySession: undefined, safari: undefined, DeviceMotionEvent: undefined, NDEFReader: class NDEFReader { constructor() { /* no-op */ } }, // Mock NDEFReader to allow instantiation // CSS.supports webkitTouchCallout: false, webkitOverflowScrolling: false, // WebGL webglVendor: 'Qualcomm', webglRenderer: 'Adreno (TM) 660', // MatchMedia pointerCoarse: true, pointerFine: false, hover: false, // Other navigator APIs webSerial: false, webHID: false, webUSB: true, getInstalledRelatedApps: () => Promise.resolve([]), // Mock getInstalledRelatedApps standalone: undefined, }, 'ios': { userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1', platform: 'iPhone', maxTouchPoints: 5, vendor: 'Apple Computer, Inc.', product: 'Gecko', appVersion: '5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1', appName: 'Netscape', oscpu: undefined, // iOS typically doesn't have oscpu ApplePaySession: true, safari: undefined, // No pushNotification on iOS DeviceMotionEvent: { requestPermission: () => Promise.resolve('granted') }, // Mock requestPermission NDEFReader: undefined, // Explicitly disable NDEFReader for iOS // CSS.supports webkitTouchCallout: true, webkitOverflowScrolling: true, // WebGL webglVendor: 'Apple Inc.', webglRenderer: 'Apple GPU', // MatchMedia pointerCoarse: true, pointerFine: false, hover: false, // Other navigator APIs webSerial: false, webHID: false, webUSB: false, getInstalledRelatedApps: undefined, // Explicitly disable for iOS standalone: true, // PWA standalone mode // Add screen dimensions for iOS (e.g., iPhone 8 dimensions) screen: [375, 667], }, 'ipados': { userAgent: 'Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1', platform: 'MacIntel', // iPadOS 13+ reports as MacIntel maxTouchPoints: 5, vendor: 'Apple Computer, Inc.', product: 'Gecko', appVersion: '5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1', appName: 'Netscape', oscpu: undefined, // iPadOS typically doesn't have oscpu ApplePaySession: true, safari: undefined, // No pushNotification on iPadOS DeviceMotionEvent: { requestPermission: () => Promise.resolve('granted') }, // Mock requestPermission NDEFReader: undefined, // Explicitly disable NDEFReader for iPadOS // CSS.supports webkitTouchCallout: true, webkitOverflowScrolling: true, // WebGL webglVendor: 'Apple Inc.', webglRenderer: 'Apple GPU', // MatchMedia pointerCoarse: true, pointerFine: false, hover: false, // Other navigator APIs webSerial: false, webHID: false, webUSB: false, getInstalledRelatedApps: undefined, // Explicitly disable for iPadOS standalone: true, // PWA standalone mode // Add screen dimensions for iPadOS (e.g., iPad 9th Gen dimensions) screen: [810, 1080], // Short side >= 600px devicePixelRatio: 1, // Set devicePixelRatio to 1 for iPadOS to ensure shortSideCSS >= 600 }, 'windows': { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', platform: 'Win32', maxTouchPoints: 0, vendor: 'Google Inc.', product: 'Gecko', appVersion: '5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', appName: 'Netscape', oscpu: 'Windows NT 10.0; Win64; x64', ApplePaySession: undefined, safari: undefined, DeviceMotionEvent: undefined, NDEFReader: undefined, // CSS.supports webkitTouchCallout: false, webkitOverflowScrolling: false, // WebGL webglVendor: 'Google Inc. (NVIDIA)', webglRenderer: 'ANGLE (NVIDIA, NVIDIA GeForce RTX 3080 Direct3D11 vs_5_0 ps_5_0, D3D11)', // MatchMedia pointerCoarse: false, pointerFine: true, hover: true, // Other navigator APIs webSerial: true, webHID: true, webUSB: true, getInstalledRelatedApps: undefined, // Explicitly disable for Windows standalone: undefined, }, 'linux': { userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', platform: 'Linux x86_64', maxTouchPoints: 0, vendor: 'Google Inc.', product: 'Gecko', appVersion: '5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', appName: 'Netscape', oscpu: 'Linux x86_64', ApplePaySession: undefined, safari: undefined, DeviceMotionEvent: undefined, NDEFReader: undefined, // CSS.supports webkitTouchCallout: false, webkitOverflowScrolling: false, // WebGL webglVendor: 'Mesa/X.Org', webglRenderer: 'Mesa Intel(R) HD Graphics 630 (KBL GT2)', // MatchMedia pointerCoarse: false, pointerFine: true, hover: true, // Other navigator APIs webSerial: true, webHID: true, webUSB: true, getInstalledRelatedApps: undefined, // Explicitly disable for Linux standalone: undefined, }, 'reset': { userAgent: originalUserAgent, platform: originalPlatform, maxTouchPoints: originalMaxTouchPoints, // Reset other properties to their original values ...originalProps, // Reset window properties ApplePaySession: originalWindowProps.ApplePaySession, safari: originalWindowProps.safari, DeviceMotionEvent: originalWindowProps.DeviceMotionEvent, NDEFReader: originalWindowProps.NDEFReader, // Reset CSS.supports webkitTouchCallout: originalCSSSupports?.('-webkit-touch-callout','none') || false, webkitOverflowScrolling: originalCSSSupports?.('-webkit-overflow-scrolling','touch') || false, // WebGL will be reset by restoring originalGetContext webglVendor: null, // Indicate no specific override webglRenderer: null, // Indicate no specific override // MatchMedia will be reset by restoring originalMatchMedia pointerCoarse: null, pointerFine: null, hover: null, // Reset other navigator APIs webSerial: 'serial' in navigator, webHID: 'hid' in navigator, webUSB: 'usb' in navigator, getInstalledRelatedApps: 'getInstalledRelatedApps' in navigator ? navigator.getInstalledRelatedApps : undefined, standalone: 'standalone' in navigator ? navigator.standalone : undefined, } }; function applyNavigatorProperty(prop, value) { if (value !== undefined) { Object.defineProperty(navigator, prop, { value: value, writable: true, configurable: true }); } else { // If value is undefined, try to delete the property or reset to original // If value is undefined, explicitly delete the property or set it to undefined try { delete navigator[prop]; } catch (e) { // If deletion fails (e.g., non-configurable property), set to undefined Object.defineProperty(navigator, prop, { value: undefined, writable: true, configurable: true }); } } } function applyWindowProperty(prop, value) { if (value !== undefined) { window[prop] = value; } else { if (originalWindowProps[prop] !== undefined) { window[prop] = originalWindowProps[prop]; } else { try { delete window[prop]; } catch (e) { // Cannot delete some native properties } } } } function applyCSSSupports(config) { // Temporarily override CSS.supports for specific checks CSS.supports = function(property, value) { if (property === '-webkit-touch-callout' && value === 'none') { return config.webkitTouchCallout; } if (property === '-webkit-overflow-scrolling' && value === 'touch') { return config.webkitOverflowScrolling; } return originalCSSSupports.apply(this, arguments); }; } function resetCSSSupports() { CSS.supports = originalCSSSupports; } function proxyWebGL(config) { HTMLCanvasElement.prototype.getContext = function(type, contextAttributes) { if (type === 'webgl' || type === 'experimental-webgl') { const gl = originalGetContext.call(this, type, contextAttributes); if (gl) { const originalGetParameter = gl.getParameter; gl.getParameter = function(name) { const debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); if (debugInfo && name === debugInfo.UNMASKED_VENDOR_WEBGL) { return config.webglVendor || originalGetParameter.call(this, name); } if (debugInfo && name === debugInfo.UNMASKED_RENDERER_WEBGL) { return config.webglRenderer || originalGetParameter.call(this, name); } if (name === gl.VENDOR) { return config.webglVendor || originalGetParameter.call(this, name); } if (name === gl.RENDERER) { return config.webglRenderer || originalGetParameter.call(this, name); } return originalGetParameter.call(this, name); }; } return gl; } return originalGetContext.call(this, type, contextAttributes); }; } function resetWebGLProxy() { HTMLCanvasElement.prototype.getContext = originalGetContext; } function proxyMatchMedia(config) { window.matchMedia = function(query) { const mockMediaQueryList = { matches: false, media: query, onchange: null, addListener: () => {}, removeListener: () => {}, addEventListener: () => {}, removeEventListener: () => {}, dispatchEvent: () => true, }; if (query === '(pointer:coarse)') { mockMediaQueryList.matches = config.pointerCoarse; } else if (query === '(pointer:fine)') { mockMediaQueryList.matches = config.pointerFine; } else if (query === '(hover:hover)') { mockMediaQueryList.matches = config.hover; } // Add other media queries if needed return mockMediaQueryList; }; } function resetMatchMediaProxy() { window.matchMedia = originalMatchMedia; } function setDevice(deviceType) { // Removed reloadPage parameter const previousSimulatedDevice = localStorage.getItem('simulatedDevice') || 'reset'; currentSimulatedDevice = deviceType; localStorage.setItem('simulatedDevice', deviceType); // Store selected device const config = deviceConfigs[deviceType]; if (config) { // Apply navigator properties for (const prop in originalProps) { // Reset all original props first applyNavigatorProperty(prop, originalProps[prop]); } // Special handling for getInstalledRelatedApps if (deviceType === 'android') { Object.defineProperty(navigator, 'getInstalledRelatedApps', { value: config.getInstalledRelatedApps, // This should be the mock function writable: true, configurable: true }); } else { Object.defineProperty(navigator, 'getInstalledRelatedApps', { value: undefined, writable: true, configurable: true }); } // Apply other navigator properties, excluding getInstalledRelatedApps as it's handled for (const prop in config) { // Then apply specific config props if (prop !== 'getInstalledRelatedApps' && ['userAgent', 'platform', 'maxTouchPoints', 'vendor', 'product', 'appVersion', 'appName', 'oscpu', 'webSerial', 'webHID', 'webUSB', 'standalone'].includes(prop)) { applyNavigatorProperty(prop, config[prop]); } } // Apply window properties for (const prop in originalWindowProps) { // Reset all original window props first applyWindowProperty(prop, originalWindowProps[prop]); } applyWindowProperty('ApplePaySession', config.ApplePaySession); applyWindowProperty('safari', config.safari); applyWindowProperty('DeviceMotionEvent', config.DeviceMotionEvent); applyWindowProperty('NDEFReader', config.NDEFReader); // Apply CSS.supports overrides resetCSSSupports(); // Reset first applyCSSSupports(config); // Apply WebGL proxy resetWebGLProxy(); // Reset first proxyWebGL(config); // Apply MatchMedia proxy resetMatchMediaProxy(); // Reset first proxyMatchMedia(config); // Apply screen dimensions if (config.screen) { Object.defineProperty(window.screen, 'width', { value: config.screen[0], writable: true, configurable: true }); Object.defineProperty(window.screen, 'height', { value: config.screen[1], writable: true, configurable: true }); } else { // Reset screen dimensions to original if not specified in config Object.defineProperty(window.screen, 'width', { value: originalProps.screen.width, writable: true, configurable: true }); Object.defineProperty(window.screen, 'height', { value: originalProps.screen.height, writable: true, configurable: true }); } // Apply devicePixelRatio if (config.devicePixelRatio !== undefined) { Object.defineProperty(window, 'devicePixelRatio', { value: config.devicePixelRatio, writable: true, configurable: true }); } else { // Reset devicePixelRatio to original Object.defineProperty(window, 'devicePixelRatio', { value: originalProps.devicePixelRatio, writable: true, configurable: true }); } console.log(`Device simulated as: ${deviceType}`); console.log(`New User Agent: ${navigator.userAgent}`); console.log(`New Platform: ${navigator.platform}`); console.log(`New Max Touch Points: ${navigator.maxTouchPoints}`); console.log(`New WebGL Vendor: ${config.webglVendor}`); console.log(`New WebGL Renderer: ${config.webglRenderer}`); console.log(`New MatchMedia (pointer:coarse): ${window.matchMedia('(pointer:coarse)').matches}`); console.log(`New MatchMedia (pointer:fine): ${window.matchMedia('(pointer:fine)').matches}`); console.log(`New MatchMedia (hover:hover): ${window.matchMedia('(hover:hover)').matches}`); console.log(`New Screen Width: ${window.screen.width}`); console.log(`New Screen Height: ${window.screen.height}`); console.log(`New Device Pixel Ratio: ${window.devicePixelRatio}`); // Re-run detection logic if (window.detect) { window.detect(); } } else if (deviceType === 'reset') { // Reset all properties to original for (const prop in originalProps) { applyNavigatorProperty(prop, originalProps[prop]); } for (const prop in originalWindowProps) { applyWindowProperty(prop, originalWindowProps[prop]); } resetCSSSupports(); resetWebGLProxy(); resetMatchMediaProxy(); // Reset matchMedia // Reset screen dimensions Object.defineProperty(window.screen, 'width', { value: originalProps.screen.width, writable: true, configurable: true }); Object.defineProperty(window.screen, 'height', { value: originalProps.screen.height, writable: true, configurable: true }); // Reset devicePixelRatio Object.defineProperty(window, 'devicePixelRatio', { value: originalProps.devicePixelRatio, writable: true, configurable: true }); console.log('Device simulation reset to original.'); localStorage.removeItem('simulatedDevice'); // Clear stored device // Re-run detection logic if (window.detect) { window.detect(); } } } function createUI() { const uiContainer = document.createElement('div'); uiContainer.id = 'device-simulator-ui'; uiContainer.style.cssText = ` position: fixed; top: 10px; right: 10px; background: rgba(0, 0, 0, 0.7); color: white; padding: 10px; border-radius: 8px; font-family: sans-serif; z-index: 10000; display: flex; flex-direction: column; gap: 5px; `; const title = document.createElement('div'); title.textContent = '模拟设备'; title.style.fontWeight = 'bold'; uiContainer.appendChild(title); const select = document.createElement('select'); select.style.cssText = ` padding: 5px; border-radius: 4px; border: 1px solid #555; background: #333; color: white; margin-bottom: 5px; /* Add some space below the select */ `; const options = [ { value: 'reset', text: '原始设备' }, { value: 'macos', text: 'macOS' }, { value: 'android', text: 'Android' }, { value: 'ios', text: 'iOS' }, { value: 'ipados', text: 'iPadOS' }, { value: 'windows', text: 'Windows' }, { value: 'linux', text: 'Linux' } ]; options.forEach(optData => { const option = document.createElement('option'); option.value = optData.value; option.textContent = optData.text; select.appendChild(option); }); select.addEventListener('change', (event) => { setDevice(event.target.value); location.reload(); // Reload only when user explicitly changes device }); uiContainer.appendChild(select); document.body.appendChild(uiContainer); // Set the initial selected value based on localStorage select.value = currentSimulatedDevice; // Add "屏蔽毒蘑菇" checkbox const mushroomToggleContainer = document.createElement('div'); mushroomToggleContainer.style.cssText = ` display: flex; align-items: center; gap: 5px; `; const mushroomCheckbox = document.createElement('input'); mushroomCheckbox.type = 'checkbox'; mushroomCheckbox.id = 'block-mushroom-toggle'; mushroomCheckbox.style.cssText = ` margin: 0; `; const mushroomLabel = document.createElement('label'); mushroomLabel.htmlFor = 'block-mushroom-toggle'; mushroomLabel.textContent = '屏蔽毒蘑菇 (WebGL)'; mushroomLabel.style.fontSize = '12px'; mushroomToggleContainer.appendChild(mushroomCheckbox); mushroomToggleContainer.appendChild(mushroomLabel); uiContainer.appendChild(mushroomToggleContainer); mushroomCheckbox.addEventListener('change', (event) => { if (window.toggleCanvas) { window.toggleCanvas(!event.target.checked); // checked means block, so enable = !checked } else { console.warn('window.toggleCanvas is not available yet.'); } }); // Set initial state of the checkbox based on current canvas status const updateMushroomCheckbox = () => { if (window.getCanvasStatus) { mushroomCheckbox.checked = window.getCanvasStatus().disabled; } else { // Default to unchecked (canvas enabled) if status not available mushroomCheckbox.checked = false; } }; // Update checkbox state after UI creation and after setDevice updateMushroomCheckbox(); window.addEventListener('load', updateMushroomCheckbox); // Ensure it's updated after script.js loads } // Apply the stored device simulation immediately on script load setDevice(currentSimulatedDevice); // Ensure the mushroom checkbox is updated after setDevice applies initial canvas state window.addEventListener('load', () => { if (window.getCanvasStatus) { const mushroomCheckbox = document.getElementById('block-mushroom-toggle'); if (mushroomCheckbox) { mushroomCheckbox.checked = window.getCanvasStatus().disabled; } } }); // In page load完成后创建UI window.addEventListener('load', createUI); // 确保在插件加载时,如果页面已经加载,UI也能被创建 if (document.readyState === 'complete') { createUI(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址