Leave-debugger

用于破解网页无限debugger,支持多种调试方式拦截

// ==UserScript==
// @name         Leave-debugger
// @namespace    https://github.com/SherryBX/Leave-debugger
// @version      v2.2.0
// @description  用于破解网页无限debugger,支持多种调试方式拦截
// @author       Sherry
// @match        *://*/*
// @include      *://*/*
// @run-at       document-start
// @license      MIT
// @icon         https://mms0.baidu.com/it/u=2886239489,318124131&fm=253&app=138&f=JPEG?w=800&h=800
// ==/UserScript==

(function () {
    'use strict';

    // 配置项
    const CONFIG = {
        version: 'v2.2.0',
        debugMode: false, // 调试模式开关
        checkPatterns: ['debugger', 'debug', 'DevTools'], // 检查的关键字模式
    };

    // 统一的日志输出
    const Logger = {
        styles: {
            main: 'color: #43bb88; font-size: 14px; font-weight: bold;',
            info: 'color: #666; font-size: 12px;',
            hook: 'color: #43bb88;'
        },
        print(message, style = 'main') {
            console.log(`%c ${message}`, this.styles[style]);
        },
        debug(...args) {
            if (CONFIG.debugMode) {
                console.log('[Debug]', ...args);
            }
        }
    };

    // Hook 状态管理
    const HookManager = {
        notified: new Set(),
        markNotified(type) {
            if (!this.notified.has(type)) {
                this.notified.add(type);
                Logger.print(`🎯 Hook ${type} debugger!`, 'hook');
            }
        }
    };

    // 工具函数
    const Utils = {
        // 安全地检查函数字符串
        safeToString(func) {
            try {
                const str = Function.prototype.toString.call(func);
                return typeof str === 'string' ? str.replace(/\s+/g, '') : '';
            } catch (e) {
                Logger.debug('toString error:', e);
                return '';
            }
        },
        // 检查是否包含调试相关代码
        containsDebugger(content) {
            if (!content) return false;
            return CONFIG.checkPatterns.some(pattern => content.includes(pattern));
        },
        // 创建空函数
        createEmptyFunction() {
            return function () { return -1; };
        }
    };

    // Hook 实现
    const Hooks = {
        // Hook Function constructor
        hookConstructor() {
            const original = Function.prototype.constructor;
            Function.prototype.constructor = function (string) {
                if (Utils.containsDebugger(string)) {
                    HookManager.markNotified('constructor');
                    return Utils.createEmptyFunction();
                }
                return original.apply(this, arguments);
            };
        },

        // Hook setInterval
        hookSetInterval() {
            const original = window.setInterval;
            window.setInterval = function (func, delay) {
                if (typeof func === 'function' && Utils.containsDebugger(Utils.safeToString(func))) {
                    HookManager.markNotified('setInterval');
                    return Utils.createEmptyFunction();
                }
                return original.apply(this, arguments);
            };
        },

        // Hook setTimeout
        hookSetTimeout() {
            const original = window.setTimeout;
            window.setTimeout = function (func, delay) {
                if (typeof func === 'function' && Utils.containsDebugger(Utils.safeToString(func))) {
                    HookManager.markNotified('setTimeout');
                    return Utils.createEmptyFunction();
                }
                return original.apply(this, arguments);
            };
        },

        // Hook eval
        hookEval() {
            const original = window.eval;
            window.eval = function (string) {
                if (Utils.containsDebugger(string)) {
                    HookManager.markNotified('eval');
                    string = string.replace(/debugger\s*;?/g, '');
                }
                return original.call(this, string);
            };
            // 保持 toString 的原始行为
            Object.defineProperty(window.eval, 'toString', {
                value: function() { return original.toString(); },
                configurable: false,
                writable: false
            });
        }
    };

    // 错误处理
    const ErrorHandler = {
        setup() {
            window.addEventListener('error', function (event) {
                if (event.error?.message?.includes('Cannot read properties') ||
                    event.error?.message?.includes('Cannot set property')) {
                    event.preventDefault();
                    Logger.debug('Prevented error:', event.error.message);
                    return false;
                }
            }, true);
        }
    };

    // 初始化
    function initialize() {
        Logger.print('Leave-debugger 已启动 🚀');
        Logger.print(`Version: ${CONFIG.version} 📦`, 'info');
        Logger.print('Author: Sherry 🛡️', 'info');

        // 应用所有 hooks
        Object.values(Hooks).forEach(hook => {
            try {
                hook();
            } catch (e) {
                Logger.debug('Hook error:', e);
            }
        });

        // 设置错误处理
        ErrorHandler.setup();
    }

    // 启动脚本
    initialize();
})();