示例

https://www.yijianjiexi.com/

调试的时候会发现一直在debugger

找到上层函数

_0x5eb719(0x144)丢到控制台运行,得到stateObject,把_0x5eb719(0x169)丢到控制台运行,得到apply ,把_0x5eb719(0x101) + _0x5eb719(0x11b)丢到控制台运行,得到debugger

所以这段代码的逻辑

1
2
3
4
5
6
7
else
('' + _0x1814be / _0x1814be)[_0x5eb719(0x167)] !== 0x1 || _0x1814be % 0x14 === 0x0 ? function() {
return !![];
}['constructor'](_0x5eb719(0x101) + _0x5eb719(0x11b))['call'](_0x5eb719(0x129))
: function() {
return ![];
}['constructor'](_0x5eb719(0x101) + _0x5eb719(0x11b))[_0x5eb719(0x169)](_0x5eb719(0x144));

有一个问号的条件判断,然后根据条件去执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//function() {
// return ![];
//}['constructor']
// 上面的写法相当于new Function(...)
function() {
return ![];
}['constructor'](_0x5eb719(0x101) + _0x5eb719(0x11b))[_0x5eb719(0x169)](_0x5eb719(0x144));
//也就是
function() {
return ![];
}['constructor']('debugger')['apply']('stateObject');
//也就是相当于一个匿名函数,函数体就是debugger,然后apply调用,参数是'stateObject'
//参数是什么不重要,最后都会执行debugger,加上循环就是无限debugger
//把下面的代码放到浏览器直接运行也会断在debugger的位置
(function (){
debugger;
})('stateObject')

常见debugger的几种方式

1
2
3
4
5
6
7
8
9
10
11
12
debugger;
eval("debugger");
eval("(function() {var a = new Date(); debugger; return new Date() - a > 100;}())");

Function("debugger").call()
Function("debugger").apply()
Function("debugger").bind()
Function.constructor("debugger").call("action")
funObj.constructor("debugger").call("action")
(function() {return !![];}["constructor"]("debugger")["call"]("action"))
eval('(function() {}["constructor"]("debugger")["call"]("action"));')
setInterval(function (){debugger;}, 1000);

无限debugger的绕过

条件断点

下条件断点,让debugger代码处的条件永远为false,在目标代码行右键,add conditional breakpoint,这种方法不一定有用,针对上面那种在vm中断下来的没用

替换js代码

使用开发者工具的overriders功能,替换js代码,sources面板的左上角pages右侧的箭头,点击overrides,但是这种方法也不方便,debugger的地方有很多

Hook Function构造函数

1
2
3
4
5
6
7
8
9
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);
}

Hook eval

1
2
3
4
5
6
7
var _eval = eval;
eval = function(arg) {
if(arg.indexOf('debugger') != -1){
return function(){}
}
return _eval(arg);
}

Hook setInterval

1
2
3
4
5
6
7
8
9
setInterval = function(){}; //将调用debugger的上层函数置空也可以,前提是setInterval和业务逻辑无关

_setInterval = setInterval;
setInterval = function(a,b) {
if(a.toString().indexOf('debugger') != -1){
return null;
}
return _setInterval(a,b);
}