这一篇主要是研究一下这个混淆器的反调试功能,并找到对应的解决办法。
源代码:
// Paste your JavaScript code here
function hi() {
console.log("Hello World!");
}
hi();
反调试,这个跟源代码没什么关系,就用自带的代码就行。
1.调试选项[Debug Protection]
混淆选项:
只选这一个,其他的都不选,生成的混淆代码:
function hi() {
var _0xc89b72 = function () {
var _0x56f7f3 = !![];
return function (_0x506ee0, _0x2ca148) {
var _0x5d9580 = _0x56f7f3 ? function () {
if (_0x2ca148) {
var _0x47065a = _0x2ca148['apply'](_0x506ee0, arguments);
_0x2ca148 = null;
return _0x47065a;
}
} : function () {
};
_0x56f7f3 = ![];
return _0x5d9580;
};
}();
(function () {
_0xc89b72(this, function () {
var _0x1962eb = new RegExp('function\x20*\x5c(\x20*\x5c)');
var _0x5cff30 = new RegExp('\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)', 'i');
var _0x21c51c = SnktC('init');
if (!_0x1962eb['test'](_0x21c51c + 'chain') || !_0x5cff30['test'](_0x21c51c + 'input')) {
_0x21c51c('0');
} else {
SnktC();
}
})();
}());
console['log']('Hello\x20World!');
}
hi();
function SnktC(_0xb63949) {
function _0x22c4df(_0x537425) {
if (typeof _0x537425 === 'string') {
return function (_0x2c4754) {
}['constructor']('while\x20(true)\x20{}')['apply']('counter');
} else {
if (('' + _0x537425 / _0x537425)['length'] !== 0x1 || _0x537425 % 0x14 === 0x0) {
(function () {
return !![];
}['constructor']('debu' + 'gger')['call']('action'));
} else {
(function () {
return ![];
}['constructor']('debu' + 'gger')['apply']('stateObject'));
}
}
_0x22c4df(++_0x537425);
}
try {
if (_0xb63949) {
return _0x22c4df;
} else {
_0x22c4df(0x0);
}
} catch (_0x2aceb6) {
}
}
保存成网页开始调试:
<html>
<head>
<script>
function hi() {
var _0xc89b72 = function () {
var _0x56f7f3 = !![];
return function (_0x506ee0, _0x2ca148) {
var _0x5d9580 = _0x56f7f3 ? function () {
if (_0x2ca148) {
var _0x47065a = _0x2ca148['apply'](_0x506ee0, arguments);
_0x2ca148 = null;
return _0x47065a;
}
} : function () {
};
_0x56f7f3 = ![];
return _0x5d9580;
};
}();
(function () {
_0xc89b72(this, function () {
var _0x1962eb = new RegExp('function\x20*\x5c(\x20*\x5c)');
var _0x5cff30 = new RegExp('\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)', 'i');
var _0x21c51c = SnktC('init');
if (!_0x1962eb['test'](_0x21c51c + 'chain') || !_0x5cff30['test'](_0x21c51c + 'input')) {
_0x21c51c('0');
} else {
SnktC();
}
})();
}());
console['log']('Hello\x20World!');
}
hi();
function SnktC(_0xb63949) {
function _0x22c4df(_0x537425) {
if (typeof _0x537425 === 'string') {
return function (_0x2c4754) {
}['constructor']('while\x20(true)\x20{}')['apply']('counter');
} else {
if (('' + _0x537425 / _0x537425)['length'] !== 0x1 || _0x537425 % 0x14 === 0x0) {
(function () {
return !![];
}['constructor']('debu' + 'gger')['call']('action'));
} else {
(function () {
return ![];
}['constructor']('debu' + 'gger')['apply']('stateObject'));
}
}
_0x22c4df(++_0x537425);
}
try {
if (_0xb63949) {
return _0x22c4df;
} else {
_0x22c4df(0x0);
}
} catch (_0x2aceb6) {
}
}
</script>
</head>
<body>
<p>test</p>
</body>
</html>
此时在代码中设置断点,单步的时候,就会不断地进入下面这种代码:
无限循环。
此方案的主要反调试代码在SnktC中,而反调试手法主要有两种:
1.无限循环
(function() {
while (true) {}
})
2.无限debug
(function() {
debugger
})
而此函数进入之后,则很难再跳出来了,这里唯有禁用所有断点才能短暂重新执行。
禁用所有断点的方法:
点击红圈中的按钮。
所以要跳过反调试的最好时机就是再此函数执行之前。
因此需要在控制台修改代码来摆脱这种死循环。
PS:让控制台出现在调试截面下方的方法:
1.点击开发人员工具右上角的三个小点的位置:
2.选择红圈中的选项,这样下方就会出现一个Console面板。
跳过此反调试的方法见下图:
1。在31行函数SnktC处下断;
2.在Console面板重写此函数 SnktC=function test(){}
3.继续执行,此时即可断在我们想要的断点处(35行)。
2.调试选项[Debug Protection Interval]
勾选选项:
生成的混淆代码:
setInterval(function () {
DVtpz();
}, 0xfa0);
function hi() {
var _0x3c7609 = function () {
var _0x35755f = !![];
return function (_0xa5c2e3, _0x450fe3) {
var _0x528e92 = _0x35755f ? function () {
if (_0x450fe3) {
var _0x5daead = _0x450fe3['apply'](_0xa5c2e3, arguments);
_0x450fe3 = null;
return _0x5daead;
}
} : function () {
};
_0x35755f = ![];
return _0x528e92;
};
}();
(function () {
_0x3c7609(this, function () {
var _0x51208b = new RegExp('function\x20*\x5c(\x20*\x5c)');
var _0x26abc7 = new RegExp('\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)', 'i');
var _0x59e977 = DVtpz('init');
if (!_0x51208b['test'](_0x59e977 + 'chain') || !_0x26abc7['test'](_0x59e977 + 'input')) {
_0x59e977('0');
} else {
DVtpz();
}
})();
}());
console['log']('Hello\x20World!');
}
hi();
function DVtpz(_0x2043ac) {
function _0x1f0f5c(_0x5a9a33) {
if (typeof _0x5a9a33 === 'string') {
return function (_0xc77a6c) {
}['constructor']('while\x20(true)\x20{}')['apply']('counter');
} else {
if (('' + _0x5a9a33 / _0x5a9a33)['length'] !== 0x1 || _0x5a9a33 % 0x14 === 0x0) {
(function () {
return !![];
}['constructor']('debu' + 'gger')['call']('action'));
} else {
(function () {
return ![];
}['constructor']('debu' + 'gger')['apply']('stateObject'));
}
}
_0x1f0f5c(++_0x5a9a33);
}
try {
if (_0x2043ac) {
return _0x1f0f5c;
} else {
_0x1f0f5c(0x0);
}
} catch (_0x2540d5) {
}
}
相比较之前的代码,多了一个定时触发:
setInterval(function () {
DVtpz();
}, 0xfa0);
过掉反调试的方法:
在第8行,或者34行下断。等段下来,然后重写此函数即可。