前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >网页调试之debugger原理与绕过

网页调试之debugger原理与绕过

作者头像
PayneWu
发布2021-07-16 15:31:29
6.8K0
发布2021-07-16 15:31:29
举报
文章被收录于专栏:积跬Coder积跬Coder积跬Coder

当我们调试JS的时候,时常会遇见无限debugger。无限debugger的原理是什么呢?它在何时触发?如何绕过?

debugger 语句用于停止执行 JavaScript(以下简称JS),并调用 (如果可用) 调试函数。

使用 debugger 语句类似于在代码中设置断点。

注意: 如果调试工具不可用,则调试语句将无法工作。

实现debugger功能

直接使用书写debugger
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Example DEBUGGER</title>
</head>

<body>
    <script>
        debugger;
    </script>
</body>

</html>

当我们使用浏览器打开Devtools即执行debugger;如下图所示

eval配合debugger

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。 如果参数是一个表达式,eval() 函数将执行表达式。如果参数是Javascript语句,eval()将执行 Javascript 语句。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Example DEBUGGER</title>
</head>

<body>
    <script>
        var a = 1;
        eval("var 1 = 1;debugger")
    </script>
</body>

</html>

当使用eval执行时,将会在虚拟机中执行,也就是说非同一作用域。 同时也由于将字符串当作表达式来执行,那么里面常常伴随着代码混淆

函数内执行debugger
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Example DEBUGGER</title>
</head>

<body>
    <script>
        (function a(){
            var data = Date();
            alert(data);
            debugger;
        }())
    </script>
</body>

</html>

因为以上三种体现形式,在debugger上所设计的方案十分多。例如常见的无限制debugger、配合settimeout延迟debugger、代码混淆+debugger等等。

设置debugger的原理去对抗反爬,其核心原理就是如果调试工具可用,则调试语句将执行.也就是经常一打开就跳出debugger。

无限debugger,其实是一种泛指的概念,无限泛指多,而非真的无限 其基于debugger之上,在此加入多次执行debugger的语句从而实现“无限debugger”。“反正只要chrome Devtools不开debugger便不会执行”.(经过调试是这样的,如果不准确请自行完善哦)

debugger绕过原理

debugger的绕过也很简单,我个人总结共有两种大的方向。它们分别是替换、掠过。其原理都是不让debugger执行。个人并不推荐新手使用替换法中的方法

  • 替换法
  • JS注入
  • 重写(Hook)
  • 掠过法
  • Never pause here
  • 条件断点
JS注入

实现js注入的方式有很多,例如chrome Devtools的overrides、fiddler autoresponse、 mitmproxy、Charles的map local等等。若有兴趣自行搜索其使用方式

Never pause here

找到debugger前面的行号,鼠标右键点击该行号,点击Never pause here。便会跳过此断点

条件断点

找到debugger前面的行号,鼠标右键点击该行号,点击 Add conditional breakpoint,直接写false。回车即可

Deactivate breakpoints

打开这个图标如下图所示(高亮为打开)

当遇见breakpoints时会执行一次断点,鼠标单击如下图标

即可直接跳过breakpoints。

小技巧:Deactivate breakpoints可以配合xhr、dom、Script等断点使用,便于调试

Hook绕过
function a() {
    eval("debugger");
}
(function() {
    var eval_cache = eval;
    eval = function(obj) {
        if (obj.indexof('debugger') === -1) {
            eval_cache(obj);
        }
    }
}())

此方法有局限性,若在此函数(在这里指函数a)若没有借用相关函数(eval),那么就无法使用此方法绕过

函数滞空法

当遇见断点时,回退一次堆栈。将对应函数滞空即可,例如遇见如下的debugger

function a() {
  debugger;
    eval("debugger");
}

直接在控制台输入如下内容即可。

此方法有局限性,若在此函数中还参杂了关键代码,将可能无法访问或调试等

总结

Debugger绕过其实并不难,但在调试中仅仅是一道“开胃菜”,本节总结了debugger的实现方式,以及触发机制。当然也总结了几种我已知的所有绕过方案。

展望

如何hook“变量”debugger?如果可以实现那么就可以实现反调试的debugger“通杀”,当然目前我也有在探究此方案。在加到hook函数中,那么调试便可以近似于一步到位。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 积跬Coder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现debugger功能
    • 直接使用书写debugger
      • eval配合debugger
        • 函数内执行debugger
        • debugger绕过原理
          • JS注入
            • Never pause here
              • 条件断点
                • Deactivate breakpoints
                  • Hook绕过
                    • 函数滞空法
                    • 总结
                      • 展望
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档