
无限debugger
更新: 2025/2/24 字数: 0 字 时长: 0 分钟
在前面一节的实战当中,有一道题目,打开开发者工具就自动进入了 debugger 状态,当我们点击继续运行后,它永远的跳转到下一个 debugger 那去,其原因是网站在网站代码中添加 debugger 调试代码,当进入网站打开开发者工具后就会频繁的去执行 debugger 逻辑,目的就是为了阻断爬虫工程师的调试,这样的反爬方式就称之为“无限debugger”。
实现原理
**虽然“无限debugger”名字中带有“无限”两个字,但是无限 debugger 不可能无限,否则浏览器会卡死。简单说,就是很频繁的去执行 debugger 逻辑,而不是真正的死循环。**实现 debugger 的方法有很多,例如关键字、eval
制作虚拟机、Function
函数等:
// 不可混淆
debugger;
// 可混淆
eval("debugger;")
// 可重度混淆
Function("debugger").call()/apply()或赋值bind()
XXX.constructor("debugger").call("action")
Function.constructor("debugger").call("action")
(function() {return !![];}["constructor"]("debugger")["call"]("action"))
任何可以循环的代码都可以实现无限 debugger,例如使用 setInterval
定时器来实现一个每 0.5 秒触发的无限 debugger:
<!-- 每0.5秒触发的无限debugger -->
<script>
function a(){
debugger;
}
setInterval(a, 500);
</script>
绕过方案
无限 debugger 一般出现在加密逻辑之前,因此想要通过调试找到函数入口,必须绕过无限 debugger。
覆盖替换
覆盖替换,用 Chrome 的 overrides
替换源 JS 文件,修改 debugger
关键字,或者用 Fiddler 等工具替换 Autoresponse 中 debugger
关键字。
无视跳过
无视跳过,遇到 debugger,可以在对应行的左侧右键点击选择 Nerver pause here
永远不停留这里来过掉,不过这样的处理方式方式只能处理小部分“无限 debugger”。
条件断点
条件断点,在 debugger
所在行设置断点,点击鼠标右键蓝色断点位置,选择 Edit breakpoint
选项编辑断点:
输入条件为 false
属性:
保存后断点变黄:
代码注入
代码注入,针对真动态文件或 Autoresponse 失效或删掉 debugger 逻辑很繁琐的情况下。
通过
Function
关键字启动的debugger
,可以注入以下代码重写函数构造器:javascript(()=>{ Function.prototype.__constructor = Function; Function = function (){ if (arguments && typeof arguments[0] === 'string'){ if ("debugger" === arguments[0]){ return } return Function.apply(this, arguments); } } })()
通过
constructor
关键字启动的debugger
,可以注入代码进行绕过:javascript(()=>{ Function.prototype.__constructor = Function.prototype.constructor; Function.prototype.constructor = function (){ if (arguments && typeof arguments[0] === 'string'){ if ("debugger" === arguments[0]){ return } return Function.prototype.constructor.apply(this, arguments); } } })()
通过
eval
函数启动的debugger
,可以注入以下代码重构eval
函数:javascripteval_bc = eval eval = function(a) { if (a === '(function() {var a = new Date(); debugger; return new Date() - a > 100;}())') {} else { return eval_bc(a) } }
通过
setInterval
定时器启动的debugger
,可以替换setInterval
或者清除定时器,在该函数被调用前重写该函数并生效:javascriptsetInterval_back = setInterval // 只要定时器里面的参数不包含了'debugger'就执行 setInterval = function(a, b){ if(a.toString().indexOf('debugger') == -1){ return setInterval_back(a, b) } } // 如果业务代码里面是不重要的代码,我们也可以直接置空它 setInterval = function(){}