
Исследование защиты программы DzSoft PHP Editor

Скриншот программы DzSoft PHP Editor
DzSoft PHP Editor - редактор PHP-скриптов и HTML страничек. В наличии имеется практически весь нужный инструментарий для разработки: подсветка синтаксиса, шаблоны, встроенный FTP-клиент, поддержка юникода, просмотр результатов в браузере и всякое такое. У каждого программиста для работы наверняка есть свой привычный, отобранный годами инструментарий, но может быть и этот редактор кому-нибудь пригодится. Лично мне в DzSoft PHP Editor не нравится то, что за программу требуется выкладывать деньги.
Забираем дистрибутив с офсайта или с альтернативной ссылки, устанавливаем, запускаем. Первым делом нас встречает триальное окно:

Триальноное окно
Бежать сломя голову в кассу мы подождем, пока просто запустим программу. Вторичным триальным признаком будет здоровенная надпись "UNREGISTERED" в окне "О программе":

Окно "О программе"
Третьим признаком будет ссылка на покупку в меню "Help". С исходными данными разобрались, переходим к анализу исполняемого файла. На нем навешан протектор ASProtect. Снять его можно в отладчике при помощи скрипта от VolX или автоматическим распаковщиком DecomAS. Особенность обоих способов в том, что корректно сделать это получается только на Windows XP, для этого у меня есть отдельный нетбук. На других более новых операционных системах распакованный файл получается нерабочим. На счет виртуальных машин ничего сказать не могу, при наличии физического железа с Windows XP я предпочитаю использовать его.

Распаковка ASProtect
Протектор успешно нейтрализован, распакованный файл запускается без ошибок, переходим к его более детальному разбору. Отправляем распакованный файл в дизассемблер. Когда процесс дизассемблирования завершится, начнем исследование с первой зацепки - триального окна. В ресурсах обнаруживается строка сообщения:

Строка в ресурсах
Ее индекс 65195 в десятичной системе счисления или 0FEABh в шестнадцатеричной. Ищем это значение в листинге:
Code (Assembler) : Убрать нумерацию
- .text:004ED21C off_4ED21C dd offset dword_6E07FC
- .text:004ED220 dd 0FEABh
Code (Assembler) : Убрать нумерацию
- .data:006DD008 off_6DD008 dd offset off_4ED21C
Code (Assembler) : Убрать нумерацию
- .text:006B0ECC lea eax, [ebp+var_90]
- .text:006B0ED2 push eax
- .text:006B0ED3 lea edx, [ebp+var_98]
- ; Указатель на указатель на индекс строки сообщения
- .text:006B0ED9 mov eax, off_6DD008
- .text:006B0EDE call sub_408258
- .text:006B0EE3 mov edx, [ebp+var_98]
- .text:006B0EE9 lea ecx, [ebp+var_94]
- .text:006B0EEF mov eax, offset aConst_trialmsg
- ; "const_TrialMsg"
- .text:006B0EF4 call sub_4ED374
- .text:006B0EF9 mov eax, [ebp+var_94]
- .text:006B0EFF push eax
Code (Assembler) : Убрать нумерацию
- .text:006B0D9C mov edx, off_6DD814
- .text:006B0DA2 mov edx, [edx]
- .text:006B0DA4 call sub_406384
- .text:006B0DA9 mov eax, [ebp+var_6C]
- .text:006B0DAC lea edx, [ebp+var_68]
- .text:006B0DAF call sub_40B418
- .text:006B0DB4 mov eax, [ebp+var_68]
- .text:006B0DB7 xor edx, edx
- .text:006B0DB9 call sub_40655C
- ; Перепрыгнуть все триальные сообщения
- .text:006B0DBE jnz loc_6B0F87
- .text:006B0DC4 mov eax, off_6DD670
- .text:006B0DC9 cmp dword ptr [eax], 1
- .text:006B0DCC jge loc_6B0E54
- .text:006B0DD2 lea eax, [ebp+var_70]
- .text:006B0DD5 push eax
- .text:006B0DD6 lea edx, [ebp+var_78]
- .text:006B0DD9 mov eax, off_6DD860
- .text:006B0DDE call sub_408258
- .text:006B0DE3 mov edx, [ebp+var_78]
- .text:006B0DE6 lea ecx, [ebp+var_74]
- .text:006B0DE9 mov eax, offset aConst_trialexp
- ; "const_TrialExpiries"
- .text:006B0DEE call sub_4ED374
- .text:006B0DF3 mov eax, [ebp+var_74]
- .text:006B0DF6 mov edx, off_6DCE90
- .text:006B0DFC mov edx, [edx]

