1. 使用 debugger
关键字检测并阻止调试
- 技术原理:在代码中插入
debugger
关键字,当调试器附着时,执行到该关键字会暂停。我们可以利用 try - catch
捕获异常来检测是否因调试器附着而触发了 debugger
。如果捕获到异常,可采取阻止调试的措施。
- 代码示例:
try {
debugger;
console.log('正常执行');
} catch (e) {
// 这里表示调试器被触发,采取阻止调试措施
throw new Error('调试被检测到,程序终止');
}
- 局限性和绕过方法:
- 局限性:现代浏览器的调试工具越来越智能,一些高级调试工具可以忽略
debugger
关键字。
- 绕过方法:在调试工具中设置忽略
debugger
语句,或通过代理脚本在运行前移除 debugger
关键字。
2. 通过 performance.now()
检测调试器
- 技术原理:当调试器附着时,JavaScript 执行会暂停,
performance.now()
获取的时间戳会出现异常变化。通过记录代码执行的时间间隔,如果时间间隔过长,可能表明调试器附着。
- 代码示例:
let startTime = performance.now();
// 执行一段耗时较短的代码
for (let i = 0; i < 1000000; i++);
let endTime = performance.now();
// 如果时间间隔超过一定阈值,认为调试器附着
if (endTime - startTime > 100) {
throw new Error('检测到调试器,程序终止');
}
- 局限性和绕过方法:
- 局限性:时间阈值难以精确设定,不同机器性能不同,正常执行也可能出现时间间隔较长的情况,导致误判。
- 绕过方法:在调试时通过优化调试环境,使代码执行时间尽可能接近正常执行时间,或者修改
performance.now()
的实现,使其返回固定值。
3. 利用 setInterval
检测
- 技术原理:正常情况下
setInterval
会按照设定的时间间隔周期性执行回调函数。当调试器附着时,JavaScript 执行暂停,setInterval
的执行会受到影响,导致回调函数执行间隔异常。
- 代码示例:
let lastTime = Date.now();
const interval = setInterval(() => {
let currentTime = Date.now();
if (currentTime - lastTime > 100) {
clearInterval(interval);
throw new Error('检测到调试器,程序终止');
}
lastTime = currentTime;
}, 50);
- 局限性和绕过方法:
- 局限性:与
performance.now()
类似,时间阈值不好确定,容易误判。而且有些调试工具可以模拟正常的 setInterval
执行,避免时间间隔异常。
- 绕过方法:使用高级调试工具模拟正常执行环境,使
setInterval
的时间间隔保持正常。