您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
绕过网站对开发工具的限制,具有增强的保护功能
当前为
// ==UserScript== // @name DevTools Bypass // @name:vi Bỏ Qua Chặn DevTools // @name:zh-CN 开发工具限制绕过 // @name:ru Разблокировка DevTools // @namespace https://greasyfork.org/vi/users/1195312-renji-yuusei // @version 3.3 // @description Bypass for website restrictions on DevTools with enhanced protection // @description:vi Bỏ qua các hạn chế của trang web về DevTools với bảo vệ nâng cao // @description:zh-CN 绕过网站对开发工具的限制,具有增强的保护功能 // @description:ru Разблокировка DevTools с усиленной защитой // @author Yuusei // @match *://*/* // @grant unsafeWindow // @run-at document-start // @license GPL-3.0-only // ==/UserScript== (function() { 'use strict'; const CONSTANTS = { PREFIX: '[DevTools Bypass]', LOG_LEVELS: { INFO: 'info', WARN: 'warn', ERROR: 'error', DEBUG: 'debug' }, TIME_THRESHOLDS: { DEBUGGER: 80, CACHE: 30000 } }; const config = { debugPatterns: { basic: /;\s*(?:debugger|debug(?:ger)?|breakpoint)\s*;?/gi, advanced: /(?:debugger|debug(?:ger)?|breakpoint)[\s;]*(?:\{[\s\S]*?\})?/gi, timing: /(?:performance|Date)\.now\(\)|new\s+Date(?:\(\))?\.getTime\(\)/gi, eval: /eval\(.*?(?:debugger|debug|breakpoint).*?\)/gi, devtools: /(?:isDevTools|devtools|debugMode|debug_mode)\s*[=:]\s*(?:true|1)/gi, consoleCheck: /console\.[a-zA-Z]+\s*\(.*?\)/gi, functionDebug: /function.*?\{[\s\S]*?debugger[\s\S]*?\}/gi, sourceMap: /\/\/[#@]\s*source(?:Mapping)?URL=.*?$/gm }, consoleProps: ['log', 'warn', 'error', 'info', 'debug', 'trace', 'dir', 'dirxml', 'table', 'profile'], cutoffs: { debugger: { amount: 30, within: CONSTANTS.TIME_THRESHOLDS.CACHE }, debuggerThrow: { amount: 30, within: CONSTANTS.TIME_THRESHOLDS.CACHE } }, bypassTriggers: { timeThreshold: CONSTANTS.TIME_THRESHOLDS.DEBUGGER, stackDepth: 40, recursionLimit: 80 }, logging: { enabled: true, prefix: CONSTANTS.PREFIX, levels: Object.values(CONSTANTS.LOG_LEVELS), detailedErrors: true }, protection: { preventDevToolsKeys: true, hideStackTraces: true, sanitizeErrors: true, obfuscateTimers: true } }; class Logger { static #instance; #lastLog = 0; #logCount = 0; constructor() { if (Logger.#instance) { return Logger.#instance; } Logger.#instance = this; } #shouldLog() { const now = Date.now(); if (now - this.#lastLog > 1000) { this.#logCount = 0; } this.#lastLog = now; return ++this.#logCount <= 10; } #log(level, ...args) { if (!config.logging.enabled || !this.#shouldLog()) return; const timestamp = new Date().toISOString(); console[level]( config.logging.prefix, `[${timestamp}]`, `(${level.toUpperCase()})`, ...args ); } info(...args) { this.#log(CONSTANTS.LOG_LEVELS.INFO, ...args); } warn(...args) { this.#log(CONSTANTS.LOG_LEVELS.WARN, ...args); } error(...args) { this.#log(CONSTANTS.LOG_LEVELS.ERROR, ...args); if (config.logging.detailedErrors) { console.trace('Error stack trace:'); } } debug(...args) { this.#log(CONSTANTS.LOG_LEVELS.DEBUG, ...args); } } const logger = new Logger(); class OriginalFunctions { static defineProperty = Object.defineProperty; static getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; static setTimeout = window.setTimeout; static setInterval = window.setInterval; static Date = window.Date; static now = Date.now; static performance = window.performance; static Function = window.Function; static eval = window.eval; static console = {}; static toString = Function.prototype.toString; static preventDefault = Event.prototype.preventDefault; static getComputedStyle = window.getComputedStyle; static addEventListener = window.addEventListener; static removeEventListener = window.removeEventListener; static initConsole() { config.consoleProps.forEach(prop => { if (console[prop]) { this.console[prop] = console[prop].bind(console); } }); } } OriginalFunctions.initConsole(); class DebuggerDetector { static #detectionCache = new Map(); static isPresent() { try { const cacheKey = 'debugger_check'; const cached = this.#detectionCache.get(cacheKey); if (cached && Date.now() - cached.timestamp < 1000) { return cached.result; } const startTime = OriginalFunctions.now.call(Date); new Function('debugger;')(); const timeDiff = OriginalFunctions.now.call(Date) - startTime; const result = timeDiff > config.bypassTriggers.timeThreshold; this.#detectionCache.set(cacheKey, { result, timestamp: Date.now() }); if (result) { logger.warn('Debugger detected:', timeDiff, 'ms'); } return result; } catch (e) { logger.error('Debugger detection error:', e); return false; } } static analyzeStack() { try { const stack = new Error().stack; const frames = stack.split('\n'); const uniqueFrames = new Set(frames); const analysis = { depth: frames.length, hasDebugKeywords: frames.some(frame => Object.values(config.debugPatterns).some(pattern => pattern.test(frame) ) ), isRecursive: uniqueFrames.size < frames.length, suspiciousPatterns: this.#detectSuspiciousPatterns(stack) }; if (analysis.hasDebugKeywords || analysis.isRecursive) { logger.warn('Suspicious stack detected:', analysis); } return analysis; } catch (e) { logger.error('Stack analysis error:', e); return { depth: 0, hasDebugKeywords: false, isRecursive: false, suspiciousPatterns: [] }; } } static #detectSuspiciousPatterns(stack) { const patterns = [ /eval.*?\(/g, /Function.*?\(/g, /debugger/g, /debug/g ]; return patterns .map(pattern => pattern.test(stack)) .filter(Boolean); } } class Protection { static applyAll() { this.#protectTimers(); this.#protectTiming(); this.#protectFunction(); this.#protectStack(); this.#protectEval(); this.#protectConsole(); this.#setupMutationObserver(); this.#protectDevToolsKeys(); } static #protectTimers() { const wrapTimer = (original) => { return function(handler, timeout, ...args) { if (typeof handler !== 'function') return original.apply(this, arguments); const wrappedHandler = function() { try { if (DebuggerDetector.isPresent()) { logger.warn('Timer execution blocked due to debugger'); return; } return handler.apply(this, arguments); } catch (e) { if (e.message?.includes('debugger')) { logger.info('Timer debugger bypassed'); return; } throw e; } }; if (config.protection.obfuscateTimers) { timeout = Math.max(1, timeout + Math.random() * 10 - 5); } return original.call(this, wrappedHandler, timeout, ...args); }; }; window.setTimeout = wrapTimer(OriginalFunctions.setTimeout); window.setInterval = wrapTimer(OriginalFunctions.setInterval); } static #protectTiming() { const timeOffset = Math.random() * 15; const safeNow = () => OriginalFunctions.now.call(Date) + timeOffset; Object.defineProperty(Date, 'now', { value: safeNow, configurable: true, writable: true }); if (window.performance?.now) { Object.defineProperty(window.performance, 'now', { value: safeNow, configurable: true, writable: true }); } } static #protectFunction() { const handler = { apply(target, thisArg, args) { if (typeof args[0] === 'string') { args[0] = Protection.#cleanCode(args[0]); } return Reflect.apply(target, thisArg, args); }, construct(target, args) { if (typeof args[0] === 'string') { args[0] = Protection.#cleanCode(args[0]); } return Reflect.construct(target, args); } }; window.Function = new Proxy(OriginalFunctions.Function, handler); if (typeof unsafeWindow !== 'undefined') { unsafeWindow.Function = window.Function; } } static #protectStack() { if (!config.protection.hideStackTraces) return; const errorHandler = { get(target, prop) { if (prop === 'stack') { const stack = target.stack; return Protection.#cleanCode(stack); } return target[prop]; } }; const originalErrorPrototype = Error.prototype; const proxyErrorPrototype = Object.create(originalErrorPrototype); Object.defineProperty(proxyErrorPrototype, 'stack', { get() { const error = new Error(); return Protection.#cleanCode(error.stack); }, configurable: true }); try { Error.prototype = proxyErrorPrototype; } catch (e) { logger.warn('Failed to modify Error.prototype:', e); } } static #protectEval() { const safeEval = function(code) { if (typeof code === 'string') { if (DebuggerDetector.isPresent()) { logger.warn('Eval blocked due to debugger'); return; } return OriginalFunctions.eval.call(this, Protection.#cleanCode(code)); } return OriginalFunctions.eval.apply(this, arguments); }; Object.defineProperty(window, 'eval', { value: safeEval, configurable: true, writable: true }); if (typeof unsafeWindow !== 'undefined') { unsafeWindow.eval = safeEval; } } static #protectConsole() { const consoleHandler = { get(target, prop) { if (!config.consoleProps.includes(prop)) return target[prop]; return function(...args) { if (DebuggerDetector.isPresent()) { logger.warn('Console blocked:', prop); return; } return OriginalFunctions.console[prop]?.apply(console, args); }; }, set(target, prop, value) { if (config.consoleProps.includes(prop)) { logger.warn('Console modification blocked:', prop); return true; } target[prop] = value; return true; } }; window.console = new Proxy(console, consoleHandler); } static #setupMutationObserver() { new MutationObserver((mutations) => { mutations.forEach(mutation => { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.tagName === 'SCRIPT') { const originalContent = node.textContent; const cleanedContent = Protection.#cleanCode(originalContent); if (originalContent !== cleanedContent) { node.textContent = cleanedContent; logger.info('Cleaned script content'); } } }); } }); }).observe(document, { childList: true, subtree: true }); } static #protectDevToolsKeys() { if (!config.protection.preventDevToolsKeys) return; const handler = (e) => { const { keyCode, ctrlKey, shiftKey } = e; if ( (keyCode === 123) || // F12 (ctrlKey && shiftKey && keyCode === 73) || // Ctrl+Shift+I (ctrlKey && shiftKey && keyCode === 74) || // Ctrl+Shift+J (ctrlKey && keyCode === 85) // Ctrl+U ) { e.preventDefault(); logger.warn('DevTools hotkey blocked'); } }; window.addEventListener('keydown', handler, true); } static #cleanCode(code) { if (typeof code !== 'string') return code; let cleanCode = code; Object.entries(config.debugPatterns).forEach(([key, pattern]) => { if (pattern.test(code)) { logger.warn(`Cleaned ${key} pattern`); cleanCode = cleanCode.replace(pattern, ''); } }); return cleanCode; } } class DevToolsBypass { static init() { try { logger.info('Initializing DevTools Bypass...'); Protection.applyAll(); logger.info('Initialization complete'); } catch (e) { logger.error('Initialization failed:', e); } } static checkStatus() { return { initialized: true, debuggerPresent: DebuggerDetector.isPresent(), stackAnalysis: DebuggerDetector.analyzeStack(), timestamp: new Date().toISOString(), version: '3.3' }; } } window._checkDevToolsBypassStatus = DevToolsBypass.checkStatus; DevToolsBypass.init(); })();