Строка сообщения
Наверняка именно она отображается, когда программа зарегистрирована. Поищем место в коде, где она используется.
Code (Assembler) : Убрать нумерацию
- .text:0069E4A5 mov eax, [ebp-28h]
- .text:0069E4A8 test eax, eax
- .text:0069E4AA jz short loc_69E4B1
- .text:0069E4AC sub eax, 4
- .text:0069E4AF mov eax, [eax]
- .text:0069E4B1 loc_69E4B1:
- .text:0069E4B1 dec eax
- ; Перепрыгнуть строчки "Licensed to"
- .text:0069E4B2 jle loc_69E5F8
- .text:0069E4B8 mov dl, 1
- .text:0069E4BA mov eax, [ebx+384h]
- .text:0069E4C0 call sub_4C6A88
- .text:0069E4C5 xor edx, edx
- .text:0069E4C7 mov eax, [ebx+384h]
- .text:0069E4CD call sub_4A1774
- .text:0069E4D2 mov eax, [ebx+384h]
- .text:0069E4D8 mov edx, [eax+44h]
- .text:0069E4DB sub edx, 8
- .text:0069E4DE call sub_4C6018
- .text:0069E4E3 mov eax, [ebx+384h]
- .text:0069E4E9 mov edx, [eax+4Ch]
- .text:0069E4EC add edx, 10h
- .text:0069E4EF call sub_4C6080
- .text:0069E4F4 lea edx, [ebp-4]
- .text:0069E4F7 mov eax, 2
- .text:0069E4FC call sub_6CB168
- .text:0069E501 cmp dword ptr [ebp-4], 0
- .text:0069E505 jz short loc_69E517
- .text:0069E507 lea eax, [ebp-4]
- .text:0069E50A mov ecx, [ebp-4]
- .text:0069E50D mov edx, offset dword_69E69C
- .text:0069E512 call sub_405D58
- .text:0069E517 loc_69E517:
- .text:0069E517 lea eax, [ebp-2Ch]
- .text:0069E51A mov edx, off_6DD814
- .text:0069E520 mov edx, [edx]
- .text:0069E522 call sub_405C1C
- .text:0069E527 mov eax, [ebp-2Ch]
- .text:0069E52A mov edx, offset aUkrainianUserU
- ; "Ukrainian User\r\n\r\nUKRAYINA\r\nUkrainian L"...
- .text:0069E52F call sub_405E68
- ; Используется локальная лицензия
- .text:0069E534 jnz short loc_69E54B
- .text:0069E536 mov edx, offset loc_69E6EC
- .text:0069E53B mov eax, [ebx+384h]
- .text:0069E541 call sub_4C698C
- .text:0069E546 jmp loc_69E5DE
- .text:0069E54B ; ---------------------------------------
- .text:0069E54B loc_69E54B:
- .text:0069E54B call sub_6CB254
- .text:0069E550 fstp qword ptr [ebp-10h]
- .text:0069E553 wait
- .text:0069E554 push dword ptr [ebp-0Ch]
- .text:0069E557 push dword ptr [ebp-10h]
- ; Вывести сообщение о зарегистрированности
- .text:0069E55A mov edx, off_6DD14C
- .text:0069E560 mov edx, [edx]
- .text:0069E562 lea eax, [ebp-8]
- .text:0069E565 call sub_40F6D4
- .text:0069E56A push offset aLicensedTo ; "Licensed to "
- .text:0069E56F lea edx, [ebp-34h]
- .text:0069E572 mov eax, 1
- .text:0069E577 call sub_6CB168

Окно "О программе"
Вот, уже гораздо приятнее. Не совсем то, что надо, но зато надпись "UNREGISTERED" больше не появляется. Вернемся к украинской лицензии. Если после сравнения не выполнится условный переход по адресу 0069E534, то в окне "О программе" должны появиться данные локальной лицензии. NOPим условный переход, сохраняем изменения, запускаем.

Окно "О программе"
Теперь программа считает, что она зарегистрирована на локального пользователя. Если релиз ориентирован на украинских пользователей, то тут можно больше ничего не делать. А для интернационального релиза можно заменить эту строку на что-нибудь другое, например, прописав вместо нее ваш ник и команду.

Строка сообщения

Программа успешно "зарегистрирована"
Можно остановиться и на этом шаге, основные косметические недостатки программы устранены. Но если вы хотите пойти до конца, то надо избавиться от надписи "BUY NOW" в меню "Help". Строка находится в ресурсах файла, в дельфовой форме:

Пункты меню в ресурсах
Мы видим два пункта меню - "Check for Updates" с атрибутом Visible = False и интересующий нас пункт "BUY NOW". Если еще раз посмотреть меню, то пункта с проверкой обновления в нем нет. Значит оно появляется только в зарегистрированной версии и подменяет собой пункт о покупке. Можно конкретно заморочиться, найти в коде место, отвечающее за эти пункты, и исправить его нужным образом. А можно сделать проще. Там же в редакторе ресурсов переносим атрибут Visible = False с пункта обновления на пункт покупки:

Пункты меню в ресурсах
Теперь отображение пунктов меню по умолчанию должно поменяться на противоположное. Сохраняем изменения, запускаем.

Исправленное меню
Как вы видите, ненужный пункт меню скрыт, а нужный отображается. И при клике на него действительно открывается страница с проверкой обновления.
На этом можно считать цель достигнутой. Программа работает без ограничений. Навесной протектор нейтрализован, триальное время не тикает, никаких ненужных надписей и пунктов меню в интерфейсе больше нет. Таким же способом обходится защита и на других программах DzSoft.
Просмотров: 3795 | Комментариев: 7
Метки: исследование защиты, PHP

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(03.02.2019 в 21:26):
Так для личного использования же, в этом случае не стыдно :)

TEKTON
(04.10.2018 в 19:13):
Молодцы авторы, которые не дерут "со своих" "в три шкуры".
Таких даже ломать как то совестно :)
Спасибо за статью.
Таких даже ломать как то совестно :)
Спасибо за статью.

ManHunter
(22.09.2018 в 00:04):
Отслеживание GetSystemDefaultUILanguage, например. Если бесплатный вариант программы заточен на конкретное значение языка, то ищешь вызов, потом подменяешь возвращаемое значение или патчишь какой-нибудь условный переход.

Noobie
(21.09.2018 в 12:47):
Статья, как обычно, нужная и подлежит изучению.
DimitarSerg,
А можно подробнее? Не про конкретную программу, а, так сказать, в общих чертах, как найти подобную проверку?
DimitarSerg,
А можно подробнее? Не про конкретную программу, а, так сказать, в общих чертах, как найти подобную проверку?

ManHunter
(20.09.2018 в 08:39):
А я раньше ее релизил немного иначе. Подменял адрес серийника и впечатывал фейковый серийник в данные. Но это не так наглядно :)

DimitarSerg
(19.09.2018 в 00:19):
Ага... Я ее когда-то так и ломал, патчил проверку локали )

3ton
(18.09.2018 в 03:49):
Насколько я помню, эта программа бесплатна для жителей СНГ. Где то даже ключик от нее лежит. За статью спасибо!

Добавить комментарий
Заполните форму для добавления комментария
