Исследование защиты программы Advanced Gomoku


Скриншот программы Advanced Gomoku

Игрушка Advanced Gomoku - это по сути те же самые "крестики-нолики", в которые, наверное, играл каждый. Игрушка достаточно старая, и из-за особенности ее защиты получается, что она работает только на системах Windows XP. Это значит, что даже если кто-то потратил деньги на ее приобретение, то он не сможет в нее играть после обновления своей операционной системы. Справедливо? Нет. В соответствии с действующем законодательством мы имеем полное право внести изменения в программу, чтобы она могла продолжать работать на новой системе.

Правомерно овладеваем дистрибутивом, но для его установки придется воспользоваться компьютером с Windows XP или виртуальной машиной. После установки и запуска появляется триальное окно:


Наг-скрин при старте программы

Кроме него, как я понял, в программе других ограничений нет. Первичный осмотр главного исполняемого файла показывает, что он упакован старой версией ASProtect, именно поэтому файл и отказывается работать на современных системах. Статические распаковщики его не берут, воспользуемся автоматическим распаковщиком Stripper 2.07 для снятия навесного протектора.


Распаковываем исполняемый файл

Проверим распакованный файл на работоспособность. Он запускается, триальное окно при запуске пропало, но в окне "О программе" все равно показывается, что программа не зарегистрирована и остался минус один день испытательного срока. Если со счетчиком дней все понятно - это побочный эффект снятия ASProtect, и ничего страшного в этом нет, то строка "unregistered" говорит о том, что программа не может найти регистрационное имя (ключ). Казалось бы, можно оставить и так, триального окна же нет. Но на своей практике я уже неоднократно сталкивался с тем, что после распаковки на одном компьютере программа считает себя зарегистрированной, а на другом распакованный файл продолжает работать как триалка. Это связано с тем, что в файле все равно могут оставаться некоторые функции протектора, и запрашиваемые им адреса памяти на разных машинах могут отличаться.


Окно "О программе"

Для однозначного решения этой проблемы надо сделать так, чтобы программа на свой запрос всегда получала какое-нибудь регистрационное имя, лучше всего наше. В конце концов мы же ее адаптируем, так сделаем это по полной программе. Посмотрим в дизассемблере, как и при каких условиях появляется строка о незарегистрированной программе:
; Проверить первый байт строки, на которую ссылается указатель dword_440BD0
.text:00401269                 mov     edx, ds:dword_440BD0
.text:0040126F                 movsx   eax, byte ptr [edx]
.text:00401272                 test    eax, eax
; Если строка пустая (регистрационного имени нет), то программа триальная
.text:00401274                 jz      short loc_4012C9
; Иначе вывести строку "Зарегистрирована на..."
.text:00401276                 push    0               ; nCmdShow
.text:00401278                 push    403h            ; nIDDlgItem
.text:0040127D                 mov     ecx, [ebp+hWnd]
.text:00401280                 push    ecx             ; hDlg
.text:00401281                 call    GetDlgItem
.text:00401287                 push    eax             ; hWnd
.text:00401288                 call    ShowWindow
; Указатель на строку регистрационного имени
.text:0040128E                 mov     edx, ds:dword_440BD0
.text:00401294                 push    edx
.text:00401295                 push    offset aRegisteredToS
; "Registered to :\n%s"
.text:0040129A                 lea     eax, [ebp+String]
.text:004012A0                 push    eax
.text:004012A1                 call    wsprintfA
.text:004012A7                 add     esp, 0Ch
.text:004012AA                 lea     ecx, [ebp+String]
.text:004012B0                 push    ecx             ; lpString
.text:004012B1                 push    401h            ; nIDDlgItem
.text:004012B6                 mov     edx, [ebp+hWnd]
.text:004012B9                 push    edx             ; hDlg
.text:004012BA                 call    GetDlgItem
.text:004012C0                 push    eax             ; hWnd
.text:004012C1                 call    SetWindowTextA
.text:004012C7                 jmp     short loc_40133E
.text:004012C9 ; -------------------------------------------------------
.text:004012C9 loc_4012C9:
.text:004012C9                 mov     eax, ds:dword_429004
.text:004012CE                 push    eax
.text:004012CF                 push    offset aUnregisteredVe
; "Unregistered version!\nYou can use this "...
.text:004012D4                 lea     ecx, [ebp+String]
.text:004012DA                 push    ecx
.text:004012DB                 call    wsprintfA

