// ==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();
})();