
Скриншот программы JavaScript Scrambler
Читаю сейчас
умную книжку по JavaScript, в одной из глав наткнулся на описание якобы крутой программы для защиты исходных кодов JavaScript от всяких посягательств. И там же было сказано, что программа еще и платная. Речь идет о
JavaScript Scrambler. Не знаю что мне захотелось больше: поковыряться внутри самой программы или в результатах ее работы. Так что придется воплощать в жизнь оба желания.
С главной страницы сайта ссылок на программу нет, более того, нет вообще никаких упоминаний о ней, что уже настораживает. Ладно, качаем
дистрибутив по прямой ссылке. Устанавливать ничего не надо, все лежит в архиве. Беглый осмотр пациента указывает, что главный файл ничем не упакован. Пока работает дизассемблер, почитаем описание с офсайта: "... заменяет до 100 имен функций на рандомные имена ..." (мне было лениво разбираться с динамическим распределением памяти, поэтому я тупо забил массив из 100 строк фиксированной длины), "... обработка html-файлов размером аж до 60 килобайт ..." (блин, и тут придется делать динамическое выделение памяти, ладно, пусть будет массив 60000 of char), "... возможность пакетной обработки файлов через командную строку ..." (выбор одного файла я уже умею делать, про drag'n'drop, listbox и групповую обработку файлов почитаю в другой раз). В скобках указаны предполагаемые мысли аффтара этой поделки на этапе ее разработки.
Ладно, оставим аффтара в покое, вернемся к его выкидышу. На ввод левых регистрационных данных программа реагирует сообщением "The serial number you entered, was wrong!". Замечательно, вот эта строка в файле:

Нехорошая строка найдена
Посмотрим, что нам скажет дизассемблер. Параллельно пройдем этот блок под отладчиком, чтобы было понятно, откуда что берется. В листинге все ключевые места прокомментированы.
CODE:00433F69 lea edx, [ebp+var_8]
CODE:00433F6C mov eax, [ebx+230h]
CODE:00433F72 call sub_41A8BC
CODE:00433F77 mov eax, [ebp+var_4]
CODE:00433F7A call sub_403A30
; Проверка длины имени, если оно меньше 4 символов, то дальше ничего не проверять
CODE:00433F7F cmp eax, 4
CODE:00433F82 jle loc_43406D
CODE:00433F88 lea ecx, [ebp+var_C]
CODE:00433F8B mov edx, [ebp+var_4]
CODE:00433F8E mov eax, ebx
; Тут из имени вычисляется правильный серийный номер
CODE:00433F90 call sub_4339B0
CODE:00433F95 mov eax, [ebp+var_C]
CODE:00433F98 mov edx, [ebp+var_8]
CODE:00433F9B call sub_403B40
; Если функция не установила флаг ZF, то серийный номер неправильный
; Так работает функция сравнения двух строк, адреса которых переданы в
; регистрах EAX и EDX
CODE:00433FA0 jnz loc_43406D
; Сохранить правильные регистрационные данные
CODE:00433FA6 mov ds:byte_435948, 1
CODE:00433FAD mov ecx, offset aJsscrambler__0
; "JSScrambler.ini" - теперь мы знаем, куда это все будет записываться
CODE:00433FB2 mov dl, 1
CODE:00433FB4 mov eax, off_42F3D4
CODE:00433FB9 call sub_42F430
CODE:00433FBE mov esi, eax
CODE:00433FC0 mov eax, [ebp+var_4]
CODE:00433FC3 push eax
CODE:00433FC4 mov ecx, offset aName_0 ; "Name"
CODE:00433FC9 mov edx, offset aJavascriptSc_2
; "JavaScript Scrambler"
CODE:00433FCE mov eax, esi
CODE:00433FD0 call sub_42F4C4
CODE:00433FD5 mov eax, [ebp+var_8]
CODE:00433FD8 push eax
CODE:00433FD9 mov ecx, offset dword_43411C
CODE:00433FDE mov edx, offset aJavascriptSc_2
; "JavaScript Scrambler"
CODE:00433FE3 mov eax, esi
CODE:00433FE5 call sub_42F4C4
CODE:00433FEA mov eax, esi
CODE:00433FEC call sub_402D50
CODE:00433FF1 mov eax, offset aThankYouForR_0
; "Thank you for registering!"
CODE:00433FF6 call sub_42F1E4
CODE:00433FFB mov edx, offset aJavascriptSc_3
; "JavaScript Scrambler V1.11"
CODE:00434000 mov eax, ds:dword_43673C
CODE:00434005 call sub_41A8EC
CODE:0043400A push offset dword_43417C
CODE:0043400F push [ebp+var_4]
CODE:00434012 push offset dword_434194
CODE:00434017 lea eax, [ebp+var_C]
CODE:0043401A mov edx, 3
CODE:0043401F call sub_403AF0
CODE:00434024 mov edx, [ebp+var_C]
CODE:00434027 mov eax, [ebx+21Ch]
CODE:0043402D call sub_41A8EC
CODE:00434032 mov edx, offset aThankYouForR_0
; Вывести сообщение "Thank you for registering!"
CODE:00434037 mov eax, [ebx+220h]
CODE:0043403D call sub_41A8EC
CODE:00434042 xor edx, edx
CODE:00434044 mov eax, [ebx+1F8h]
CODE:0043404A call sub_430E88
CODE:0043404F mov eax, [ebx+1F8h]
CODE:00434055 mov edx, [eax]
CODE:00434057 call dword ptr [edx+50h]
CODE:0043405A mov edx, [ebx+1ECh]
CODE:00434060 mov eax, [ebx+1E8h]
CODE:00434066 call sub_4312B0
CODE:0043406B jmp short loc_4340A2
CODE:0043406D ; ------------------------------------------------
CODE:0043406D loc_43406D:
CODE:0043406D mov eax, offset aTheSerialNumbe
; Вывести сообщение "The serial number you entered, was wrong"...
CODE:00434072 call sub_42F1E4
CODE:00434077 xor edx, edx
CODE:00434079 mov eax, [ebx+22Ch]
CODE:0043407F call sub_41A8EC
Под отладчиком поставим точку останова перед функцией сравнения строк по адресу 00433F95 и снова введем какие-нибудь левые регистрационные данные. На стеке получается интересная картина: введенное имя, введенный левый код и еще какая-то строка, очень похожая на серийный номер.

