您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
绕过网站的反开发者工具限制,启用完整的开发者访问权限
// ==UserScript== // @name DevTools Bypass // @name:vi Bỏ Qua Chặn DevTools // @name:zh-CN 开发工具限制绕过 // @name:en DevTools Bypass // @namespace https://greasyfork.org/vi/users/1195312-renji-yuusei // @version 4.0.0 // @description Bypass website anti-DevTools restrictions and enable full developer access // @description:vi Vô hiệu hóa các biện pháp chặn DevTools của website và cho phép truy cập đầy đủ // @description:zh-CN 绕过网站的反开发者工具限制,启用完整的开发者访问权限 // @description:en Bypass website anti-DevTools restrictions and enable full developer access // @author Yuusei // @match *://*/* // @grant unsafeWindow // @run-at document-start // @license GPL-3.0-only // ==/UserScript== (() => { "use strict"; // Configuration const CONFIG = { // Enhanced regex to detect and neutralize anti-DevTools code antiDevToolsRegex: new RegExp( [ // Debugger statements - remove completely /(?:^|[;\s{(,])\s*debugger\s*(?:[;\s}),]|$)/.source, // Function constructor with debugger /(?:new\s+)?Function\s*\(\s*['"`][^'"`]*debugger[^'"`]*['"`]\s*\)/ .source, // Timer-based debugger injections /(?:setTimeout|setInterval)\s*\(\s*(?:function[^{]*\{[^}]*debugger[^}]*\}|['"`][^'"`]*debugger[^'"`]*['"`])\s*[,)]/ .source, // eval with debugger /eval\s*\(\s*['"`][^'"`]*debugger[^'"`]*['"`]\s*\)/.source, // Console detection tricks /console\s*\[\s*['"`](?:log|warn|error|info|debug|clear|table|dir|group|time)['"`]\s*\]\s*\.\s*toString/ .source, /console\.(?:log|warn|error|info|debug|trace|clear|table|dir|group|time)\s*\.\s*toString\s*\(\s*\)/ .source, // DevTools size detection /(?:window\.(?:outer|inner)(?:Width|Height)|screen\.(?:width|height))\s*[-+*\/]\s*(?:window\.(?:outer|inner)(?:Width|Height)|screen\.(?:width|height))\s*[<>=!]+\s*\d+/ .source, // Performance timing detection /(?:performance\.now|Date\.now)\s*\(\s*\)\s*[-+]\s*(?:performance\.now|Date\.now)\s*\(\s*\)\s*[><=!]+\s*\d+/ .source, // Known anti-DevTools libraries /(?:FuckDevTools|devtools-detector|disable-devtool|console-ban|anti-debug|devtools-detect|fuck-debugger)/ .source, // DevTools event listeners /(?:addEventListener|on)\s*\(\s*['"`](?:keydown|keyup|keypress|contextmenu|selectstart|copy|cut|paste|dragstart)['"`][^)]*(?:F12|preventDefault|stopPropagation)/ .source, // Console override attempts /console\s*=\s*(?:\{\}|null|undefined|false)/.source, /window\.console\s*=/.source, // DevTools detection via exceptions /try\s*\{[^}]*(?:debugger|console)[^}]*\}\s*catch/.source, // Stack trace analysis for DevTools detection /(?:Error|TypeError|ReferenceError)\(\)\.stack\.(?:split|match|replace|indexOf|includes|search)/ .source, // Arguments.callee detection (used in some anti-debug) /arguments\.callee/.source, // toString override for detection /toString\s*=\s*function[^{]*\{[^}]*(?:devtools|debug|console)/.source, ].join("|"), "gim" ), protection: { neutralizeDebugger: true, enableDevToolsKeys: true, enableRightClick: true, enableTextSelection: true, enableCopyPaste: true, preventAntiDebugTimers: true, restoreConsole: true, preventKeyBlocking: true, }, logging: { enabled: true, prefix: "[DevTools Bypass]", verbose: false, }, }; // Logger class Logger { static #logHistory = new Map(); static #maxLogsPerType = 5; static #canLog(type, message) { const key = `${type}:${message}`; const count = this.#logHistory.get(key) || 0; if (count >= this.#maxLogsPerType) return false; this.#logHistory.set(key, count + 1); return true; } static info(message, ...args) { if (CONFIG.logging.enabled && this.#canLog("info", message)) { console.info(CONFIG.logging.prefix, message, ...args); } } static warn(message, ...args) { if (CONFIG.logging.enabled && this.#canLog("warn", message)) { console.warn(CONFIG.logging.prefix, message, ...args); } } static debug(message, ...args) { if ( CONFIG.logging.enabled && CONFIG.logging.verbose && this.#canLog("debug", message) ) { console.debug(CONFIG.logging.prefix, message, ...args); } } } // Store original functions before they get overridden const ORIGINAL = { // Core functions Function: window.Function, eval: window.eval, setTimeout: window.setTimeout, setInterval: window.setInterval, clearTimeout: window.clearTimeout, clearInterval: window.clearInterval, // Timing Date: window.Date, now: Date.now, performance: window.performance?.now?.bind(window.performance), // DOM addEventListener: window.addEventListener, removeEventListener: window.removeEventListener, createElement: document.createElement, // Object methods defineProperty: Object.defineProperty, getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor, keys: Object.keys, // Console (store before potential override) console: {}, }; // Backup console methods [ "log", "warn", "error", "info", "debug", "trace", "dir", "table", "group", "groupEnd", "clear", "time", "timeEnd", ].forEach((method) => { if (console[method]) { ORIGINAL.console[method] = console[method].bind(console); } }); // Code Neutralizer - Cleans anti-DevTools code class CodeNeutralizer { static neutralize(code) { if (typeof code !== "string" || !code.trim()) { return code; } try { let neutralized = code; // Replace anti-DevTools patterns neutralized = neutralized.replace( CONFIG.antiDevToolsRegex, (match, ...args) => { const replacement = this.#getReplacement(match); Logger.debug( "Neutralized anti-DevTools code:", match.substring(0, 100) ); return replacement; } ); // Handle encoded debugger statements neutralized = neutralized.replace( /\\u0064\\u0065\\u0062\\u0075\\u0067\\u0067\\u0065\\u0072/g, "" ); neutralized = neutralized.replace( /\u0064\u0065\u0062\u0075\u0067\u0067\u0065\u0072/g, "" ); // Remove obfuscated debugger neutralized = neutralized.replace(/['"`]debugger['"`]/g, '""'); neutralized = neutralized.replace(/\bdebugger\b/g, ""); // Neutralize console blocking neutralized = neutralized.replace( /console\s*=\s*(?:\{\}|null|undefined|false)/g, "console = console" ); neutralized = neutralized.replace(/window\.console\s*=\s*[^;]+/g, ""); return neutralized; } catch (e) { Logger.warn("Code neutralization failed:", e.message); return code; } } static #getReplacement(match) { if (match.includes("debugger")) { return "/* debugger statement removed */"; } if (match.includes("console")) { return "/* console detection removed */"; } if (match.includes("addEventListener") || match.includes("keydown")) { return "/* key blocking removed */"; } if (match.includes("performance") || match.includes("Date.now")) { return "/* timing detection removed */"; } return "/* anti-DevTools code removed */"; } } // DevTools Protection Bypass class DevToolsProtectionBypass { static apply() { this.#neutralizeFunctionConstructor(); this.#neutralizeEval(); this.#neutralizeTimers(); this.#preventKeyBlocking(); this.#restoreRightClick(); this.#restoreTextSelection(); this.#restoreConsole(); this.#preventTimingDetection(); this.#neutralizeDebuggerTricks(); this.#patchMutationObserver(); this.#restoreClipboard(); this.#preventErrorOverrides(); } // Neutralize Function constructor to prevent debugger injection static #neutralizeFunctionConstructor() { const handler = { construct(target, args) { if (args[0] && typeof args[0] === "string") { args[0] = CodeNeutralizer.neutralize(args[0]); } return Reflect.construct(target, args); }, apply(target, thisArg, args) { if (args[0] && typeof args[0] === "string") { args[0] = CodeNeutralizer.neutralize(args[0]); } return Reflect.apply(target, thisArg, args); }, }; try { window.Function = new Proxy(ORIGINAL.Function, handler); if (typeof unsafeWindow !== "undefined") { unsafeWindow.Function = window.Function; } Logger.info("Function constructor protected"); } catch (e) { Logger.warn("Function protection failed:", e.message); } } // Neutralize eval to prevent debugger injection static #neutralizeEval() { const safeEval = function (code) { if (typeof code === "string") { code = CodeNeutralizer.neutralize(code); } return ORIGINAL.eval.call(this, code); }; try { Object.defineProperty(window, "eval", { value: safeEval, writable: false, configurable: false, }); if (typeof unsafeWindow !== "undefined") { unsafeWindow.eval = safeEval; } Logger.info("eval function protected"); } catch (e) { Logger.warn("eval protection failed:", e.message); } } // Neutralize timers that might inject debugger static #neutralizeTimers() { const wrapTimer = (original, name) => { return function (handler, delay, ...args) { if (typeof handler === "string") { handler = CodeNeutralizer.neutralize(handler); } return original.call(this, handler, delay, ...args); }; }; window.setTimeout = wrapTimer(ORIGINAL.setTimeout, "setTimeout"); window.setInterval = wrapTimer(ORIGINAL.setInterval, "setInterval"); Logger.info("Timer functions protected"); } // Prevent key blocking (F12, Ctrl+Shift+I, etc.) static #preventKeyBlocking() { const events = ["keydown", "keypress", "keyup"]; events.forEach((eventType) => { // Override addEventListener to prevent key blocking const originalAddListener = ORIGINAL.addEventListener; document.addEventListener = function (type, listener, options) { if (type === eventType && typeof listener === "function") { const originalListener = listener; listener = function (event) { const key = event.key?.toLowerCase(); const code = event.code?.toLowerCase(); // Allow DevTools keys const isDevToolsKey = key === "f12" || (event.ctrlKey && event.shiftKey && ["i", "j", "c"].includes(key)) || (event.ctrlKey && key === "u"); if (isDevToolsKey) { Logger.debug("Allowing DevTools key:", key); return; // Don't call the original listener } return originalListener.call(this, event); }; } return originalAddListener.call(this, type, listener, options); }; // Also handle window events window.addEventListener = document.addEventListener; }); // Block existing key event listeners by overriding preventDefault const originalPreventDefault = Event.prototype.preventDefault; Event.prototype.preventDefault = function () { const key = this.key?.toLowerCase(); const isDevToolsKey = key === "f12" || (this.ctrlKey && this.shiftKey && ["i", "j", "c"].includes(key)) || (this.ctrlKey && key === "u"); if ( isDevToolsKey && (this.type === "keydown" || this.type === "keypress" || this.type === "keyup") ) { Logger.debug("Prevented preventDefault on DevTools key:", key); return; // Don't prevent default for DevTools keys } return originalPreventDefault.call(this); }; Logger.info("Key blocking prevention enabled"); } // Restore right-click context menu static #restoreRightClick() { // Override contextmenu event blocking const originalAddListener = document.addEventListener; document.addEventListener = function (type, listener, options) { if (type === "contextmenu") { // Replace with a dummy function that doesn't block listener = function (e) { Logger.debug("Context menu allowed"); return true; }; } return originalAddListener.call(this, type, listener, options); }; // Also handle oncontextmenu attribute const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if ( mutation.type === "attributes" && mutation.attributeName === "oncontextmenu" ) { mutation.target.removeAttribute("oncontextmenu"); Logger.debug("Removed oncontextmenu attribute"); } }); }); observer.observe(document.documentElement, { attributes: true, subtree: true, attributeFilter: ["oncontextmenu"], }); Logger.info("Right-click restored"); } // Restore text selection static #restoreTextSelection() { // Override selectstart event blocking const originalAddListener = document.addEventListener; const blockedEvents = ["selectstart", "dragstart", "copy", "cut"]; document.addEventListener = function (type, listener, options) { if (blockedEvents.includes(type)) { listener = function (e) { Logger.debug("Selection/copy event allowed:", type); return true; }; } return originalAddListener.call(this, type, listener, options); }; // Remove CSS that prevents text selection const style = document.createElement("style"); style.textContent = ` *, *::before, *::after { -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; user-select: text !important; } `; document.head.appendChild(style); Logger.info("Text selection restored"); } // Restore console if it was overridden static #restoreConsole() { try { // Check if console was disabled/overridden if (!window.console || typeof window.console.log !== "function") { window.console = ORIGINAL.console; Logger.info("Console restored"); } // Ensure console methods are working Object.keys(ORIGINAL.console).forEach((method) => { if (!console[method] || typeof console[method] !== "function") { console[method] = ORIGINAL.console[method]; } }); // Prevent future console overrides Object.defineProperty(window, "console", { value: window.console, writable: false, configurable: false, }); } catch (e) { Logger.warn("Console restoration failed:", e.message); } } // Prevent timing-based DevTools detection static #preventTimingDetection() { // Add small random delays to timing functions to break detection const addNoise = () => Math.random() * 2; try { Object.defineProperty(Date, "now", { value: () => ORIGINAL.now() + addNoise(), writable: false, configurable: false, }); if (window.performance?.now) { Object.defineProperty(window.performance, "now", { value: () => ORIGINAL.performance() + addNoise(), writable: false, configurable: false, }); } Logger.info("Timing detection prevented"); } catch (e) { Logger.warn("Timing protection failed:", e.message); } } // Neutralize debugger tricks static #neutralizeDebuggerTricks() { // Override toString methods that might be used for detection const safeToString = function () { return this.name ? `function ${this.name}() { [native code] }` : "function() { [native code] }"; }; try { // Protect critical functions from toString inspection window.Function.prototype.toString = safeToString; window.eval.toString = () => "function eval() { [native code] }"; Logger.info("Debugger tricks neutralized"); } catch (e) { Logger.warn("Debugger trick neutralization failed:", e.message); } } // Monitor and clean injected scripts static #patchMutationObserver() { if (!window.MutationObserver) return; try { new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE) { // Clean script content if (node.tagName === "SCRIPT" && node.textContent) { const originalContent = node.textContent; const cleanedContent = CodeNeutralizer.neutralize(originalContent); if (originalContent !== cleanedContent) { node.textContent = cleanedContent; Logger.debug("Cleaned injected script"); } } // Clean event attributes if (node.attributes) { Array.from(node.attributes).forEach((attr) => { if ( attr.name.startsWith("on") || attr.name === "oncontextmenu" ) { const cleaned = CodeNeutralizer.neutralize(attr.value); if ( cleaned !== attr.value || attr.name === "oncontextmenu" ) { node.removeAttribute(attr.name); Logger.debug( "Removed/cleaned event attribute:", attr.name ); } } }); } } }); }); }).observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: [ "onload", "onerror", "onclick", "oncontextmenu", "onkeydown", "onkeyup", ], }); Logger.info("DOM monitoring active"); } catch (e) { Logger.warn("DOM monitoring failed:", e.message); } } // Restore clipboard functionality static #restoreClipboard() { const clipboardEvents = ["copy", "cut", "paste"]; clipboardEvents.forEach((eventType) => { document.addEventListener( eventType, (e) => { // Ensure clipboard events are not blocked e.stopImmediatePropagation(); }, true ); }); Logger.info("Clipboard functionality restored"); } // Prevent error handling overrides that might block DevTools static #preventErrorOverrides() { const originalErrorHandler = window.onerror; window.addEventListener( "error", (e) => { // Don't let websites block error reporting e.stopImmediatePropagation(); }, true ); // Prevent overriding of error handlers Object.defineProperty(window, "onerror", { set: function (handler) { Logger.debug("Prevented error handler override"); }, get: function () { return originalErrorHandler; }, }); Logger.info("Error override prevention active"); } } // Main bypass controller class DevToolsBypass { static init() { try { Logger.info("Starting DevTools protection bypass..."); // Apply all bypasses DevToolsProtectionBypass.apply(); // Clean existing page content this.#cleanExistingContent(); Logger.info("DevTools bypass activated successfully"); // Show success indicator this.#showSuccessIndicator(); } catch (e) { Logger.warn("Bypass initialization failed:", e.message); } } static #cleanExistingContent() { try { // Clean all existing script tags const scripts = document.querySelectorAll("script"); scripts.forEach((script) => { if (script.textContent) { const cleaned = CodeNeutralizer.neutralize(script.textContent); if (cleaned !== script.textContent) { script.textContent = cleaned; Logger.debug("Cleaned existing script"); } } }); // Remove problematic event attributes const elementsWithEvents = document.querySelectorAll( "[oncontextmenu], [onkeydown], [onkeyup], [onselectstart], [ondragstart]" ); elementsWithEvents.forEach((element) => { [ "oncontextmenu", "onkeydown", "onkeyup", "onselectstart", "ondragstart", ].forEach((attr) => { if (element.hasAttribute(attr)) { element.removeAttribute(attr); Logger.debug("Removed event attribute:", attr); } }); }); } catch (e) { Logger.warn("Content cleaning failed:", e.message); } } static #showSuccessIndicator() { if (!CONFIG.logging.enabled) return; // Create a temporary success indicator const indicator = document.createElement("div"); indicator.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #4CAF50; color: white; padding: 10px 20px; border-radius: 5px; z-index: 999999; font-family: Arial, sans-serif; font-size: 14px; box-shadow: 0 2px 10px rgba(0,0,0,0.3); `; indicator.textContent = "✓ DevTools Bypass Active"; document.body?.appendChild(indicator); // Remove after 3 seconds setTimeout(() => { indicator.remove(); }, 3000); } } // Initialize immediately and on various events DevToolsBypass.init(); // Also initialize when DOM is ready (fallback) if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", DevToolsBypass.init); } // Initialize on window load (another fallback) window.addEventListener("load", DevToolsBypass.init); })();