Все понятно. Проверяется строка регистрационного имени, на которую ссылается указатель по адресу 00440BD0. Как я уже говорил выше, этот указатель в нормальных условиях инициализируется протектором, но протектор мы уже сняли, поэтому надо проинициализировать указатель самостоятельно. Поищем наиболее удобное место, где это можно сделать.


Перекрестные ссылки на указатель

По перекрестным ссылкам находим команду, которая записывает EAX в указатель. Казалось бы - вот оно, но не тут-то было. Это всего лишь "мертвый" код, оставшийся от протектора. Он никогда не получит управления, а значит что-то исправлять там бесполезно. Самый лучший вариант - это заменить какую-нибудь его проверку на инициализацию. По другим перекрестным ссылкам находим код, в котором раньше всего выполняется проверка:
.text:0041BBFE                 push    ebp
.text:0041BBFF                 mov     ebp, esp
; Если указатель пустой, то запустить игру
.text:0041BC01                 cmp     ds:dword_440BD0, 0
.text:0041BC08                 jz      short loc_41BC26
; Если указатель есть, но строка пустая, то показать триальное окно
.text:0041BC0A                 mov     eax, ds:dword_440BD0
.text:0041BC0F                 movsx   ecx, byte ptr [eax]
.text:0041BC12                 test    ecx, ecx
.text:0041BC14                 jnz     short loc_41BC26
.text:0041BC16                 call    sub_40CF5E
; По выбранной кнопке в триальном окне или выход, или играем
.text:0041BC1B                 test    eax, eax
.text:0041BC1D                 jz      short loc_41BC26
.text:0041BC1F                 push    1               ; Code
.text:0041BC21                 call    _exit
.text:0041BC26 ; ----------------------------------------
.text:0041BC26 loc_41BC26:
.text:0041BC26                 call    sub_410EC4
.text:0041BC2B                 pop     ebp
.text:0041BC2C                 retn
.text:0041BC2C sub_41BBFE      endp

Теперь мы знаем, почему пропало триальное окно при старте. Указатель пустой, значит сразу выполняется переход на запуск игры. Вот сюда мы и поместим инициализацию, но сперва надо имплантировать регистрационное имя прямо в исполняемый файл. Мы уже так делали, и на этот раз точно так же перебьем строку сообщения о незарегистрированной программе на наше имя. Не забывайте, что строка должна быть в формате ASCIIZ!


Заменяем строку регистрационного имени

Осталось заменить код по адресу 0041BC01 на команды MOV DWORD [440BD0h], 427094h и заNOPить оставшиеся куски проверки, чтобы не нарушать логику программы. Условный переход по адресу 0041BC14 надо заменить на безусловный, чтобы после инициализации регистрациионного имени сразу же запускалась игра.


Прописываем адрес строки

Сохраняем изменения, снова запускаем игру. Триального окна все так же нет, заглянем в окно "О программе". Какая прелесть!


Программа успешно "зарегистрирована"

Вот так мы осуществили действия, необходимые для функционирования программы или базы данных в соответствии с их назначением. А именно внесли в программу для ЭВМ или базу данных изменения исключительно в целях их функционирования на технических средствах пользователя. Как говорил Остап Бендер: "Уголовный кодекс надо чтить!"
Теги:
защита, взлом
Добавлено: 16 Сентября 2013 02:25:23 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...