一款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行下斷。等段下來,然後重寫此函數即可。

 

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