Серийный номер на стеке
Если пройти код в пошаговом режиме чуть дальше, то видно, что именно эта строка используется при сравнении с введенным левым серийником. Можно предположить, что это и есть правильный серийный номер, который был вычислен программой на основе введенного имени. Повторим попытку регистрации с тем же именем, но уже с полученным серийником. Предположение оказалось верным.

Программа успешно зарегистрирована
Файл с регистрационными данными JSScrambler.ini создается в папке Windows. Ну правильно, блин, больше ж негде... Тратить время на кейгенинг этого убожества даже не хочется, хоть алгоритм там очень простой. Ладно, ограничение по размеру обрабатываемых файлов теперь снято, можно посмотреть как это чудо программерской мысли зарекомендует себя в работе. Включаем все опции защиты, но даже в этом режиме программа категорически отказывается обрабатывать чистые скрипты .js, они обязательно должны быть внутри тегов script в html-странице. Хорошо, сделаем как просят. Вот что получилось у меня после обработки (фрагмент кода):
function x065309(lay){if(loaded==0)return false;if(is.ie4up)document.all(lay).style.visibility='visible';else if(is.gecko)document.getElementById(lay).style.visibility='visible';}
function x058446(lay){if(loaded==0)return false;if(is.ie4up)document.all(lay).style.visibility='hidden';else if(is.gecko)document.getElementById(lay).style.visibility='hidden';}
Что мы видим? Переносы строк, пробелы и комментарии убраны, имена функций заменены на псевдослучайные, имена переменных не тронуты, текстовые строки не искажены. Стойкость такой защиты уверенно стремится к нулю. Из-за отсутствия полноценной пакетной обработки при нескольких взаимосвязанных скриптах корректность результата работы JavaScript Scrambler в точности равна такому же нулевому значению. Этакий сферический говнософт в вакууме: ни украсть, ни покараулить. Видимо аффтар не зря решил не выкладывать этот позор на всеобщее обозрение, вот только мне непонятно, как ЭТО может стоить аж целых 15 баксов?