- // ==UserScript==
- // @name DevTools Bypass
- // @name:vi Bỏ Qua Chặn DevTools
- // @name:zh-CN 开发工具限制绕过
- // @namespace https://greasyfork.org/vi/users/1195312-renji-yuusei
- // @version 3.0
- // @description Bypass for website restrictions on DevTools with improved protection
- // @description:vi Bỏ qua các hạn chế của trang web về DevTools với bảo vệ được cải tiến
- // @description:zh-CN 绕过网站对开发工具的限制,具有增强的保护功能
- // @author Yuusei
- // @match *://*/*
- // @grant unsafeWindow
- // @run-at document-start
- // @license GPL-3.0-only
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // Add initialization logging
- console.log('[DevTools Bypass] Script initialized at:', new Date().toISOString());
-
- const config = {
- debugPatterns: {
- basic: /;\s*(?:debugger|debug(?:ger)?|breakpoint)\s*;?/g,
- advanced: /(?:debugger|debug(?:ger)?|breakpoint)[\s;]*(?:\{[\s\S]*?\})?/g,
- timing: /performance\.now\(\)|Date\.now\(\)/g,
- eval: /eval\(.*?debugger.*?\)/g
- },
- consoleProps: ['log', 'warn', 'error', 'info', 'debug', 'trace'],
- cutoffs: {
- debugger: { amount: 50, within: 60000 },
- debuggerThrow: { amount: 50, within: 60000 }
- },
- bypassTriggers: {
- timeThreshold: 100,
- stackDepth: 50,
- recursionLimit: 100
- },
- logging: {
- enabled: false,
- prefix: '[DevTools Bypass]',
- levels: ['info', 'warn', 'error']
- }
- };
-
- // Enhanced logging utility
- const logger = {
- info: (...args) => {
- if (config.logging.enabled) {
- console.log(config.logging.prefix, '(INFO)', ...args);
- }
- },
- warn: (...args) => {
- if (config.logging.enabled) {
- console.warn(config.logging.prefix, '(WARN)', ...args);
- }
- },
- error: (...args) => {
- if (config.logging.enabled) {
- console.error(config.logging.prefix, '(ERROR)', ...args);
- }
- }
- };
-
- const originals = {
- defineProperty: Object.defineProperty,
- getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor,
- setTimeout: window.setTimeout,
- setInterval: window.setInterval,
- Date: window.Date,
- now: Date.now,
- performance: window.performance,
- Function: window.Function,
- eval: window.eval,
- console: {},
- toString: Function.prototype.toString,
- preventDefault: Event.prototype.preventDefault,
- getComputedStyle: window.getComputedStyle
- };
-
- config.consoleProps.forEach(prop => {
- if (console[prop]) {
- originals.console[prop] = console[prop].bind(console);
- }
- });
-
- const isDebuggerPresent = () => {
- try {
- const startTime = originals.now.call(Date);
- const testFunc = new Function('debugger;')();
- const timeDiff = originals.now.call(Date) - startTime;
- if (timeDiff > config.bypassTriggers.timeThreshold) {
- logger.warn('Debugger detected! Time difference:', timeDiff, 'ms');
- return true;
- }
- return false;
- } catch (e) {
- logger.error('Error in debugger detection:', e);
- return false;
- }
- };
-
- const analyzeStack = () => {
- try {
- const stack = new Error().stack;
- const frames = stack.split('\n');
- const analysis = {
- depth: frames.length,
- hasDebugKeywords: frames.some(frame =>
- Object.values(config.debugPatterns).some(pattern =>
- pattern.test(frame)
- )
- ),
- isRecursive: new Set(frames).size < frames.length
- };
-
- if (analysis.hasDebugKeywords || analysis.isRecursive) {
- logger.warn('Suspicious stack detected:', analysis);
- }
-
- return analysis;
- } catch (e) {
- logger.error('Error analyzing stack:', e);
- return { depth: 0, hasDebugKeywords: false, isRecursive: false };
- }
- };
-
- const enhancedAntiDebugger = () => {
- try {
- let protectionCount = 0;
-
- const createSafeTimer = (original) => {
- return function(handler, timeout, ...args) {
- if (typeof handler === 'function') {
- const wrappedHandler = function() {
- try {
- return handler.apply(this, arguments);
- } catch (e) {
- if (e.message?.includes('debugger')) {
- logger.info('Caught and bypassed debugger in timer');
- return undefined;
- }
- throw e;
- }
- };
- return original.call(this, wrappedHandler, timeout, ...args);
- }
- return original.apply(this, arguments);
- };
- };
-
- const protectTiming = () => {
- const timeOffset = Math.random() * 10;
- const safeNow = function() {
- return originals.now.call(Date) + timeOffset;
- };
-
- try {
- Object.defineProperty(Date, 'now', {
- value: safeNow,
- configurable: true,
- writable: true
- });
-
- if (window.performance && window.performance.now) {
- Object.defineProperty(window.performance, 'now', {
- value: safeNow,
- configurable: true,
- writable: true
- });
- }
- protectionCount++;
- logger.info('Timing protection applied with offset:', timeOffset);
- } catch (e) {
- logger.error('Failed to protect timing:', e);
- }
- };
-
- const protectFunction = () => {
- const handler = {
- apply(target, thisArg, args) {
- const code = args[0];
- if (typeof code === 'string') {
- let cleanCode = code;
- let detectedPatterns = [];
- Object.entries(config.debugPatterns).forEach(([key, pattern]) => {
- if (pattern.test(code)) {
- detectedPatterns.push(key);
- }
- cleanCode = cleanCode.replace(pattern, '');
- });
-
- if (detectedPatterns.length > 0) {
- logger.warn('Cleaned debug patterns from Function:', detectedPatterns);
- }
-
- args[0] = cleanCode;
- }
- return Reflect.apply(target, thisArg, args);
- },
- construct(target, args) {
- const code = args[0];
- if (typeof code === 'string') {
- let cleanCode = code;
- Object.values(config.debugPatterns).forEach(pattern => {
- cleanCode = cleanCode.replace(pattern, '');
- });
- args[0] = cleanCode;
- }
- return Reflect.construct(target, args);
- }
- };
-
- window.Function = new Proxy(originals.Function, handler);
- if (typeof unsafeWindow !== 'undefined') {
- unsafeWindow.Function = window.Function;
- }
- protectionCount++;
- logger.info('Function protection applied');
- };
-
- const protectStack = () => {
- try {
- const errorHandler = {
- get(target, prop) {
- if (prop === 'stack') {
- const stack = target.stack;
- const cleanedStack = stack.split('\n')
- .filter(line => !Object.values(config.debugPatterns)
- .some(pattern => pattern.test(line)))
- .join('\n');
-
- if (cleanedStack.length !== stack.length) {
- logger.info('Cleaned suspicious stack trace');
- }
-
- return cleanedStack;
- }
- return target[prop];
- }
- };
-
- const errorProtoHandler = {
- get(target, prop) {
- if (prop === 'stack') {
- const error = new Error();
- return new Proxy(error, errorHandler).stack;
- }
- return Reflect.get(target, prop);
- }
- };
-
- Error.prototype = new Proxy(Error.prototype, errorProtoHandler);
- protectionCount++;
- logger.info('Stack protection applied');
- } catch (e) {
- logger.error('Failed to protect stack:', e);
- }
- };
-
- const protectEval = () => {
- const safeEval = function(code) {
- if (typeof code === 'string') {
- let cleanCode = code;
- let detectedPatterns = [];
- Object.entries(config.debugPatterns).forEach(([key, pattern]) => {
- if (pattern.test(code)) {
- detectedPatterns.push(key);
- }
- cleanCode = cleanCode.replace(pattern, '');
- });
-
- if (detectedPatterns.length > 0) {
- logger.warn('Cleaned debug patterns from eval:', detectedPatterns);
- }
-
- return originals.eval.call(this, cleanCode);
- }
- return originals.eval.apply(this, arguments);
- };
-
- try {
- Object.defineProperty(window, 'eval', {
- value: safeEval,
- configurable: true,
- writable: true
- });
- if (typeof unsafeWindow !== 'undefined') {
- unsafeWindow.eval = safeEval;
- }
- protectionCount++;
- logger.info('Eval protection applied');
- } catch (e) {
- logger.error('Failed to protect eval:', e);
- }
- };
-
- const protectConsole = () => {
- const handler = {
- get(target, prop) {
- if (config.consoleProps.includes(prop)) {
- return function(...args) {
- if (!isDebuggerPresent()) {
- return originals.console[prop]?.apply(console, args);
- }
- logger.warn('Console method blocked due to debugger presence:', prop);
- return undefined;
- };
- }
- return target[prop];
- },
- set(target, prop, value) {
- if (config.consoleProps.includes(prop)) {
- logger.warn('Attempted to modify console method:', prop);
- return true;
- }
- target[prop] = value;
- return true;
- }
- };
-
- window.console = new Proxy(console, handler);
- protectionCount++;
- logger.info('Console protection applied');
- };
-
- // Apply all protections
- window.setTimeout = createSafeTimer(originals.setTimeout);
- window.setInterval = createSafeTimer(originals.setInterval);
- protectTiming();
- protectFunction();
- protectStack();
- protectEval();
- protectConsole();
-
- // Enhanced MutationObserver with logging
- const observer = new MutationObserver((mutations) => {
- for (const mutation of mutations) {
- if (mutation.type === 'childList') {
- mutation.addedNodes.forEach((node) => {
- if (node.tagName === 'SCRIPT') {
- const content = node.textContent;
- let detectedPatterns = [];
-
- Object.entries(config.debugPatterns).forEach(([key, pattern]) => {
- if (pattern.test(content)) {
- detectedPatterns.push(key);
- }
- });
-
- if (detectedPatterns.length > 0) {
- logger.warn('Cleaned debug patterns from dynamic script:', detectedPatterns);
- node.textContent = content.replace(
- new RegExp(Object.values(config.debugPatterns)
- .map(p => p.source).join('|'), 'g'),
- ''
- );
- }
- }
- });
- }
- }
- });
-
- observer.observe(document, {
- childList: true,
- subtree: true
- });
-
- logger.info('All protections applied successfully. Total protections:', protectionCount);
-
- } catch (e) {
- logger.error('Critical error in enhancedAntiDebugger:', e);
- }
- };
-
- const init = () => {
- try {
- logger.info('Initializing DevTools bypass...');
- enhancedAntiDebugger();
- logger.info('DevTools bypass initialized successfully');
- } catch (e) {
- logger.error('Failed to initialize DevTools bypass:', e);
- }
- };
-
- // Add status check function
- window._checkDevToolsBypassStatus = () => {
- try {
- const status = {
- initialized: true,
- debuggerPresent: isDebuggerPresent(),
- stackAnalysis: analyzeStack(),
- timestamp: new Date().toISOString()
- };
- logger.info('Status check:', status);
- return status;
- } catch (e) {
- logger.error('Error checking status:', e);
- return { error: e.message };
- }
- };
-
- init();
- })();