无限debugger的原理与绕过

940 阅读3分钟

debugger 是 JavaScript 中定义的一个专门用于断点调试的关键字,只要遇到它,JavaScript 的执行便会在此处中断,进入调试模式。有了 debugger 这个关键字,我们就可以非常方便地对 JavaScript 代码进行调试,比如使用 JavaScript Hook 时,我们可以加入 debugger 关键字,使其在关键的位置停下来,以便查找逆向突破口。但有时候 debugger 会被网站开发者利用,使其成为阻挠我们正常调试的拦路虎。本节中,我们介绍一个案例来绕过无限 debugger。

无限循环debugger实现

利用 Function 产生 debugger,然后通过 setInterval 循环,每秒执行1次产生 debugger 语句的操作。当然,还有很多类似的实现,比如无限 for 循环、无限 while 循环、无限递归调用等,它们都可以实现这样的效果,原理大同小异。

(() => {
  function ban() {
    setInterval(() => {
      debugger;
    }, 50);
  }
  try {
    ban();
  } catch (err) { }
})();

绕过debugger方法

禁用所有断点

全局禁用开关位于 Sources 面板的右上角,叫做 Deactivate breakpoints;点击它,该按钮会被激活,变成蓝色。

这种全局禁用其实并不是一个好的方案,因为禁用之后我们也无法在其他位置增加断点进行调试了,所有的断点都失效了!

禁用局部断点

  1. 在 debugger 语句所在的行的行号上单击鼠标右键,此时会出现一个快捷菜单。
  2. 这里有一个 Never pause here 选项,意思是从不在此处暂停。
  3. 当前断点显示为橙色,并且断点前面多了一个 ? 符号,同时 Breakpoints 也出现了刚才添加的断点位置,这时再次点击 Resume script execution(恢复脚本执行)按钮,就可以发现我们不会再进入无限 debugger 模式了。
  4. 也可以选择另外一个选项 Add conditional breakpoint。
  5. 这个模式更加高级,我们可以设置进入断点的条件,比如在调试过程中,期望某个变量的值大于某个具体的值的时候才停下来。但在本案例中,由于这里是无限循环,我们没有什么具体的变量可以作为判定依据,因此可以直接写一个简单的表达式来控制。选择 Add conditional breakpoint 选项,直接填入 false 然后回车即可。

替换文件

利用 Overrides 面板我们可以将远程的 JavaScript 文件替换成本地的 JavaScript 文件,这里我们依然可以使用这个方法来对文件进行替换。

  1. 打开 Sources 面板下的 Overrides 面板,将修改后的完整 JavaScript 文件复制进去。
  2. 替换完成之后,重新刷新网页,这时候发现不会进入无限 debugger 模式了。

函数置空与hook

一定要在 debugger 进入之前。如:定时器造成的,所以我们可以重写这个函数,使无限 debugger 失效。

// 这里是业务代码和setInterval无关,所以直接置空即可
setInterval = function(){} //定时器置空,置空之后上面的无限debugger消失
function xxx(){} //执行函数置空 xxx

改写JavaScript文件

  1. 我们可以在 Overrides 面板上选定一个本地的文件夹,用于保存需要更改的 JavaScript 文件。
  2. 切到 Overrides 面板,点击 + 按钮。
  3. 这时候浏览器会提示我们选择一个本地文件夹,用于存储要替换的 JavaScript 文件。
  4. 直接替换 JavaScript 文件的所有内容即可。
  5. 替换完毕之后 ctrl + s 保存,这时候再切换回 Overrides 面板,就可以发现成功生成了新的 JavaScript 文件,它用于替换原有的 JavaScript 文件。