MST

星途 面试题库

面试题:JavaScript 代码保护与反调试技术

在 JavaScript 代码保护中,反调试是重要一环。请阐述至少两种在 JavaScript 中实现反调试的技术原理,并编写相应代码示例。例如,如何检测调试器是否附着,以及当检测到调试器时采取何种措施来阻止调试(如使代码进入死循环、抛出难以理解的错误等,但需考虑在正常运行时不影响程序功能)。同时分析这些技术可能存在的局限性和绕过方法。
37.1万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

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 的时间间隔保持正常。