Деобфусцировать обфусцированный скрипт JS для его выполнения на стороне сервера

Как я могу деобфусцировать код javaScript? Это здесь (внутри самого последнего тега скрипта).

В основном я знаю, что он делает (запутывает значение атрибута имени логина/пароля формы и добавляет в форму скрытый ввод с именем = 'char' и случайным значением, см. связанный вопрос здесь). Я хочу расшифровать скрипт, чтобы узнать, как он выполняет обфускацию, чтобы я мог имитировать его на стороне сервера (с помощью php).

Этот инструмент не может его декодировать.

Я сделал некоторую деобфускацию, оценив объект hd. Я взял части кода (разделенные точкой с запятой ;) и оценил их:

<script>
    var hd =~[];
    hd={___:++hd,$$$$:(![]+"")[hd],__$:++hd,$_$_:(![]+"")[hd],_$_:++hd,$_$$:({}+"")[hd],$$_$:(hd[hd]+"")[hd],_$$:++hd,$$$_:(!""+"")[hd],$__:++hd,$_$:++hd,$$__:({}+"")[hd],$$_:++hd,$$$:++hd,$___:++hd,$__$:++hd};

    hd.$_=(hd.$_=hd+"")[hd.$_$]+(hd._$=hd.$_[hd.__$])+(hd.$$=(hd.$+"")[hd.__$])+((!hd)+"")[hd._$$]+(hd.__=hd.$_[hd.$$_])+(hd.$=(!""+"")[hd.__$])+(hd._=(!""+"")[hd._$_])+hd.$_[hd.$_$]+hd.__+hd._$+hd.$;

    hd.$$=hd.$+(!""+"")[hd._$$]+hd.__+hd._+hd.$+hd.$$;  

    hd.$=(hd.___)[hd.$_][hd.$_];  

    console.log('hd: '); 
    console.dir(hd);
    console.log('hd length: ' + Object.keys(hd).length);
</script>

Результат этого вы можете увидеть здесь в консоли браузера.

Тем не менее, последняя часть кода, очевидно, представляет собой функцию, вызывающую саму себя:

hd.$(hd.$(... _+"\"")())(); 

hd.$ — функция объекта, см. рисунок: введите здесь описание изображения

Но я не знаю, как его расшифровать. Я пытался заменить все экземпляры объекта, например. hd.$$$$, hd.$_$ и т.д. в остальном коде, но результат только как это. Без понятия, как двигаться дальше.


person Igor Savinkin    schedule 25.01.2016    source источник
comment
Возможно, вам следует подумать об использовании Node.JS, тогда вы сможете запустить его на стороне сервера;)   -  person Julian Knight    schedule 25.01.2016
comment
@JulianKnight, совместим ли Node.JS с php?   -  person Igor Savinkin    schedule 25.01.2016
comment
Попробуйте эти деобфускаторы и посмотрите, что вам подходит: kahusecurity.com/2014/javascript -deobfuscation-tools-redux   -  person Johannes Jander    schedule 25.01.2016
comment
@JohannesJander, спасибо. Я попробую их позже.   -  person Igor Savinkin    schedule 25.01.2016
comment
@IgorSavinkin: Совместимо? В том смысле, что вы можете запускать их бок о бок на одной платформе, да. Хотя, наверное, не то, что вы имели в виду. Node.JS — это еще один сервер на основе языка сценариев, такой как PHP или PYTHON, но он использует JavaScript, поэтому вы можете использовать один и тот же язык как на сервере, так и на клиенте. Он полностью кроссплатформенный даже для встроенных систем и имеет много тысяч библиотек, позволяющих делать практически все что угодно. Похож на PHP, но гораздо более гибкий. Требует большего доступа к ОС, поэтому не всегда доступен на дешевых хостинговых платформах.   -  person Julian Knight    schedule 25.01.2016


Ответы (1)


