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=201905
2.部署教程
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 immediately
const _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 debugger
window.eval = new Proxy(_eval, {
apply: function(target, thisArg, args) {
let code = args[0];
if (typeof code === 'string') {
// Remove all debugger statements
code = code.replace(/\\bdebugger\\b/gi, '');
// Remove infinite loops with debugger
code = 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 constructor
window.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 loops
let blockedTimers = new Set();
window.setTimeout = new Proxy(_setTimeout, {
apply: function(target, thisArg, args) {
const [callback, delay, ...rest] = args;
// Check if callback contains debugger
let callbackStr = '';
if (typeof callback === 'function') {
callbackStr = callback.toString();
} else if (typeof callback === 'string') {
callbackStr = callback;
}
// Block if contains debugger
if (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 debugger
let callbackStr = '';
if (typeof callback === 'function') {
callbackStr = callback.toString();
} else if (typeof callback === 'string') {
callbackStr = callback;
}
// Block if contains debugger
if (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 IDs
const _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 pattern
const 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.clear
const _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 immediately
const injectAntiDebugger = () => {
const script = document.createElement('script');
script.textContent = antiDebuggerScript;
// Try all possible injection points
const 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 possible
injectAntiDebugger();
// Also inject when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', injectAntiDebugger);
}
// ==================== VISUAL INDICATOR ====================
setTimeout(() => {
// Add status banner
const 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 seconds
setTimeout(() => {
banner.style.transition = 'opacity 0.5s ease';
banner.style.opacity = '0';
setTimeout(() => banner.remove(), 500);
}, 5000);
}
// Add floating indicator
const 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 animation
GM_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 时再尝试注入一次,意在提高在不同加载时序下成功注入的概率。
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
没有评论:
发表评论