Исследование защиты программы Smart Reversi
Скриншот программы Smart Reversi
Еще одна разновидность моей любимой игры в реверси - Smart Reversi. Игра выпущена уже давно, больше десяти лет назад, но для меня это значения не имеет. Игра классная, логика компьютера скучать не дает. Если бы не различные ограничения в триальной версии и необходимость покупки лицензии, то было бы вообще идеально.
Скачиваем дистрибутив, устанавливаем, смотрим что из этого получается. Сразу бросается в глаза, что главный исполняемый файл упакован навесным протектором ASProtect.
Наг-окно при запуске программы
Я нашел несколько ограничений незарегистрированной программы: лимит в 14 дней работы, наг-окно при запуске программы, надпись в заголовке окна, надпись в окне "О программе", пункты регистрации в меню, невозможность сохранить и загрузить процесс игры.
Окно "О программе", меню и заголовок главного окна
Перевод системного времени показывает, что как минимум ограничение по времени работы программы реализовано средствами ASProtect. При удалении из реестра "часовых бомб" этого протектора триальный срок игры обнуляется.
Для начала надо избавиться от навесной защиты. Здесь использована очень старая версия ASProtect, с ней легко справляется даже статичный распаковщик CASPR. Отправляем распакованный файл в дизассемблер. Файл совсем крохотный, поэтому его анализ займет непродолжительное время. Наиболее приметный признак триальности - текст в заголовке окна. Попробуем найти эту строчку в файле:
Строка сообщения
Никаких проблем, строка лежит в открытом виде. Вернемся в дизассемблер и посмотрим, где же она используется:
Code (Assembler) : Убрать нумерацию
- seg000:00403733 push offset ClassName ; "Smart Reversi"
- seg000:00403738 push eax ; lpString1
- seg000:00403739 call ds:lstrcpyA
- ; Указатель на строку
- seg000:0040373F push ds:lpString ; lpString
- ; Получить длину строки
- seg000:00403745 call ds:lstrlenA
- seg000:0040374B mov esi, ds:lstrcatA
- ; Длина строки не нулевая?
- seg000:00403751 test eax, eax
- ; Да, программа считается зарегистрированной
- seg000:00403753 jnz short loc_403780
- ; Надпись "UNREGISTERED" в заголовке окна
- seg000:00403755 push ds:dword_412F14
- seg000:0040375B lea eax, [ebp+String2]
- seg000:00403761 push offset aUnregisteredDD
- ; " [UNREGISTERED %d days left]"
- seg000:00403766 push eax ; LPSTR
- seg000:00403767 call ds:wsprintfA
- seg000:0040376D add esp, 0Ch
- seg000:00403770 lea eax, [ebp+String2]
- seg000:00403776 push eax ; lpString2
- seg000:00403777 lea eax, [ebp+String]
- seg000:0040377D push eax ; lpString1
- seg000:0040377E call esi ; lstrcatA
Перекрестные ссылки на строку
Если вы имели дело с ASProtect, то сразу же узнаете название одной из функций API этого протектора - GetRegistrationInformation, в которой инициализируется эта строка. Это значит, что вся регистрация программы полностью завязана на навесном протекторе.
Code (Assembler) : Убрать нумерацию
- seg000:004087A0 GetRegistrationInformation proc near
- seg000:004087A0 arg_0 = dword ptr 4
- seg000:004087A0 mov eax, [esp+arg_0]
- seg000:004087A4 mov ds:lpString, eax
- seg000:004087A9 retn 4
- seg000:004087A9 GetRegistrationInformation endp
Code (Assembler) : Убрать нумерацию
- seg000:00405E05 push ds:lpString ; lpString
- seg000:00405E0B call ds:lstrlenA
- seg000:00405E11 xor ebx, ebx
- seg000:00405E13 test eax, eax
- ; Проверить длину строки
- seg000:00405E15 jnz short loc_405E4C
- ; Если она нулевая, то показать сообщение о невозможности выполнения действия
- seg000:00405E17 push 40h ; uType
- seg000:00405E19 push offset Caption ; "Smart Reversi"
- seg000:00405E1E push offset aSaveAndLoadAre
- ; "Save and Load are available only in reg"...
- seg000:00405E23 push ds:hWnd ; hWnd
- seg000:00405E29 call ds:MessageBoxA
- seg000:00405E2F push ebx ; dwInitParam
- seg000:00405E30 push offset sub_402CFB ; lpDialogFunc
- seg000:00405E35 push ds:hWnd ; hWndParent
- seg000:00405E3B push 0B1h ; lpTemplateName
- seg000:00405E40 push ds:hInstance ; hInstance
- seg000:00405E46 call ds:DialogBoxParamA
- seg000:00405E4C loc_405E4C:
- ; Сюда выполняется переход, если программа зарегистрирована
- seg000:00405E4C jmp short loc_405E52
- seg000:00405E4C ; --------------------------------
- seg000:00405E4E dw 5EBh
- seg000:00405E50 ; --------------------------------
- seg000:00405E50 cdq
- seg000:00405E51 cdq
- seg000:00405E52 loc_405E52:
- seg000:00405E52 jmp loc_40614B
- seg000:00405E52 ; --------------------------------
- seg000:00405E57 db 0E0h
- seg000:00405E58 dd 0B372B1AFh, 12639987h, 0C85D4D71h, 3EF397CAh, 0FCA4F933h
- seg000:00405E58 dd 4DC4D812h, 0AE3B3A72h, 4CFC41DBh, 0CE5129A2h, 4D67B5CCh
- seg000:00405E58 dd 3E0C0833h, 4C21BCFDh, 6CE95E67h, 0C96456DDh, 5548DBDBh
- seg000:00405E58 dd 3DC14919h, 72EC96EBh, 0FA684A7Ah, 0CF427962h, 0D58A48Eh
- seg000:00405E58 dd 3D7658D7h, 0B9881E35h, 9F1E944Eh, 77DBC905h, 77D924BFh
- seg000:00405E58 dd 19870E08h, 71D71307h, 276E6E2Ah, 0C1B8867Fh, 2D9A2CD3h
- seg000:00405E58 dd 0FAC372BDh, 31620821h, 0C5EBD6A4h, 0A79636Fh, 57AF3992h
- seg000:00405E58 dd 8B2E150Fh, 0E2222371h, 81FFB93Ah, 1FEFB1B6h, 29751F08h
- seg000:00405E58 dd 4FF6386Bh, 3CA9F9AAh, 0EC997986h, 5E0E8C6Ch, 3C42A759h
- ...
Это же касается и окна "О программе". Даже с пропатченными проверками в нем все равно написано, что это ознакомительная версия. Эта небольшая проблемка легко решается в редакторе ресурсов, где можно заменить строку на любую другую, например, вписать вместо нее регистрационное имя:
Исправляем строку в редакторе ресурсов
Сохраняем изменения, запускаем игру. Стартовое наг-окно исчезло вместе с ограничением по времени, в меню больше нет пунктов регистрации, в заголовке окна тоже все в порядке. При попытке сохранить или загрузить игру ничего не происходит, но об этом я уже написал выше.
Программа успешно "зарегистрирована"
В окне "О программе" отображается регистрационное имя, вписанное в редакторе ресурсов. Будем считать, что защита практически полностью нейтрализована, можно приступать к игре.
Просмотров: 5166 | Комментариев: 7
Метки: исследование защиты, игры
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
user
(10.03.2015 в 21:46):
Блин. Не умею я играть в эту реверси. Не умею.
Дрючит меня на уровне новичка, как котёнка..
Дрючит меня на уровне новичка, как котёнка..
ManHunter
(10.03.2015 в 18:47):
Инлайн и лоадеры надо использовать только если не удается распаковать файл до рабочего состояния. Здесь все прекрасно распаковывается, за исключением шифрованных участков, конечно.
user
(10.03.2015 в 01:15):
В данном конкретном случае - это слишком гомоздко.
Потенциально нехорошие вещи - получение API недокументированным способом и выделение памяти. Да плюс к тому потом ещё и патч кода во время выполнения.
Это костыли.
Потенциально нехорошие вещи - получение API недокументированным способом и выделение памяти. Да плюс к тому потом ещё и патч кода во время выполнения.
Это костыли.
brute
(09.03.2015 в 21:53):
чтобы было "меньше хирургии", надо применять "aev_injector" (Armadillo Reducer и им подобные программы). Зарегистрированная программа меняет свой код, поэтому, зная места регистрации можно "быстро зарегистрировать" даже не распаковывая. Совсем вручную "с нуля" современные (и будущие) протекторы (имхо) не снять (без многолетних наработок в виде скриптов, скрывающих плагинов, хитрых дамперов и восстановителей ресурсов)
user
(09.03.2015 в 15:47):
Добавлю.
Пару раз внаглую удавалось восстановить пошифрованный функционал, имея предыдущую версию с верным ключом и, вынув из неё верно расшифрованные фрагменты, адаптировать их к новой версии, которая без ключа.
Но такие случаи редкость.
Пару раз внаглую удавалось восстановить пошифрованный функционал, имея предыдущую версию с верным ключом и, вынув из неё верно расшифрованные фрагменты, адаптировать их к новой версии, которая без ключа.
Но такие случаи редкость.
user
(09.03.2015 в 14:42):
Позволю себе уточнить.
В случае с ASPR'ом удобно найти все ссылки на пустое место в динамической памяти, где должен быть указатель на строку-имя юзера, и поправить их, эти ссылки, на статическую память, где есть пустое место. В том пустом месте статической памяти поместить указатель на следующий DWORD и в нём записать любую желаемую строку(типа имя юзера).
Например, все DWORDs в файле <dd 0041С104h> позаменять на <dd 0040F820h> (7 штук), по этому адресу .40F820h записать <dd 0040F824> (указатель на следующий DWORD)и по этому адресу .40F824: положить любую строку.
Это чтоб поменьше хирургии. Зачастую эта строка-имя потом отображается и в About'е поправленной программы.
В случае с ASPR'ом удобно найти все ссылки на пустое место в динамической памяти, где должен быть указатель на строку-имя юзера, и поправить их, эти ссылки, на статическую память, где есть пустое место. В том пустом месте статической памяти поместить указатель на следующий DWORD и в нём записать любую желаемую строку(типа имя юзера).
Например, все DWORDs в файле <dd 0041С104h> позаменять на <dd 0040F820h> (7 штук), по этому адресу .40F820h записать <dd 0040F824> (указатель на следующий DWORD)и по этому адресу .40F824: положить любую строку.
Это чтоб поменьше хирургии. Зачастую эта строка-имя потом отображается и в About'е поправленной программы.
Добавить комментарий
Заполните форму для добавления комментария
Это на средней сложности. На сложной "сухого" счета пока не получалось.