一款JavaScript 混淆(Obfuscator)工具(Tool)的研究(二) 反调试及反反调试

  这一篇主要是研究一下这个混淆器的反调试功能,并找到对应的解决办法。

源代码:

// 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行下断。等段下来,然后重写此函数即可。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章