浏览器魔改-调试就被发现如何永久破? (1)

<aside> 😀 这里写文章的前言: 一个简单的开头,简述这篇文章讨论的问题、目标、人物、背景是什么?并简述你给出的答案。

可以说说你的故事:阻碍、努力、结果成果,意外与转折。

</aside>

📝 主旨内容

检测原理解构

  1. 核心检测函数 catchCDP(e)
function catchCDP(e) {
   if (e.chrome) {  // 仅在Chrome浏览器中执行
      var rng1 = 0;
      var rng2 = 1;
      var acc = rng1;  // 累加器初始值为0
      var result = false;
      
      try {
         var errObj = new e.Error();  // 创建Error对象
         
         // 关键:重新定义stack属性的getter
         var propertyDesc = {
            configurable: false,
            enumerable: false,
            get: function () {
               acc += rng2;  // 每次访问stack时累加1
               return '';
            }
         };
         Object.defineProperty(errObj, "stack", propertyDesc);
         
         console.debug(errObj);  // 输出到控制台
         errObj.stack;           // 手动访问stack属性
         
         // 检查累加器是否发生了预期外的变化
         if (rng1 + rng2 != acc) {
            result = true;  // CDP被检测到
         }
      } catch {
         // 异常处理
      }
      return result;
   }
}

检测机制的工作流程

第一阶段:属性劫持设置

  1. 创建Error对象new e.Error()
  2. 重写stack属性:使用Object.defineProperty定义自定义getter
  3. 累加器机制:每次stack被访问,acc值增加1

第二阶段:触发检测

  1. console.debug(errObj):将Error对象输出到控制台
  2. errObj.stack:主动访问一次stack属性

第三阶段:结果判断

// 正常情况:acc = 0 + 1 = 1 (只有手动访问的一次)
// CDP开启时:acc = 0 + 1 + 1 = 2 (console.debug额外触发了一次)

if (rng1 + rng2 != acc) {  // if (0 + 1 != acc)
   result = true;  // 如果acc不等于1,说明CDP已开启
}

为什么这种方法有效

1. console.debug的特殊行为

当开发者工具未打开时: