Исследование защиты игры AxySnake
Скриншот игры AxySnake
Что-то давненько на разделочном столе нашей лаборатории не было никаких игрушек. Игра AxySnake - это классическая "змейка", но только трехмерная и в режиме "от третьего лица". Отличная графика, приятная озвучка, множество игровых локаций и всяких бонусов. В незарегистрированном варианте доступны не все игровые возможности, плюс показываются всякие нехорошие надписи и ненужные окна.
Забираем с офсайта дистрибутив, устанавливаем, запускаем. Сразу появляется окно с предложением зарегистрироваться. На ввод левых данных игрушка реагирует следующим сообщением:
Сообщение о неправильной регистрации
Если поискать это сообщение в основном файле, то ничего не будет найдено. Зато поиском по всем файлам эта строка обнаружится в файле proton.dll. Видимо, какая-то игра слов от "protection". Убедившись еще раз, что никаких навесных наворотов на нем нет, отправляем файл динамической библиотеки в дизассемблер.
Окно с сообщением в ресурсах
Но строчка находится не просто в файле, а в ресурсах, да еще и в диалоговом окне. И называется это окно "REG_FAULT". Теперь переходим в дизассемблер и поищем там строчку с названием ресурса окна.
Code (Assembler) : Убрать нумерацию
- ; Вызвать функцию проверки
- .text:1000FB04 call sub_10010960
- ; Если она вернула EAX=0, то введенный серийник неправильный
- .text:1000FB09 test eax, eax
- .text:1000FB0B jnz short loc_1000FB4E
- .text:1000FB0D push eax ; uType
- .text:1000FB0E call ds:MessageBeep
- .text:1000FB14 mov edx, hInstance
- .text:1000FB1A push 0 ; dwInitParam
- .text:1000FB1C push offset sub_1000E010 ; lpDialogFunc
- .text:1000FB21 push esi ; hWndParent
- .text:1000FB22 push offset aReg_fault ; "REG_FAULT"
- .text:1000FB27 push edx ; hInstance
- .text:1000FB28 call edi ; DialogBoxParamA
- .text:1000FB2A test eax, eax
- .text:1000FB2C jz short loc_1000FB9B
- .text:1000FB2E push 64h ; dwMilliseconds
- .text:1000FB30 call ebx ; Sleep
- .text:1000FB32 mov eax, hInstance
- .text:1000FB37 push 0 ; dwInitParam
- .text:1000FB39 push offset sub_1000E670 ; lpDialogFunc
- .text:1000FB3E push esi ; hWndParent
- .text:1000FB3F push offset aReg_dialog ; "REG_DIALOG"
- .text:1000FB44 push eax ; hInstance
- .text:1000FB45 call edi ; DialogBoxParamA
- .text:1000FB47 cmp eax, 1
- .text:1000FB4A jz short loc_1000FB04
- .text:1000FB4C jmp short loc_1000FB9B
- .text:1000FB4E ; ---------------------------------------
- .text:1000FB4E loc_1000FB4E:
- .text:1000FB4E call sub_100066B0
- .text:1000FB53 mov ecx, dword_1003D5CC
- .text:1000FB59 mov edx, [ecx+18h]
- .text:1000FB5C push edx ; phkResult
- .text:1000FB5D call sub_10010820
- .text:1000FB62 mov eax, hInstance
- .text:1000FB67 add esp, 4
- .text:1000FB6A mov ebx, 1
- .text:1000FB6F push 0 ; dwInitParam
- .text:1000FB71 push offset sub_1000E010 ; lpDialogFunc
- .text:1000FB76 push esi ; hWndParent
- .text:1000FB77 push offset aReg_ok ; "REG_OK"
- .text:1000FB7C push eax ; hInstance
- .text:1000FB7D mov dword_1003D5D0, ebx
- .text:1000FB83 call edi ; DialogBoxParamA
Code (Assembler) : Убрать нумерацию
- .text:10010960 sub_10010960 proc near
- .text:10010960 mov eax, dword_1003D4B8
- .text:10010965 test eax, eax
- .text:10010967 jz loc_10010A4E
- .text:1001096D mov ecx, dword_1003D4BC
- .text:10010973 test ecx, ecx
- .text:10010975 jz loc_10010A4E
- .text:1001097B push offset byte_10132938
- .text:10010980 push offset byte_1003D458
- .text:10010985 mov byte_1003D458[eax], 0
- ; Проверить корректность регистрационного имени
- .text:1001098C call sub_100108E0
- .text:10010991 add esp, 8
- .text:10010994 test eax, eax
- .text:10010996 jz loc_10010A4E
- .text:1001099C push offset Data
- ; Проверить корректность формата регистрационного номера
- .text:100109A1 call sub_10010890
- .text:100109A6 add esp, 4
- .text:100109A9 test eax, eax
- .text:100109AB jz loc_10010A4E
Code (Assembler) : Убрать нумерацию
- .text:100109B1 mov ecx, 49h
- .text:100109B6 xor eax, eax
- .text:100109B8 loc_100109B8:
- .text:100109B8 movsx edx, byte_10132938[eax]
- .text:100109BF add ecx, edx
- .text:100109C1 inc eax
- .text:100109C2 cmp eax, 10h
- .text:100109C5 jl short loc_100109B8
- .text:100109C7 xor eax, eax
- .text:100109C9 loc_100109C9:
- .text:100109C9 movsx edx, byte_10132918[eax]
- .text:100109D0 movsx edx, byte_1002DBB0[edx]
- .text:100109D7 add ecx, edx
- .text:100109D9 inc eax
- .text:100109DA cmp eax, 11h
- .text:100109DD jl short loc_100109C9
- .text:100109DF mov al, byte_10132929
- .text:100109E4 and ecx, 1Fh
- .text:100109E7 cmp al, cl
- .text:100109E9 jnz short loc_10010A4E
Code (Assembler) : Убрать нумерацию
- .text:100109EB mov ecx, 32h
- .text:100109F0 xor eax, eax
- .text:100109F2 loc_100109F2:
- .text:100109F2 movsx edx, byte_10132938[eax]
- .text:100109F9 sub ecx, edx
- .text:100109FB inc eax
- .text:100109FC cmp eax, 10h
- .text:100109FF jl short loc_100109F2
- .text:10010A01 xor eax, eax
- .text:10010A03 loc_10010A03:
- .text:10010A03 movsx edx, byte_10132918[eax]
- .text:10010A0A movsx edx, byte_1002DBB0[edx]
- .text:10010A11 add ecx, edx
- .text:10010A13 inc eax
- .text:10010A14 cmp eax, 12h
- .text:10010A17 jl short loc_10010A03
- .text:10010A19 mov al, byte_1013292A
- .text:10010A1E and ecx, 1Fh
- .text:10010A21 cmp al, cl
- .text:10010A23 jnz short loc_10010A4E
Code (Assembler) : Убрать нумерацию
- .text:10010A25 mov ecx, 79h
- .text:10010A2A xor eax, eax
- .text:10010A2C loc_10010A2C:
- .text:10010A2C movsx edx, byte_10132918[eax]
- .text:10010A33 movsx edx, byte_1002DBB0[edx]
- .text:10010A3A sub ecx, edx
- .text:10010A3C inc eax
- .text:10010A3D cmp eax, 13h
- .text:10010A40 jl short loc_10010A2C
- .text:10010A42 mov al, byte_1013292B
- .text:10010A47 and ecx, 1Fh
- .text:10010A4A cmp al, cl
- .text:10010A4C jz short loc_10010A64
Code (Assembler) : Убрать нумерацию
- .text:10010A4E loc_10010A4E:
- .text:10010A4E push edi
- .text:10010A4F mov ecx, 1Ah
- .text:10010A54 xor eax, eax
- .text:10010A56 mov edi, offset byte_1003D458
- .text:10010A5B rep stosd
- .text:10010A5D mov ?bRegistered@@3HA, eax
- .text:10010A62 pop edi
- .text:10010A63 retn
- .text:10010A64 ; --------------------------------------------
- .text:10010A64 loc_10010A64:
- .text:10010A64 mov eax, 1
- .text:10010A69 mov ?bRegistered@@3HA, eax
- .text:10010A6E retn
- .text:10010A6E sub_10010960 endp
Программа успешно зарегистрирована
Запускаем игру, и... Не тут-то было. Получаем сообщение, что серийный номер неправильный. В динамической библиотеке проверок больше нет, значит мы как раз напоролись на следующий уровень защиты. Отправляем в дизассемблер главный исполняемый файл. Находим в нем строчки сообщения о некорректном серийном номере.
Code (Assembler) : Убрать нумерацию
- .text:00416D60 sub esp, 10h
- .text:00416D63 push ebx
- .text:00416D64 push ebp
- .text:00416D65 push esi
- .text:00416D66 push edi
- .text:00416D67 xor edi, edi
- .text:00416D69 push edi
- .text:00416D6A call ds:?TextCls@@YAXK@Z ; TextCls(ulong)
- .text:00416D70 mov esi, ds:?TextPrint@@YAXPADKKKK@Z
- .text:00416D76 push 1
- .text:00416D78 push edi
- .text:00416D79 push 0FF0000h
- .text:00416D7E push 28h
- .text:00416D80 push offset aLicenseAgreeme
- ; " LICENSE AGREEMENT VIOLATION ! "...
- .text:00416D85 call esi
- .text:00416D87 push 3
- .text:00416D89 push edi
- .text:00416D8A push 0FFFFh
- .text:00416D8F push 28h
- .text:00416D91 push offset aYouUseAnIncorr
- ; " You use an incorrect or "...
- .text:00416D96 call esi
- ...
Code (Assembler) : Убрать нумерацию
- .text:004123BF call ds:?GetRegCode@@YAPADXZ ; GetRegCode(void)
- .text:004123C5 mov ecx, 8
- .text:004123CA mov esi, eax
- .text:004123CC mov edi, offset byte_479D74
- .text:004123D1 xor eax, eax
- .text:004123D3 rep movsd
- .text:004123D5 pop edi
- .text:004123D6 mov dword_479D70, ebx
- .text:004123DC mov ecx, 4Dh
- .text:004123E1 pop esi
- .text:004123E2 loc_4123E2:
- .text:004123E2 movsx edx, byte_479D4C[eax]
- .text:004123E9 inc eax
- .text:004123EA cmp eax, 10h
- .text:004123ED lea ecx, [ecx+edx*2]
- .text:004123F0 jl short loc_4123E2
- .text:004123F2 mov al, byte_479D74
- .text:004123F7 and ecx, 1Fh
- .text:004123FA cmp al, cl
- .text:004123FC jz short loc_412406
Code (Assembler) : Убрать нумерацию
- .text:00412711 mov ecx, 307h
- .text:00412716 loc_412716:
- .text:00412716 movsx edx, byte_479D4C[eax]
- .text:0041271D sub ecx, edx
- .text:0041271F inc eax
- .text:00412720 cmp eax, 10h
- .text:00412723 jl short loc_412716
- .text:00412725 mov al, byte_479D75
- .text:0041272A and ecx, 1Fh
- .text:0041272D cmp al, cl
- .text:0041272F jz short loc_412740
Code (Assembler) : Убрать нумерацию
- .text:004152F5 mov ecx, 86h
- .text:004152FA xor eax, eax
- .text:004152FC loc_4152FC:
- .text:004152FC movsx edx, byte_479D4C[eax]
- .text:00415303 test al, 1
- .text:00415305 jz short loc_41530B
- .text:00415307 add ecx, edx
- .text:00415309 jmp short loc_415310
- .text:0041530B ; ---------------------------------------
- .text:0041530B loc_41530B:
- .text:0041530B neg edx
- .text:0041530D lea ecx, [ecx+edx*2]
- .text:00415310 loc_415310:
- .text:00415310 inc eax
- .text:00415311 cmp eax, 10h
- .text:00415314 jl short loc_4152FC
- .text:00415316 mov al, byte_479D76
- .text:0041531B and ecx, 1Fh
- .text:0041531E cmp al, cl
- .text:00415320 jz short loc_415330
Code (Assembler) : Убрать нумерацию
- .text:0040DF0C mov edx, 7
- .text:0040DF11 xor eax, eax
- .text:0040DF13 loc_40DF13:
- .text:0040DF13 movsx ecx, byte_479D4C[eax]
- .text:0040DF1A cmp eax, 8
- .text:0040DF1D jge short loc_40DF23
- .text:0040DF1F mov esi, ecx
- .text:0040DF21 jmp short loc_40DF2A
- .text:0040DF23 ; ---------------------------------------
- .text:0040DF23 loc_40DF23:
- .text:0040DF23 mov esi, 1
- .text:0040DF28 sub esi, ecx
- .text:0040DF2A loc_40DF2A:
- .text:0040DF2A imul esi, ecx
- .text:0040DF2D add edx, esi
- .text:0040DF2F inc eax
- .text:0040DF30 cmp eax, 10h
- .text:0040DF33 jl short loc_40DF13
- .text:0040DF35 mov al, byte_479D77
- .text:0040DF3A and edx, 1Fh
- .text:0040DF3D cmp al, dl
- .text:0040DF3F jz short loc_40DF50
Code (Assembler) : Убрать нумерацию
- .text:0040D794 mov ecx, 38Ch
- .text:0040D799 xor eax, eax
- .text:0040D79B loc_40D79B:
- .text:0040D79B movsx edx, byte_479D4C[eax]
- .text:0040D7A2 cmp eax, 9
- .text:0040D7A5 jge short loc_40D7AF
- .text:0040D7A7 lea edx, [edx+edx*2]
- .text:0040D7AA lea ecx, [ecx+edx*2]
- .text:0040D7AD jmp short loc_40D7BC
- .text:0040D7AF ; ---------------------------------------
- .text:0040D7AF loc_40D7AF:
- .text:0040D7AF lea esi, ds:0[edx*4]
- .text:0040D7B6 sub esi, edx
- .text:0040D7B8 neg esi
- .text:0040D7BA add ecx, esi
- .text:0040D7BC loc_40D7BC:
- .text:0040D7BC inc eax
- .text:0040D7BD cmp eax, 10h
- .text:0040D7C0 jl short loc_40D79B
- .text:0040D7C2 mov al, byte_479D78
- .text:0040D7C7 and ecx, 1Fh
- .text:0040D7CA cmp al, cl
Code (Assembler) : Убрать нумерацию
- .text:0040BD20 xor esi, esi
- .text:0040BD22 cmp eax, 3A98h
- .text:0040BD27 jle short loc_40BD91
- .text:0040BD29 mov al, byte_479D59
- .text:0040BD2E mov cl, byte_479D58
- .text:0040BD34 mov dl, byte_479D50
- .text:0040BD3A imul eax, ecx
- .text:0040BD3D mov cl, byte_479D4F
- .text:0040BD43 imul edx, ecx
- .text:0040BD46 mov cl, byte_479D4D
- .text:0040BD4C sub eax, edx
- .text:0040BD4E mov dl, byte_479D4E
- .text:0040BD54 imul edx, ecx
- .text:0040BD57 mov cl, byte_479D51
- .text:0040BD5D sub eax, edx
- .text:0040BD5F mov dl, byte_479D52
- .text:0040BD65 imul edx, ecx
- .text:0040BD68 mov cl, byte_479D80
- .text:0040BD6E add eax, edx
- .text:0040BD70 mov dl, byte_479D4C
- .text:0040BD76 sub eax, edx
- .text:0040BD78 sub eax, 0Dh
- .text:0040BD7B and eax, 1Fh
- .text:0040BD7E cmp cl, al
- .text:0040BD80 jz short loc_40BD91
Единственный плюс всех этих проверок в том, что код у них исключительно чистый, можно копировать алгоритм в кейген прямо из отладчика или из листинга дизассемблера. Автор молодец, подход к защите правильный, подвела слишком простая реализация. В качестве исключения для лучшего понимания материала статьи прилагаю готовый кейген с исходником.
Просмотров: 3299 | Комментариев: 8
Метки: исследование защиты, игры
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(29.07.2017 в 18:27):
Такое ощущение, что я тут кому-то что-то должен. Специально выложил кейген с исходником, открываешь исходник и смотришь, какие символы участвуют в проверке. Блок-схемы пусть рисуют учителя информатики в школе.
И все бесплатно, естественно. На этом сайте все делается исключительно в личное время, и как его расходовать, а также на что его расходовать - это мое дело. В интернете полно сайтов с хорошим годным контентом, прям куда ни ткни, каждый первый. Почему бы не выбрать себе что-нибудь из них?
А спиннеров тут точно не будет, так же как и видеообзоров.
И все бесплатно, естественно. На этом сайте все делается исключительно в личное время, и как его расходовать, а также на что его расходовать - это мое дело. В интернете полно сайтов с хорошим годным контентом, прям куда ни ткни, каждый первый. Почему бы не выбрать себе что-нибудь из них?
А спиннеров тут точно не будет, так же как и видеообзоров.
Анон
(29.07.2017 в 12:32):
Такое ощущение складывается что Вас при помощи пыток заставляют анализировать софт. В прошлый раз был минутный патч, в этот раз начало хорошее, а вот концовка в стиле "надоело копаться в этом ховне, пусть читатели сами последнюю проверку разбирают по полочкам".
Я очень надеюсь, что в следующий раз будет подробный разбор кода с комментариями. А если ещё и блок-схемы будут то это просто мечта начинающего (читать как юного) крекера!
Потом можно и видео на ютубчик пилить по этой теме, всяко лучше чем спинеры, летсплеи по Майнкрафту и распаковки хлама с али. Годный контент в массы!
Я очень надеюсь, что в следующий раз будет подробный разбор кода с комментариями. А если ещё и блок-схемы будут то это просто мечта начинающего (читать как юного) крекера!
Потом можно и видео на ютубчик пилить по этой теме, всяко лучше чем спинеры, летсплеи по Майнкрафту и распаковки хлама с али. Годный контент в массы!
ManHunter
(20.07.2017 в 07:06):
Между уровнями - это как раз 13-й символ серийника.
voffka
(20.07.2017 в 01:18):
Могу ошибаться, но там кажется еще проверки должны быть, после какого-то уровня. Давно смотрел, не помню.
Vladimir
(18.07.2017 в 22:40):
Вы сами как-то про блокировщики рекламы писали, что очень поощряете и одобряете.
А вообще я это просто в качестве мелкого багрепорта написал, движок ж у сайта вроде ваш собственный.
А вообще я это просто в качестве мелкого багрепорта написал, движок ж у сайта вроде ваш собственный.
ManHunter
(18.07.2017 в 22:34):
А почему сайт не в исключениях? :) Перезалил.
Vladimir
(18.07.2017 в 21:48):
У вас в урле к третьему по счёту изображению на странице содержится /ad/. Баннерорезки убивают картинку на раз.
Добавить комментарий
Заполните форму для добавления комментария
Подробные разборы, с принтскринами, подписями и пояснениями... Замечательный контент же, на самом деле.
И в целом сайт очень интересный, спасибо автору.