- // ==UserScript==
- // @name Anti Anti-debugger
- // @name:vi Chống Anti-debugger
- // @name:zh-CN 反反调试
- // @namespace https://greasyfork.org/vi/users/1195312-renji-yuusei
- // @version 1.1
- // @description Stops most anti-debugging implementations by JavaScript obfuscators and stops the console logs from being automatically cleared. Fixed issue with missing console tab.
- // @description:vi Ngăn chặn hầu hết các triển khai anti-debugging bằng JavaScript obfuscators và ngăn chặn việc xóa nhật ký console tự động. Đã sửa lỗi mất tab console.
- // @description:zh-CN 阻止大多数 JavaScript 混淆器实现的反调试,并阻止控制台日志被自动清除。修复了控制台标签丢失的问题。
- // @author Yuusei
- // @match *://*/*
- // @grant unsafeWindow
- // @grant GM_setValue
- // @grant GM_getValue
- // @run-at document-start
- // @license GPL-3.0-only
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- const config = {
- excludedDomains: ['vidstream.pro', 'mcloud.to'],
- debugKeywords: ['debugger', 'debug', 'debugging', 'breakpoint'],
- consoleProps: ['log', 'warn', 'error', 'info', 'debug', 'assert', 'dir', 'dirxml', 'trace', 'group', 'groupCollapsed', 'groupEnd', 'time', 'timeEnd', 'profile', 'profileEnd', 'count'],
- enabled: true, // Can be toggled at runtime
- };
-
- // Load user settings
- const loadSettings = () => {
- config.enabled = GM_getValue('antiAntiDebuggerEnabled', true);
- config.excludedDomains = GM_getValue('excludedDomains', config.excludedDomains);
- };
-
- loadSettings();
-
- const isExcludedDomain = () => config.excludedDomains.some(domain =>
- new RegExp(`(^|\.)${domain.replace(/\./g, '\\.')}$`, 'i').test(location.hostname)
- );
-
- if (isExcludedDomain()) return;
-
- const safeEval = (code, context = {}) => {
- const safeContext = { ...context, console: { log: () => {} } };
- const safeCode = `
- 'use strict';
- const alert = () => {};
- const confirm = () => {};
- const prompt = () => {};
- ${Object.keys(safeContext).map(key => `const ${key} = this.${key};`).join('\n')}
- return (${code});
- `;
- try {
- return new Function(safeCode).call(safeContext);
- } catch (error) {
- console.warn('Failed to evaluate code:', error);
- return null;
- }
- };
-
- const modifyFunction = (func) => {
- if (typeof func !== 'function') return func;
-
- let funcStr = func.toString();
- if (config.debugKeywords.some(keyword => funcStr.includes(keyword))) {
- funcStr = funcStr.replace(new RegExp(`\\b(${config.debugKeywords.join('|')})\\b`, 'g'), '/* removed */');
- return safeEval(funcStr) || func;
- }
- return func;
- };
-
- const wrapConsole = () => {
- const originalConsole = { ...console };
- const consoleProxy = new Proxy(originalConsole, {
- get: (target, prop) => {
- if (config.consoleProps.includes(prop) && typeof target[prop] === 'function') {
- return new Proxy(target[prop], {
- apply: (targetFunc, thisArg, args) => {
- if (!config.enabled) return Reflect.apply(targetFunc, thisArg, args);
- args = args.map(modifyFunction);
- return Reflect.apply(targetFunc, thisArg, args);
- }
- });
- }
- return Reflect.get(target, prop);
- }
- });
-
- Object.defineProperty(unsafeWindow, 'console', {
- value: consoleProxy,
- writable: false,
- configurable: false
- });
- };
-
- const antiAntiDebugger = () => {
- const proxyHandler = {
- apply: (target, thisArg, args) => {
- if (!config.enabled) return Reflect.apply(target, thisArg, args);
- args = args.map(modifyFunction);
- return Reflect.apply(target, thisArg, args);
- },
- construct: (target, args) => {
- if (!config.enabled) return Reflect.construct(target, args);
- args = args.map(modifyFunction);
- return Reflect.construct(target, args);
- }
- };
-
- Function.prototype.constructor = new Proxy(Function.prototype.constructor, proxyHandler);
-
- // Protect eval and Function constructor
- unsafeWindow.eval = new Proxy(unsafeWindow.eval, proxyHandler);
- unsafeWindow.Function = new Proxy(unsafeWindow.Function, proxyHandler);
- };
-
- const preventDebugging = () => {
- const noop = () => {};
- const protectedProps = [...config.debugKeywords, 'pause', 'alert', 'confirm', 'prompt'];
-
- protectedProps.forEach(prop => {
- if (prop !== 'debugger') { // Exclude 'debugger' to prevent issues
- Object.defineProperty(unsafeWindow, prop, {
- get: () => config.enabled ? noop : unsafeWindow[prop],
- set: () => {},
- configurable: false
- });
- }
- });
-
- // Override common debugging-related Date methods
- const originalDate = unsafeWindow.Date;
- unsafeWindow.Date = new Proxy(originalDate, {
- construct: (target, args) => {
- const date = new target(...args);
- date.getTime = new Proxy(date.getTime, {
- apply: (target, thisArg, args) => {
- if (config.enabled && new Error().stack.includes('debugger')) {
- return 0; // Return a fake timestamp
- }
- return Reflect.apply(target, thisArg, args);
- }
- });
- return date;
- }
- });
- };
-
- const setupToggleShortcut = () => {
- document.addEventListener('keydown', (e) => {
- if (e.ctrlKey && e.shiftKey && e.key === 'D') {
- config.enabled = !config.enabled;
- GM_setValue('antiAntiDebuggerEnabled', config.enabled);
- console.log(`Anti Anti-debugger ${config.enabled ? 'enabled' : 'disabled'}`);
- }
- });
- };
-
- wrapConsole();
- antiAntiDebugger();
- preventDebugging();
- setupToggleShortcut();
-
- console.log('Anti Anti-debugger is active');
- })();