После того, как ваш объект hd построен, никакие другие назначения переменных не выполняются, он просто создает большую строку для анализа в функцию.

Итак, используя ваш результирующий объект hd, я извлек часть, строящую строку, и получил это:

"return\"docu\155e\156t.\147et\105le\155e\156t\102\171\111d('lo\147\151\156fo\162\155').\151\156\156e\162\110\124\115\114\40=\40'<d\151\166\40\163t\171le=\"\155a\162\147\151\156-botto\155:\4025\160\170\"\40cla\163\163=\"\151\156\160ut-\147\162ou\160\"><\163\160a\156\40cla\163\163=\"\151\156\160ut-\147\162ou\160-addo\156\"><\151\40cla\163\163=\"\147l\171\160\150\151co\156\40\147l\171\160\150\151co\156-u\163e\162\"></\151></\163\160a\156><\151\156\160ut\40\151d=\"lo\147\151\156-u\163e\162\156a\155e\"\40t\171\160e=\"te\170t\"\40cla\163\163=\"fo\162\155-co\156t\162ol\"\40\156a\155e=\"\130\161\125\106\1603\107\156e\147\"\40\166alue=\"\"\40\160lace\150olde\162=\"\114o\147\151\156\"></d\151\166><d\151\166\40\163t\171le=\"\155a\162\147\151\156-botto\155:\4025\160\170\"\40cla\163\163=\"\151\156\160ut-\147\162ou\160\"><\163\160a\156\40cla\163\163=\"\151\156\160ut-\147\162ou\160-addo\156\"><\151\40cla\163\163=\"\147l\171\160\150\151co\156\40\147l\171\160\150\151co\156-loc\153\"></\151></\163\160a\156><\151\156\160ut\40\151d=\"lo\147\151\156-\160a\163\163\167o\162d\"\40t\171\160e=\"\160a\163\163\167o\162d\"\40cla\163\163=\"fo\162\155-co\156t\162ol\"\40\156a\155e=\"\171l\110\156\110\161\150\104\1262\"\40\160lace\150olde\162=\"\120a\163\163\167o\162d\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40cla\163\163=\"\151\156\160ut-\147\162ou\160\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40cla\163\163=\"c\150ec\153bo\170\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<label>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<\151\156\160ut\40\151d=\"lo\147\151\156-\162e\155e\155be\162\"\40t\171\160e=\"c\150ec\153bo\170\"\40\156a\155e=\"\162e\155e\155be\162\"\40\166alue=\"1\">\40\122e\155e\155be\162\40\155e\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</label>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40\163t\171le=\"\155a\162\147\151\156-to\160:10\160\170\"\40cla\163\163=\"fo\162\155-\147\162ou\160\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40cla\163\163=\"col-\163\155-12\40co\156t\162ol\163\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<a\40\151d=\"bt\156-lo\147\151\156\"\40\150\162ef=\"#\"\40cla\163\163=\"bt\156\40bt\156-\163ucce\163\163\">\114o\147\151\156\40\40</a>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<\151\156\160ut\40t\171\160e=\"\150\151dde\156\"\40\156a\155e=\"c\150a\162\"\40\166alue=\"&\156ot;\">';\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40$(\"#bt\156-lo\147\151\156\").cl\151c\153(fu\156ct\151o\156(){\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\166a\162\40\163e\162\40=\40$(\40\"#lo\147\151\156fo\162\155\"\40).\163e\162\151al\151\172e();\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40$.\160o\163t(\"/\160o\163t.\160\150\160\",\163e\162+\"&\150a\163\150=\"+\155d5(\163e\162),fu\156ct\151o\156(){locat\151o\156.\162e\160lace(\"/lo\147\147ed.\160\150\160\");});\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40});\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\"";

Это дает нам полпути. Но многие символы имеют кодировку URI (\xxx). Я сделал простую замену регулярного выражения для декодирования этих значений:

