为了防止开发者通过浏览器控制台进行调试、逆向工程或绕过某些限制,一些网站会采用反调试手段。以下是常见的浏览器控制台反调试手段:
无限 debugger
在代码中插入 debugger 语句,当用户打开开发者工具时,代码会不断执行到 debugger 处,从而使调试过程变得异常困难。
            
            
              javascript
              
              
            
          
          setInterval(() => {
    debugger;
}, 100);
        解决方案:
1. 禁用调试器
在浏览器开发者工具中,部分浏览器(如 Chrome)提供了禁用调试器的功能。在 "Sources" 面板中,有一个 "Deactivate breakpoints"(停用断点)的按钮,点击该按钮后,debugger 语句将不再起作用。
或者 选中Debugger 右键禁用
2. 重写函数
可以通过重写 Function.prototype.constructor 来拦截包含 debugger 的代码执行。以下是示例代码:
            
            
              javascript
              
              
            
          
          const originalFunctionConstructor = Function.prototype.constructor;
Function.prototype.constructor = function (arg) {
    if (typeof arg === 'string' && arg.includes('debugger')) {
        return function () {};
    }
    return originalFunctionConstructor.apply(this, arguments);
};
        这段代码重写了 Function.prototype.constructor,当传入的代码字符串包含 debugger 时,返回一个空函数,从而跳过 debugger 语句的执行。
检测开发者工具是否打开
1. 通过 console.log 输出内容的宽度变化检测:
在大多数浏览器中,当开发者工具打开时,console.log 输出内容的宽度会发生变化。可以通过比较正常情况下和当前情况下输出内容的宽度来判断开发者工具是否打开。
            
            
              javascript
              
              
            
          
          (function () {     //自执行函数
    const threshold = 160;
    const test = "test";
    console.log("%c" + test, "font: 1px sans-serif");
    const width = console.log.caller.toString().length;
    if (width > threshold) {
        // 开发者工具已打开,可执行相应操作,如刷新页面
        window.location.reload();
    }
})();
        2. 通过 performance 对象检测:
开发者工具打开时会对浏览器的性能指标产生影响,通过监测 performance 对象的相关属性可以检测开发者工具是否打开。
            
            
              javascript
              
              
            
          
          const start = performance.now();
debugger;
const end = performance.now();
if (end - start > 100) {
    // 开发者工具已打开
    alert('请关闭开发者工具');
}
        解决方案
1. 绕过 console.log 宽度检测
可以通过在浏览器开发者工具的 "Settings"(设置)中,调整控制台的字体大小或布局,使 console.log 输出内容的宽度不受开发者工具打开的影响。
2. 绕过 performance 对象检测
可以通过修改 performance.now() 的返回值来绕过检测。在控制台输入以下代码:
            
            
              javascript
              
              
            
          
          const originalPerformanceNow = performance.now;
performance.now = function () {
    return originalPerformanceNow.call(this) - 200; // 调整差值以绕过检测
};
        这段代码重写了 performance.now 方法,使其返回一个经过调整的值,从而绕过基于 performance 对象的检测。
监听控制台事件
监听控制台的特定事件,当检测到用户在控制台执行某些操作时,执行相应的反调试措施,如刷新页面、跳转到其他页面或禁用某些功能。
            
            
              javascript
              
              
            
          
          window.addEventListener('error', function (event) {
    if (event.message.includes('console')) {
        // 检测到控制台相关错误,可能是用户在控制台操作
        window.location.href = 'https://example.com';
    }
});
        解决方案
1. 阻止事件监听
可以通过移除事件监听器来阻止对控制台事件的监听。首先,需要找到添加事件监听器的代码,然后使用 removeEventListener 方法移除该监听器。例如,如果是通过 window.addEventListener('error', ...) 添加的监听器,可以使用以下代码移除:
            
            
              javascript
              
              
            
          
          const errorHandler = function (event) {
    if (event.message.includes('console')) {
        window.location.href = 'https://example.com';
    }
};
window.removeEventListener('error', errorHandler);
        阻止控制台输入
通过覆盖 console 对象的方法,阻止用户在控制台输入命令。
            
            
              javascript
              
              
            
          
          console.log = function () {};
console.error = function () {};
console.warn = function () {};
        上述代码将 console 对象的 log、error 和 warn 方法覆盖为空函数,这样用户在控制台输入的相关命令将不会产生任何输出。
解决方案
1. 恢复 console 对象方法
可以通过重新定义 console 对象的方法来恢复控制台的输入功能。在控制台输入以下代码:
            
            
              javascript
              
              
            
          
          console.log = window.console.log.bind(window.console);
console.error = window.console.error.bind(window.console);
console.warn = window.console.warn.bind(window.console);
        这段代码将 console 对象的 log、error 和 warn 方法恢复为原始的实现。
需要注意的是,在进行调试时应遵守相关法律法规和网站的使用条款,避免进行非法或违反道德的行为。