Anti Anti-debugger

Advanced protection against anti-debugging with improved performance and features. Attempts to fix video playback issues.

נכון ליום 09-10-2024. ראה הגרסה האחרונה.

// ==UserScript==
// @name         Anti Anti-debugger 
// @name:vi      Chống Anti-debugger 
// @name:zh-CN   反反调试
// @namespace    https://gf.zukizuki.org/vi/users/1195312-renji-yuusei
// @version      1.5
// @description  Advanced protection against anti-debugging with improved performance and features. Attempts to fix video playback issues.
// @description:vi Bảo vệ nâng cao chống anti-debugging với hiệu suất và tính năng được cải thiện. Cố gắng sửa lỗi phát lại video.
// @description:zh-CN 高级反反调试保护,具有改进的性能和功能。 尝试修复视频播放问题。
// @author       Yuusei
// @match        *://*/*
// @grant        unsafeWindow
// @run-at       document-start
// @license      GPL-3.0-only
// ==/UserScript==

(function() {
    'use strict';

    const config = {
        debugKeywords: /;\s*(?:debugger|debug(?:ger)?|breakpoint)\s*;?/g, // Use regex for efficiency
        consoleProps: ['log', 'warn', 'error', 'info', 'debug', 'assert', 'dir', 'dirxml', 'trace', 'group', 'groupCollapsed', 'groupEnd', 'time', 'timeEnd', 'profile', 'profileEnd', 'count'],
        maxLogHistory: 100,
        whitelist: /^(?:example\.com|another-site\.net)$/, // Use regex for whitelist
    };

    const originalConsole = console; // No need for Object.fromEntries

    const logHistory = [];

    const safeEval = (code) => { // Removed unused context
        try {
            return Function(`return (${code})()`)(); // Simpler and potentially faster
        } catch (error) {
            originalConsole.error('Failed to evaluate code:', error, code);
            return null;
        }
    };

    const modifyFunction = (func) => {
        if (typeof func !== 'function') return func;

        const funcStr = func.toString();
        if (config.debugKeywords.test(funcStr)) {
            const modifiedStr = funcStr.replace(config.debugKeywords, ';/* removed */');
            try {
                return safeEval(modifiedStr);
            } catch (e) {
                originalConsole.error("Error modifying function:", e);
                return func;
            }
        }
        return func;
    };

    const wrapConsole = () => {
        config.consoleProps.forEach(prop => {
            const original = originalConsole[prop];
            console[prop] = (...args) => {
                original.apply(originalConsole, args); // Use apply for correct context
                logHistory.push(`[${prop.toUpperCase()}] ${args.map(formatLogArgument).join(' ')}`);
                if (logHistory.length > config.maxLogHistory) logHistory.shift();
            };
        });
    };

    const antiAntiDebugger = () => {
        const handler = {
            apply(target, thisArg, args) {
                return Reflect.apply(target, thisArg, args.map(modifyFunction));
            },
            construct(target, args) {
                return Reflect.construct(target, args.map(modifyFunction));
            }
        };

        unsafeWindow.eval = new Proxy(unsafeWindow.eval, handler);
        unsafeWindow.Function = new Proxy(unsafeWindow.Function, handler);
    };

    const preventDebugging = () => {
        if (config.whitelist.test(window.location.host)) return; // Use regex for whitelist check

        const noop = () => {};
        ['alert', 'confirm', 'prompt'].forEach(prop => {
            try {
                Object.defineProperty(unsafeWindow, prop, { value: noop, writable: false, configurable: false });
            } catch (e) {
                originalConsole.error("Error overriding ", prop, ":", e);
            }
        });

        try { // Restore video playback
            Object.defineProperty(HTMLMediaElement.prototype, 'play', {
                value: HTMLMediaElement.prototype.play,
                writable: true,
                configurable: true
            });
        } catch (error) {
            originalConsole.error("Error restoring HTMLMediaElement.play:", error);
        }
    };


    const formatLogArgument = (arg) => {
        if (arg == null) return String(arg); // Simplified null/undefined check
        if (typeof arg === 'object') {
            try {
                return JSON.stringify(arg, null, 2); // Removed replacer function for simplicity
            } catch {
                return '[Circular]';
            }
        }
        return String(arg);
    };


    if (!config.whitelist.test(window.location.host)) { // Moved whitelist check to top level
        wrapConsole();
        antiAntiDebugger();
    }
    preventDebugging();

    console.log('%cAnti Anti-debugger is active', 'color: #00ff00; font-weight: bold;');
})();