var raw = "return\"docu\155e\156t.\147et\105le\155e\156t\102\171\111d('lo\147\151\156fo\162\155').\151\156\156e\162\110\124\115\114\40=\40'<d\151\166\40\163t\171le=\"\155a\162\147\151\156-botto\155:\4025\160\170\"\40cla\163\163=\"\151\156\160ut-\147\162ou\160\"><\163\160a\156\40cla\163\163=\"\151\156\160ut-\147\162ou\160-addo\156\"><\151\40cla\163\163=\"\147l\171\160\150\151co\156\40\147l\171\160\150\151co\156-u\163e\162\"></\151></\163\160a\156><\151\156\160ut\40\151d=\"lo\147\151\156-u\163e\162\156a\155e\"\40t\171\160e=\"te\170t\"\40cla\163\163=\"fo\162\155-co\156t\162ol\"\40\156a\155e=\"\130\161\125\106\1603\107\156e\147\"\40\166alue=\"\"\40\160lace\150olde\162=\"\114o\147\151\156\"></d\151\166><d\151\166\40\163t\171le=\"\155a\162\147\151\156-botto\155:\4025\160\170\"\40cla\163\163=\"\151\156\160ut-\147\162ou\160\"><\163\160a\156\40cla\163\163=\"\151\156\160ut-\147\162ou\160-addo\156\"><\151\40cla\163\163=\"\147l\171\160\150\151co\156\40\147l\171\160\150\151co\156-loc\153\"></\151></\163\160a\156><\151\156\160ut\40\151d=\"lo\147\151\156-\160a\163\163\167o\162d\"\40t\171\160e=\"\160a\163\163\167o\162d\"\40cla\163\163=\"fo\162\155-co\156t\162ol\"\40\156a\155e=\"\171l\110\156\110\161\150\104\1262\"\40\160lace\150olde\162=\"\120a\163\163\167o\162d\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40cla\163\163=\"\151\156\160ut-\147\162ou\160\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40cla\163\163=\"c\150ec\153bo\170\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<label>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<\151\156\160ut\40\151d=\"lo\147\151\156-\162e\155e\155be\162\"\40t\171\160e=\"c\150ec\153bo\170\"\40\156a\155e=\"\162e\155e\155be\162\"\40\166alue=\"1\">\40\122e\155e\155be\162\40\155e\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</label>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40\163t\171le=\"\155a\162\147\151\156-to\160:10\160\170\"\40cla\163\163=\"fo\162\155-\147\162ou\160\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<d\151\166\40cla\163\163=\"col-\163\155-12\40co\156t\162ol\163\">\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<a\40\151d=\"bt\156-lo\147\151\156\"\40\150\162ef=\"#\"\40cla\163\163=\"bt\156\40bt\156-\163ucce\163\163\">\114o\147\151\156\40\40</a>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40</d\151\166>\\\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40<\151\156\160ut\40t\171\160e=\"\150\151dde\156\"\40\156a\155e=\"c\150a\162\"\40\166alue=\"&\156ot;\">';\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40$(\"#bt\156-lo\147\151\156\").cl\151c\153(fu\156ct\151o\156(){\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\166a\162\40\163e\162\40=\40$(\40\"#lo\147\151\156fo\162\155\"\40).\163e\162\151al\151\172e();\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40$.\160o\163t(\"/\160o\163t.\160\150\160\",\163e\162+\"&\150a\163\150=\"+\155d5(\163e\162),fu\156ct\151o\156(){locat\151o\156.\162e\160lace(\"/lo\147\147ed.\160\150\160\");});\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40});\12\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\"";

var decoded = raw.replace(/\\\d+/g, function(match) {
    return window.decodeURIComponent(match);
});

Это дало мне следующее (немного прибрался и отформатировал):

