1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/E8o0aM若失效,可用地址
阿里云:
服务器购买地址
https://t.aliyun.com/U/E8o0aM若失效,可用地址
https://www.aliyun.com/daily-act/ecs/activity_selection?source=5176.29345612&userCode=49hts92d腾讯云:
https://curl.qcloud.com/wJpWmSfU若失效,可用地址
https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console华为云
https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=2019052.部署教程
3.代码如下
(function() {'use strict';console.log('%c[ANTI-DEBUG] 🛡️ Anti-Debugger Script Loading...', 'background: blue; color: white; font-size: 14px; font-weight: bold');// ==================== ANTI-DEBUGGER CORE ====================const antiDebuggerScript = `(function() {// Save originals immediatelyconst _eval = window.eval;const _Function = window.Function;const _setTimeout = window.setTimeout;const _setInterval = window.setInterval;const _constructor = window.constructor;// Try to disable debugger keyword (check if it's configurable first)try {const descriptor = Object.getOwnPropertyDescriptor(window, 'debugger');if (!descriptor || descriptor.configurable !== false) {Object.defineProperty(window, 'debugger', {get: function() { return undefined; },set: function() { return false; },configurable: false});}} catch(e) {console.log('[ANTI-DEBUG] Cannot redefine debugger:', e.message);}// Override eval to remove debuggerwindow.eval = new Proxy(_eval, {apply: function(target, thisArg, args) {let code = args[0];if (typeof code === 'string') {// Remove all debugger statementscode = code.replace(/\\bdebugger\\b/gi, '');// Remove infinite loops with debuggercode = code.replace(/while\\s*\\(.*?\\)\\s*{[^}]*debugger[^}]*}/gi, '');code = code.replace(/for\\s*\\(.*?\\)\\s*{[^}]*debugger[^}]*}/gi, '');args[0] = code;}return Reflect.apply(target, thisArg, args);}});// Override Function constructorwindow.Function = new Proxy(_Function, {construct: function(target, args) {// Clean last argument (function body)if (args.length > 0) {let body = args[args.length - 1];if (typeof body === 'string') {body = body.replace(/\\bdebugger\\b/gi, '');args[args.length - 1] = body;}}return Reflect.construct(target, args);},apply: function(target, thisArg, args) {// Clean last argument (function body)if (args.length > 0) {let body = args[args.length - 1];if (typeof body === 'string') {body = body.replace(/\\bdebugger\\b/gi, '');args[args.length - 1] = body;}}return Reflect.apply(target, thisArg, args);}});// Override timers to block debugger loopslet blockedTimers = new Set();window.setTimeout = new Proxy(_setTimeout, {apply: function(target, thisArg, args) {const [callback, delay, ...rest] = args;// Check if callback contains debuggerlet callbackStr = '';if (typeof callback === 'function') {callbackStr = callback.toString();} else if (typeof callback === 'string') {callbackStr = callback;}// Block if contains debuggerif (callbackStr.includes('debugger') ||callbackStr.includes('constructor("debugger")') ||callbackStr.includes('Function("debugger")') ||callbackStr.includes('constructor.constructor')) {const fakeId = Math.random() * 1000000;blockedTimers.add(fakeId);console.log('[ANTI-DEBUG] Blocked setTimeout with debugger');return fakeId;}return Reflect.apply(target, thisArg, args);}});window.setInterval = new Proxy(_setInterval, {apply: function(target, thisArg, args) {const [callback, delay, ...rest] = args;// Check if callback contains debuggerlet callbackStr = '';if (typeof callback === 'function') {callbackStr = callback.toString();} else if (typeof callback === 'string') {callbackStr = callback;}// Block if contains debuggerif (callbackStr.includes('debugger') ||callbackStr.includes('constructor("debugger")') ||callbackStr.includes('Function("debugger")') ||callbackStr.includes('constructor.constructor')) {const fakeId = Math.random() * 1000000;blockedTimers.add(fakeId);console.log('[ANTI-DEBUG] Blocked setInterval with debugger');return fakeId;}return Reflect.apply(target, thisArg, args);}});// Override clearInterval and clearTimeout for fake IDsconst _clearInterval = window.clearInterval;const _clearTimeout = window.clearTimeout;window.clearInterval = function(id) {if (!blockedTimers.has(id)) {return _clearInterval(id);}blockedTimers.delete(id);};window.clearTimeout = function(id) {if (!blockedTimers.has(id)) {return _clearTimeout(id);}blockedTimers.delete(id);};// Block constructor.constructor patternconst OriginalFunction = Function;Function.prototype.constructor = new Proxy(Function.prototype.constructor, {apply: function(target, thisArg, args) {if (args[0] && args[0].includes && args[0].includes('debugger')) {console.log('[ANTI-DEBUG] Blocked constructor.constructor debugger');return function() {};}return Reflect.apply(target, thisArg, args);},construct: function(target, args) {if (args[0] && args[0].includes && args[0].includes('debugger')) {console.log('[ANTI-DEBUG] Blocked constructor.constructor debugger');return function() {};}return Reflect.construct(target, args);}});// Prevent console.clearconst _clear = console.clear;console.clear = function() {console.log('[ANTI-DEBUG] Console.clear blocked');};console.log('%c[ANTI-DEBUG] 🛡️ Protection active!', 'background: green; color: white; font-weight: bold');})();`;// ==================== INJECTION MECHANISM ====================// Inject immediatelyconst injectAntiDebugger = () => {const script = document.createElement('script');script.textContent = antiDebuggerScript;// Try all possible injection pointsconst targets = [document.documentElement,document.head,document.body];for (const target of targets) {if (target) {target.insertBefore(script, target.firstChild);console.log('[ANTI-DEBUG] Anti-debugger injected to:', target.tagName);break;}}};// Inject as early as possibleinjectAntiDebugger();// Also inject when DOM is readyif (document.readyState === 'loading') {document.addEventListener('DOMContentLoaded', injectAntiDebugger);}// ==================== VISUAL INDICATOR ====================setTimeout(() => {// Add status bannerconst banner = document.createElement('div');banner.innerHTML = '🛡️ ANTI-DEBUGGER ACTIVE';banner.style.cssText = `position: fixed;top: 0;left: 0;right: 0;background: linear-gradient(90deg, #FF6B6B, #4ECDC4);color: white;padding: 8px;text-align: center;z-index: 999999;font-weight: bold;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;font-size: 14px;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);`;if (document.body) {document.body.appendChild(banner);// Auto-hide after 5 secondssetTimeout(() => {banner.style.transition = 'opacity 0.5s ease';banner.style.opacity = '0';setTimeout(() => banner.remove(), 500);}, 5000);}// Add floating indicatorconst indicator = document.createElement('div');indicator.innerHTML = '🛡️';indicator.title = 'Anti-Debugger Active';indicator.style.cssText = `position: fixed;bottom: 20px;left: 20px;width: 50px;height: 50px;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);border-radius: 50%;display: flex;align-items: center;justify-content: center;font-size: 24px;z-index: 999998;box-shadow: 0 4px 20px rgba(102, 126, 234, 0.5);animation: shieldPulse 2s infinite;`;if (document.body) {document.body.appendChild(indicator);}}, 1000);// Add animationGM_addStyle(`@keyframes shieldPulse {0% { transform: scale(1); opacity: 1; }50% { transform: scale(1.05); opacity: 0.8; }100% { transform: scale(1); opacity: 1; }}`);console.log('%c[ANTI-DEBUG] 🛡️ Anti-Debugger Script Loaded Successfully', 'background: green; color: white; font-size: 16px; font-weight: bold');})();
该脚本为网球馆自动预约脚本(https://wxsports.ydmap.cn)。
主要实现原理
元信息(
@run-at document-start/@match/@grant等)
在元头中声明尽早执行(document-start)并指定生效域名,目的是尽可能在页面脚本运行前把保护注入进页面环境。组装字符串化的保护脚本(
antiDebuggerScript)
把要注入的保护逻辑以字符串形式准备好——实际执行体就是该字符串被插入到页面并立即执行的代码。注入机制(
injectAntiDebugger)
创建一个<script>元素,把antiDebuggerScript放进去,然后尽早将其插入documentElement/head/body的最前面,保证脚本在页面其它脚本之前或尽早运行。覆盖 / 代理标准函数和构造器
覆盖
eval(在执行字符串代码前把字符串中的debugger等片段做文本替换或清除,从源头减少debugger语句生效的机会。覆盖
Function构造器(在通过new Function(...)动态创建函数时清理函数体中的debugger关键字。修改
Function.prototype.constructor的行为(检测通过constructor.constructor/类似链式调用生成带debugger的代码并阻止。
这些覆盖的目的是拦截页面通过动态代码字符串或构造器植入的调试触发器。拦截/过滤定时器(
setTimeout/setInterval)
在定时器回调提交前检查回调函数(或字符串)中是否包含明显的调试片段(如debugger、constructor("debugger")等),若检测到则阻止注册并返回伪造的定时器 ID。并且重写clearTimeout/clearInterval来兼容这些伪造 ID。目的是阻止通过定时器持续触发的调试/自检循环。尝试屏蔽
debugger关键字对象
通过Object.defineProperty(window, 'debugger', ...)的尝试,企图让window.debugger变为不可用或无害(注意:debugger是语言关键字,实际重定义效果取决于环境与浏览器)。阻断
console.clear
覆盖console.clear,避免页面脚本在控制台被清空时干扰开发者观察或清除日志痕迹。注入视觉提示(banner + 浮动图标)
在页面加载后添加一个短暂显示的顶部 banner 和一个固定的浮动图标,用于提示"Anti-Debugger Active"(视觉反馈,非功能性保护)。双重注入保障
脚本既在立刻执行时注入一次,也在 DOMContentLoaded 时再尝试注入一次,意在提高在不同加载时序下成功注入的概率。
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
没有评论:
发表评论