Как работает самозащита Javascript и как ему удается входить в бесконечный цикл при украшении?

#javascript #obfuscation

#javascript #запутывание

Вопрос:

Есть веб-сайт «obfuscator.io «, который запутывает код Javascript. Одна из его функций — «Самозащита». Это превращает простую console.log() строку в это:

 var _0x2a3a06=function(){var _0x409993=!![];return function(_0xe0f537,_0x527a96){var _0x430fdb=_0x409993?function(){if(_0x527a96){var _0x154d06=_0x527a96['apply'](_0xe0f537,arguments);_0x527a96=null;return _0x154d06;}}:function(){};_0x409993=![];return _0x430fdb;};}();var _0x165132=_0x2a3a06(this,function(){var _0x46b23c=function(){var _0x4c0e23=_0x46b23c['constructor']('returnx20/x22x20 x20thisx20 x20x22/')()['constructor']('^([^x20] (x20 [^x20] ) ) [^x20]}');return!_0x4c0e23['test'](_0x165132);};return _0x46b23c();});_0x165132();console['log']();
  

Код действительно работает в консоли Webkit, но когда вы украшаете его с помощью приложения типа «beautifier.io » или «de4js» и снова запустите его в той же консоли, код входит в бесконечный цикл, по существу нарушая код. Как это работает? Имеет ли это какое-то отношение к тому, как работают средства украшения, или к тому, как Javascript интерпретирует код?

Ответ №1:

Запуск кода через улучшитель, как вы это делали, а затем применение некоторых базовых переименований переменных и отмена экранирования приводит к следующему коду:

 var makeRun = function() {
    var firstMakeRun = true;
    return function(global, callback) {
        var run = firstMakeRun ? function() {
            if (callback) {
                var result = callback['apply'](global, arguments);
                callback = null;
                return resu<
            }
        } : function() {};
        firstMakeRun = false;
        return run;
    };
}();
var run = makeRun(this, function() {
    var fluff = function() {
        var regex = fluff['constructor']('return /"   this   "/')()['constructor']('^([^ ] (  [^ ] ) ) [^ ]}');
        return !regex['test'](run);
    };
    return fluff();
});
run();
console['log']()
  

Важная часть заключается в том, что он проверяет регулярное /^([^ ] ( [^ ] ) ) [^ ]}/ выражение на run соответствие самой функции, выполняя неявное run.toString() .

Теперь, где бесконечный цикл? Такого нет, но это регулярное выражение, применяемое к строке, содержащей много пробелов, демонстрирует катастрофическое откат. Попробуйте запустить код с отступом табуляции вместо пробелов, и он будет работать просто отлично — регулярное выражение совпадает до тех пор, пока ваша run функция не содержит несколько пробелов друг после друга и пробелов перед закрытием } .

Ответ №2:

Например, он может вызывать .Метод toString() некоторых функциональных объектов, поэтому, если он каким-то образом переработан, вывод не тот.