
Скриншот программы PHP Locker
В поисках очередных пациентов для PHPiD наткнулся на софтину под названием
PHP Locker. "Мощная программа для шифрования ваших PHP-скриптов. Она превращает исходный код в нечто трудное для понимания и реверсивного исследования. В отличие от других систем шифрования, не требует установки дополнительных модулей на серверную часть". Это мнение о программе самих разработчиков, так что "мопед не мой, я просто разместил объяву" :) Там же на офсайте вывешен целый иконостас орденов и медалей, коими наградили этот продукт различные популярные софтообозревательные сайты. И да, к слову, цена за персональную лицензию 180$, а за корпоративную аж все 2800$.
Посмотрим на это чудо повнимательнее. Скачиваем
дистрибутив, устанавливаем. Предварительным анализом файла определяем, что исполняемый файл ничем не упакован и написан на Delphi. На попытку ввода неправильных регистрационных данных программа реагирует сообщением "The wrong username or registration code!" Поиск строки в файле показывает, что она находится в секции ресурсов. Но и просмотр этой секции особо не поможет, потому что файл написан на Delphi, зато мы можем узнать название формы, в которой открывается сообщение об ошибке - TfrmError.

Форма в ресурсах
Для борьбы с Delphi на помощь приходит другой инструмент - декомпилятор для Delphi под названием DeDe. Эта программа написана уже давно, но она до сих пор помогает в исследованиях. Загоняем в нее исполняемый файл, ждем когда закончится декомпиляция, сохраняем проект. В папке с проектом поиском по файлам по строке "TfrmError" находится вот такой кусок кода:
* Reference to TfrmError instance
|
004F6C4D A150F65100 mov eax, dword ptr [51F650]
004F6C52 8B00 mov eax, [eax]
* Reference to: Forms.TCustomForm.Show(TCustomForm);
|
004F6C54 E8E7A7F9FF call 00491440
004F6C59 33C0 xor eax, eax
004F6C5B 5A pop edx
004F6C5C 59 pop ecx
004F6C5D 59 pop ecx
004F6C5E 648910 mov fs:[eax], edx
Конструкция Forms.TCustomForm.Show как раз и отвечает за открытие окна с сообщением о неправильной регистрации. Отлично, теперь мы знаем, в каком месте файла по какому адресу происходит интересующее нас действие. От декомпилятора переходим к дизассемблеру, смотрим в нем условия срабатывания этой ветки алгоритма. Можно, конечно, это сделать и в листинге декомпилятора, но в дизассемблере как-то привычнее.
...
; Вызвать процедуру проверки регистрации
CODE:004F6BD3 call sub_510B10
; Если она вернула AL=0, то программа незарегистрирована
CODE:004F6BD8 test al, al
CODE:004F6BDA jz short loc_4F6C4D
; Сохранить регистрационные данные
CODE:004F6BDC mov eax, ds:off_51F6A0
CODE:004F6BE1 mov eax, [eax]
CODE:004F6BE3 mov ecx, [eax+314h]
CODE:004F6BE9 mov dl, 1
CODE:004F6BEB mov eax, off_43E728
CODE:004F6BF0 call sub_43E7D8
CODE:004F6BF5 mov ebx, eax
CODE:004F6BF7 mov eax, [ebp+var_8]
CODE:004F6BFA push eax
CODE:004F6BFB mov ecx, offset aUsername_0 ; "username"
CODE:004F6C00 mov edx, offset aUser_info ; "user_info"
CODE:004F6C05 mov eax, ebx
CODE:004F6C07 mov edi, [eax]
CODE:004F6C09 call dword ptr [edi+4]
CODE:004F6C0C mov eax, [ebp+var_C]
CODE:004F6C0F push eax
CODE:004F6C10 mov ecx, offset aRegcode ; "regcode"
CODE:004F6C15 mov edx, offset aUser_info ; "user_info"
CODE:004F6C1A mov eax, ebx
CODE:004F6C1C mov edi, [eax]
CODE:004F6C1E call dword ptr [edi+4]
CODE:004F6C21 mov eax, ebx
CODE:004F6C23 call sub_403DD4
CODE:004F6C28 mov eax, ds:off_51F6A0
CODE:004F6C2D mov eax, [eax]
CODE:004F6C2F mov ecx, [ebp+var_C]
CODE:004F6C32 mov edx, [ebp+var_8]
CODE:004F6C35 call sub_511AC0
; Вывести сообщение об удачной регистрации
CODE:004F6C3A mov eax, offset aThankYouForReg
; "Thank you for registering PHP Locker,pl"...
CODE:004F6C3F call sub_43871C
CODE:004F6C44 mov eax, esi
CODE:004F6C46 call sub_491438
CODE:004F6C4B jmp short loc_4F6C59
CODE:004F6C4D ; -------------------------------------------
; Триальная ветка алгоритма, сообщение о неуспешной регистрации
CODE:004F6C4D loc_4F6C4D:
...
По адресу 004F6BD3 происходит вызов процедуры проверки введенного ключа. Криптоанализаторы показывают наличие в ней Blowfish, бороться с этим криптоалгоритмом у меня нет никакого желания. Поэтому просто пропатчим процедуру по адресу 00510B10, записав в ее начало команды MOV AL,1; RET. После этого программа из триального режима переходит в зарегистрированный, снимаются все ограничения, в окне регистрации кнопка Register становится неактивной.