document.getElementById('loginform').innerHTML = '
    <div style="margin-bottom: 25px" class="input-group">
        <span class="input-group-addon">
            <i class="glyphicon glyphicon-user"></i>
        </span>
        <input id="login-username" type="text" class="form-control" name="XqUFp3Gneg" value="" placeholder="Login">
    </div>
    <div style="margin-bottom: 25px" class="input-group">
        <span class="input-group-addon">
            <i class="glyphicon glyphicon-lock"></i>
        </span>
        <input id="login-password" type="password" class="form-control" name="ylHnHqhDV2" placeholder="Password">
    </div>
    <div class="input-group">
        <div class="checkbox">
            <label>
                <input id="login-remember" type="checkbox" name="remember" value="1">
                Remember me
            </label>
        </div>
    </div>
    <div style="margin-top:10px" class="form-group">
        <div class="col-sm-12 controls">
            <a id="btn-login" href="#" class="btn btn-success">Login</a>
        </div>
    </div>
    <input type="hidden" name="char" value="&not;">
';

$("#btn-login").click(function(){
    var ser = $( "#loginform" ).serialize();
    $.post("/post.php",
        ser + "&hash=" + md5(ser),
        function() { location.replace("/logged.php"); }
    );
});

Другими словами, он сериализует значения формы с помощью jquery serialize(), а затем создает хэш md5 этого сериализованного значения. и передать это как строку запроса hash вызову сервера.

person Rhumborl    schedule 25.01.2016
comment
благодарю вас. Это именно то, что должно быть. Тем не менее, нужно ли мне декодировать этот скрипт каждый раз, когда я запрашиваю форму с запутанным кодом? Эти запутанные значения атрибута имени и входное значение char различны для каждого запроса (я мог видеть это, извлекая значение form.serialized()). Связаны ли эти name="XqUFp3Gneg" name="ylHnHqhDV2" и name="char" value="&not;" на целевом сервере? Что вы думаете? Если они не коррелированы, я мог бы случайным образом сгенерировать их с помощью php и отправить форму. В противном случае целевой сервер может проверить их подлинность и отклонить мои собственные значения имени и значения char. - person Igor Savinkin; 25.01.2016
comment
также не могли бы вы подробнее объяснить, как вы достигли этого: return\docu\155e\156t.\147et\105le\155e\156t\102\171\111d('lo\147\.... - person Igor Savinkin; 25.01.2016
comment
какой инструмент я могу использовать для автоматического выполнения такого декодирования на стороне сервера? - person Igor Savinkin; 25.01.2016
comment
если вы просмотрите исходный код на странице, на которую вы ссылаетесь, а затем сравните сгенерированный код выше, вы увидите, что имена form-control отличаются, а <input type="hidden" name="char"> добавлено. Этот сценарий обрабатывается сервером, поэтому он должен генерировать имена там. Это имеет смысл с точки зрения безопасности. - person Rhumborl; 25.01.2016
comment
Я точно не знаю, как вы взаимодействуете с этой страницей на стороне сервера — в основном делаете http-запрос и анализируете его? Но я бы стремился избегать его деобфускации каждый раз и пытался найти способ использовать деобфусцированный код как есть, например. используйте одни и те же имена элементов формы каждый раз. - person Rhumborl; 25.01.2016
comment
This script is rendered by the server, so it must be generating the names there. - конечно, но каждая загрузка формы этого скрипта отличается, так как эти имена разные и значение char тоже **другое*8! - person Igor Savinkin; 25.01.2016
comment
Я должен вернуть\docu\155e\156t.\147et\105le\155e\156t\102\171\111d('lo\1, просто скопировав и вставив остальную часть кода в тег script и исключив скобки, чтобы фактически запустите его. Это немного случайно, но обычно вы можете разбить его точкой с запятой, как вы начали делать. Я создал объект hd, используя то, что вы опубликовали, и просто запустил код генерации строки и вывести его в переменную - person Rhumborl; 25.01.2016
comment
Давайте продолжим обсуждение в чате. - person Rhumborl; 25.01.2016