彻底解决前端无限debugger

查看 140|回复 12
作者:0xsdeo   
0x00 前言
在很久之前我发过一篇JS逆向系列14-Bypass Debugger,但是这篇文章写的还是不太全,我决定在本篇文章中一次性将所有可能遇到的情况都写出来,具体请看下文。
注:本文不涉及修改chrome内核绕过debugger。
0x01 正文
实现前端无限debugger的三种核心方式为:
1. eval
2. Function
3. Function.prototype.constructor
当然除了上面这三种方法外,也有别的方法可以实现,例如下面这种定时器:


1756025843534.png (211.5 KB, 下载次数: 5)
下载附件
2025-8-27 00:11 上传

图上的代码使用了setTimeout定时每0.05秒调用一次debuggerProtection方法,方法内部有个debugger,通过这种方式就能引起无限debugger。
这种显式的将debugger写到前端代码里用来实现无限debugger的方法我称之为显式无限debugger,这种是可以直接绕过的。我提供了三种解决方案供大家参考:
[ol]
  • 条件断点
  • 替换
  • hook
    [/ol]
    前两个我都在之前的文章中讲过,现在我将那些内容搬到这篇文章中重新讲一遍。首先讲一下如何实现条件断点:右键执行debugger的那行代码的左侧,点击添加条件断点:


    1756044841964.png (313.66 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:12 上传

    条件设置为false:


    1756044856203.png (99.09 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:12 上传



    1756044940931.png (165.83 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:12 上传

    现在这个debugger就不会生效了,但是这东西只能生效一次,意思就是你刷新网站之后这个条件断点就没了,所以这时候就可以考虑使用替换或者hook的方式进行绕过,下面我继续讲一下该如何进行替换。
    F12打开devtools后,点击源代码,左上方有一些板块:


    1756222888512.png (93 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:12 上传

    展开点击替换:


    1756204067564.png (79.95 KB, 下载次数: 3)
    下载附件
    2025-8-27 00:12 上传



    1756204079888.png (50.1 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:13 上传

    点击上面的选择放置替换项的文件夹,选择一个存放替换后的js文件的文件夹,并点击允许:


    1756045573316.png (316.03 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:13 上传



    1756204110187.png (37.17 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:13 上传

    此时回到js中,找到执行debugger的位置:


    1756045702437.png (187.27 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:13 上传



    1756045725636.png (146.58 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:13 上传

    右键点击替换内容:


    1756045755005.png (201.51 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:14 上传

    此时删去debugger:


    1756045780701.png (214.24 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:14 上传

    然后再ctrl+s保存即可:


    1756204140640.png (418.24 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:14 上传

    文件名左边没有*号就代表已经保存成功了,此时刷新就会加载我们替换过的JS:


    1756046507850.png (208.31 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:14 上传

    现在就不会再有debugger的干扰了。
    这里我强调一下替换的两个注意事项:
    [ol]
  • 替换js后需要开着f12访问网站才会执行替换后的js,否则加载的还是原本服务端的js。
  • 如果发现修改后网站依然没有我们想要的效果,此时可以在替换后的js打个断点,检验一下网站是否加载的是我们替换后的js。
    [/ol]
    针对第二点我可以举个例子,例如下面这种情况:


    1756168251692.png (20.42 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:14 上传

    可以看到目标网站的js文件名后都加了一个时间戳,这个时间戳是会影响到我们替换js的,例如我现在替换一下adb文件,删除该文件的debugger字段并重新进入网站:


    1756168376178.png (198.82 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:14 上传

    可见网站并没有加载我们替换的js,依然弹出了debugger,原因很简单,就是因为网站导入js时往文件名后面加了个时间戳:


    1756168471323.png (15.31 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:15 上传

    这就导致替换的js与刷新网站后加载的js文件名不一致,导致替换不成功。解决这种问题很简单,那就是删除new Date().getTime():


    1756168600372.png (24.61 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:15 上传

    现在加载的js就不会带时间戳:


    1756168627602.png (131.17 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:15 上传

    替换的时候就没问题了:


    1756220994204.png (230.59 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:15 上传

    成功加载了我们替换后的js。
    我在上面还提供了一个方案,那就是hook,首先hook肯定能解决使用setTimeout引起无限debugger的问题,但是我这里就不提供相关hook脚本了,主要是因为我对hook setTimeout不太放心,有些开发者可能会利用此类方法去实现动画渲染或者其他用处,所以我担心hook此类方法后会造成不必要的异常,并且解决此类无限debugger也很简单,所以我在这里也就不提供相关代码了。
    讲完使用定时器引起无限debugger的解决方案后,现在我就来讲讲如何绕过我文章中最开始所说的那三种引起无限debugger的核心方式(目前市面上的主流方式),首先可以直接使用我的插件----AntiDebug_Breaker:


    1756169318665.png (181.43 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:15 上传

    github地址:https://github.com/0xsdeo/AntiDebug_Breaker,该脚本可以绕过大部分存在无限debugger的网站,但是在某些网站可能会出现异常,例如下面这种情况:


    1756221140038.png (551.25 KB, 下载次数: 6)
    下载附件
    2025-8-27 00:16 上传

    像这种出现一大堆异常的只有一种原因,那就是因为eval的作用域问题,如有兴趣的读者朋友们可以去看一下我这篇文章:JS逆向系列15-深入探究Hook eval后存在的作用域问题,首先我先说明一下,这个问题无解,如果有人能解出,那么从代码层面上就能彻底解决无限debugger的问题了,但至少从我目前的视角来看,这种语法限制的问题绝对是解决不了的,至少我解决不了,所以如果遇到这种情况可以先开启下面这个设置:


    1756221220212.png (70.55 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:16 上传



    1756170038369.png (95.43 KB, 下载次数: 5)
    下载附件
    2025-8-27 00:16 上传

    开启这个设置后就能彻底忽略掉由eval引起的无限debugger(注:此时必须将插件开启的绕过无限debugger的脚本关闭),并且经实测,该选项也可忽略由Function实例的代码:


    1756170873360.png (122.41 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:16 上传

    没有引起任何debugger,所以开启这个选项即可绕过我上述所说的那三种核心方式引起的无限debugger。
    其实我这一年来一直都在致力于实现无感绕过无限debugger,之所以这样做是因为我在上文并没有提到的一个原因,那就是有些在vm中的代码也很重要,如果直接忽略掉来自eval和Function的匿名脚本,可能会影响到我们正常逆向,所以如果我们遇到了eval的作用域问题,不一定非要开启上面那个设置,也可以考虑使用下面这段备用脚本:


    1756209421760.png (445.97 KB, 下载次数: 4)
    下载附件
    2025-8-27 00:16 上传

    github地址:https://github.com/0xsdeo/Hook_JS/blob/main/hook_debugger/Bypass_Debugger/Bypass_Debugger(%E5%A4%87%E7%94%A8).js,这段脚本只hook了Function和Function.prototype.constructor,没有hook eval,也就是说如果目标网站是由eval引起的无限debugger就没办法了,但是这样能过滤掉由Function和constructor引起的无限debugger,所以需要读者朋友们自行判断。
    0x02 总结
    [table]
    [tr]
    [td]类型[/td]
    [td]特征[/td]
    [td]解决方案[/td]
    [/tr]
    [tr]
    [td]显式无限debugger

    下载次数, 下载附件

  • 0xsdeo
    OP
      

    彻底解决的方案应该是把debugger关键词改掉,然后重新编译chromium(笑)
    0xsdeo
    OP
      


    jettang 发表于 2025-8-28 20:41
    膜拜一下大佬,偷偷说一句,我们好像是群友

    哈哈哈哈那很有缘了师傅!!
    0xsdeo
    OP
      


    jqrtaisk 发表于 2025-8-28 09:10
    这样也可以.

    这样就调试不了啦师傅哈哈哈~
    linac005   


    青衫桑 发表于 2025-8-27 10:46
    如果debugger是字符串拼接的,就不能用你的脚本绕过了

    您好师傅,首先这个问题本身就是错误的,我可以向您举个例子,例如eval("debu"+"gger");,eval里进行了一个字符串拼接,当这个字符串传进eval里时会先进行字符串拼接,然后再传进去,所以传进去的内容依然是debugger,debugger是一个关键字,最终进入eval或Function里的必然是一整个字符串,所以说我的脚本不可能绕不过这种情况。
    天轩科技   

    学习了,厉害厉害
    laozhang4201   

    好贴。!!JS逆向必会的知识
    mxd1wg   

    讲得真细致。好心人。
    fanqie8   

    又可以学到一招
    默默伤心   

    明文情况下直接用 charles 替换掉也是可以的
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部