常见反调试

常见反调试

1. 开发者工具反调试

1.1 阻止打开开发者工具

打开开发者工具一般是通过快捷键或鼠标右键打开,所以这里禁用调试就会从这两个地方下手:

1)禁用鼠标右键

  • 效果

    点击鼠标右键就出现提示,并且无法显示右键内容:

    image-20240617210559171

  • 代码实现

    // 监听鼠标右键事件,防止调试工具被使用
    document.oncontextmenu = () => {
        alert('检测到非法调试,右键被管理员禁用');
        return false;
    }
    

    document.oncontextmenu 表示监听鼠标右键;

    return false 表示禁止后续事件操作。

2)禁用 F12

  • 效果

    点击 F12 不出控制台,出提示:

    image-20240617210927681

  • 代码实现

    // 监听键盘按键事件,防止调试工具被使用
    document.onkeydown = () => {
        // 键盘监听事件对象
        var e = window.event || arguments[0];
        // 检测按键是否是 F12
        if (e.keyCode == 123) {
            alert("检测到非法调试,F12被管理员禁用");
            // 阻止事件继续执行
            return false;
        }
    }
    

    123 在按键中表示 F12

解决方案

控制台打开的几种方式:

  1. F12

  2. ctrl+shif+i

  3. 鼠标右键 -》检查

  4. “三点” -》更多工具 -》开发者工具

    image-20240617211413072

多了解几种打开的方式,这种不能用就换另一种。

注意:

并不是所有的检测到后都给提示,有的会直接跳转到其他地方,或者做其他操作。例如:

document.onkeydown = () => {
    var e = window.event || arguments[0];
    if (e.keyCode == 123) {
        // alert("检测到非法调试,F12被管理员禁用");
        // 跳转到百度
        window.location.href = "https://www.baidu.com";
        return false;
    }
}

当按下 F12 的时候,就会跳转到百度首页。

1.2 窗口检测

窗口检测一般检测的是内外窗口的尺寸,这个时候一般是在控制台打开之后的。检测后的常见操作:

  1. 清空控制台
  2. 跳转页面
  3. 假数据替换

不论是那种,都是检测到后执行,后面的检测基本也是做这些操作。

  • 效果

    控制台清空,每秒钟控制台都会强制清空,如果要在控制台调试,前面的值都会看不到。

    image-20240617212923215

  • 实现代码

    // 设置定时器
    setInterval(
        // 定时器执行的操作
        function () {
            // 检测浏览器外窗口尺寸和内窗口尺寸的差值   单位 像素
            if (window.outerWidth - window.innerWidth > 300 || window.outerHeight - window.innerHeight > 300) {
                // 清除控制台
                console.clear()
            }
        },
        // 定时执行的时间,每多久执行一次 ms
        500
    );
    

    这里主要用到了:

    1. 定时器:setInterval(定时任务函数,定时时间)

    2. 内外窗口尺寸检测

    如果想实现其他效果,可以自己替换清空控制台那里的代码。

  • 解决方案

    控制台悬浮出来:点击控制台右侧三点,停靠测 部分选择第一个

    image-20240617213047881

    控制台悬浮出来后,是不会占据浏览器窗口位置的,就不会被检测出异常差异。

1.3 格式化检测

格式化检测主要检测函数的压缩格式和格式化的格式:

  • 格式化函数

    var test = function () {
        return '666';
    }
    
  • 压缩格式函数

    var test = function (){return '666';}
    

    实现代码:

    // 格式化检测
    var test = function (){return '666';}
    
    // 设置定时器每秒检测一次函数是否被格式化
    setInterval(function () {
        // 定义正则表达式来匹配格式化后的函数
        var reg = new RegExp("\\w+ \\(\\){\\w+ ['|\"].+['|\"];}");
        // 匹配到了,结果返回 true
        var isFormatted = reg.test(test.toString());
    
        if (!isFormatted) {
            console.log("函数被格式化");
        }
    }, 1000);
    

    实现格式化检测,主要依赖于两个:

    1. 正则表达式:匹配符合条件的格式,reg.test 表示检测是否有符合条件的字符串,有则返回 true
    2. toString() 方法:打印函数的格式

一般格式化检测会和内存爆破结合一起使用。

内存爆破

内存爆破在调试的时候有一个明显的状态,即浏览器所消耗的内存不正常的增加,浏览器会卡死。

实现内存爆破的方式也挺简单,即无限循环的做某件事情。

例如:

// 内存爆破
var test = function () {
    return '666';
}

function dbf() {
    let memoryLeak = [];
    // 每隔10毫秒就向数组中添加一个大的对象
    setInterval(() => {
        let obj = {};
        // 给对象添加大量属性,以增加其占用的内存
        for (let i = 0; i < 500000; i++) {
            obj['key' + i] = Math.random();
        }
        memoryLeak.push(obj);

        // 可选:输出当前数组长度,以监控内存泄漏
        console.log(memoryLeak.length);
    }, 1);
}

2. 无限debugger

2.1 构建 debugger 的方式

  1. debugger 关键字

    debugger;
    

    debugger 是 js 的关键字,写在哪就可以在哪设置断点。

  2. eval

    eval("debugger");
    

    eval 函数可以将字符串当做代码执行,也就是说你在字符串中写运算,最后得到的也是运算后的值,而不是加法运算的字符串。

    1. Function
    Function("debugger")();
    

    Function 是 js 中的一个内置对象,可以用来创建函数。比如:

    var myFunction = new Function('a', 'b', 'return a + b;');
    

    这个函数名称是 myFunction,参数是 a、b,函数体是 return a + b;

    而上面构建 debugger,则是创建了一个匿名函数,并且调用了。

    上面构建 debugger 代码类似的还有:

    (function () {}["constructor"]("debugger")());
    
  • function () {} 是一个匿名函数

  • ["constructor"] 调用函数的构造函数,这里指向的就是 Function 了

    所以上面代码等价 Function("debugger")()

知道怎么构建 debugger 了,加上个无限就简单了。一般无限不是循环就是定时器,根据情况处理。

2.2 如何过 debugger

  1. 右键点击 debugger 处,点击永不在此处暂停

    image-20240618142204819

  2. hook

    hook 就是所谓的钩子函数,你们怎么理解的就怎么表达吧!

    以定时器实现的无限 debugger 为例:

    // 定时器实现无限 debugger
    setInterval(function () {
        debugger;
    }, 500);
    

    这种会在每 0.5S 就进入 debugger,根本无法正常调试。使用第一种方式可以过,但是如果类似的 debugger 比较多,就需要处理定时器而不是 debugger 了。

    处理方式 - 在进入断点之前,修改掉原来的定时器方法,让它失去定时器的功能:

    • 效果

      hook-定时器

    • 实现代码

      var _setInterval = setInterval;
      setInterval = function () {
          console.log("修改定时器");
          return function(){};
      }
      
posted @ 2025-09-17 20:50  笔锋微凉~~  阅读(263)  评论(0)    收藏  举报