Программа успешно "зарегистрирована"
Последний штрих: открываем в Блокноте файл registration.ini, который находится в папке с программой, и вписываем в него нужное регистрационное имя и какой-нибудь серийный номер. Теперь это имя будет отображаться в заголовке окна.
[user_info]
username="Manunter / PCL"
regcode="Have a Nice Day!"
serial=
C программой закончили, теперь посмотрим на результаты ее творчества, заодно проверим, не осталось ли в ней каких-нибудь еще скрытых триальных ограничений. Закодируем какой-нибудь простейший скрипт в несколько строчек, получим примерно такой текст:
<? $d='t';$h='hudgu';$b = str_replace($h,$d,'eJw1jb0KgzAYAF/FIRBDXSy1COK
ggkPhudguUGhudgu/bBeJ8VOoP4lGrfr0FaHbHRwcqm2cYgvlNgY68++Ki2Irsu+SDkRFGag
o11ChudguYTghudgun0jK8d674by1oS79958n17/QveCBvvnEvKIV87UxvJJDeyuN3YsHUU/
N+Pw0Y8cZHs4QYmLBSCu1WIaG8Vp0IKWaUgnHQ5IB49l6Xwgh1g+UGTlD');eval(gzuncom
press(base64_decode($b))); ?>
Для распаковки этого чуда нам понадобится обычный Блокнот и настроенный web-сервер, или какая-нибудь IDE для разработки на PHP со своим встроенным сервером. Подразумевается, что с самим языком PHP вы уже знакомы. Запускаем секундомер. Первый шаг: в Блокноте заменяем слово eval на echo и запускаем скрипт на выполнение. Получаем на экране что-то типа:
$m='b';$f='eayow';$z = str_replace($f,$m,'eJzjSssvUtBQyeayowQ1sFZQyeayow
QxBFPa2poK1eayowxcCgqpyRn5CkoeqTk5+YoKSta8XLW8XAAuVAuQ');eval(gzuncompre
ss(base64_decode($z)));
Копируем полученный текст обратно в Блокнотик, дополняем открывающими и закрывающими PHP-тегами, заменяем eval на echo, сохраняем и снова запускаем. На этот раз у нас получается полностью открытый исходный код скрипта. В моем случае это был вот такой коротенький пример:
for ($i=0; $i<10; $i++) {
echo "Hello! ";
}
Как видите, за два несложных шага скрипт расшифровался в точности до исходного кода, со всеми переносами строк и отступами, имена переменных тоже не тронуты. Останавливаем секундомер. Затраченное время на расшифровку - меньше минуты. Вот мне и непонятно, как можно требовать за подобную "защиту" такие деньги? И как могут доверять аффтары свои ненаглядные скрипты этой поделке почти за три килобакса, если защита снимается в обычном Блокноте? Грустно :)