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

Скриншот программы Cool ASCII
Программа Cool ASCII - простенький редактор для рисования изображений ASCII-символами, а также для преобразования графических файлов из формата BMP в цветные "картины" в виде HTML-страниц. На выходе получаются, например, такие или такие интересные результаты. Но настоящий художник должен быть голодным, так что будем избавлять эту программу от необходимости выкладывать за нее бабло.
Загружаем дистрибутив, устанавливаем, запускаем. Программа радостно сообщает, что она не зарегистрирована и поэтому будет запускаться только 10 раз, после чего понадобится сходить в кассу. После запуска посмотрим, как программа реагирует на неправильный серийный номер.

Окно регистрации программы
Отлично, теперь мы знаем нехорошую строку: "Sorry, the registration code is not correct. Please try again." Переходим к анализу исполняемого файла. Он упакован пакером ASPack, который легко снимается вручную или при помощи автоматических распаковщиков, здесь никаких проблем быть не должно. Строка о неправильной регистрации тоже лежит в открытом виде:

Нехорошая строка найдена
Загоняем распакованный файл в дизассемблер, чтобы более подробно выяснить при каких условиях она появляется.
Code (Assembler) : Убрать нумерацию
- ...
- CODE:004CCD81 mov fs:[eax], esp
- CODE:004CCD84 lea edx, [ebp-4]
- CODE:004CCD87 mov eax, [ebx+314h]
- CODE:004CCD8D call sub_47812C
- CODE:004CCD92 mov edx, [ebp-4]
- ; Проверить позицию подстроки "YI-9V" в строке серийного номера
- CODE:004CCD95 mov eax, offset aYi9v_0 ; "YI-9V"
- CODE:004CCD9A call sub_404F5C
- CODE:004CCD9F test eax, eax
- ; Если подстроки нет, то EAX=-1
- CODE:004CCDA1 jle loc_4CCE2E
- CODE:004CCDA7 mov edx, [ebp-4]
- ; Проверить позицию подстроки "7" в строке серийного номера
- CODE:004CCDAA mov eax, offset a7_0 ; "7"
- CODE:004CCDAF call sub_404F5C
- CODE:004CCDB4 test eax, eax
- ; Если подстроки нет, то EAX=-1
- CODE:004CCDB6 jle short loc_4CCE2E
- CODE:004CCDB8 mov edx, ds:off_4D0008
- CODE:004CCDBE mov edx, [edx]
- CODE:004CCDC0 lea eax, [ebp-8]
- ; Записать введенный регистрационный номер в файл
- CODE:004CCDC3 mov ecx, offset aDataCa_id_0 ; "\\Data\\ca.id"
- CODE:004CCDC8 call sub_404C64
- CODE:004CCDCD mov eax, [ebp-8]
- CODE:004CCDD0 mov edx, [ebp-4]
- CODE:004CCDD3 call sub_4C7C78
- CODE:004CCDD8 mov eax, ds:off_4D02F4
- CODE:004CCDDD mov eax, [eax]
- CODE:004CCDDF add eax, 31Ch
- CODE:004CCDE4 mov edx, offset aThanksForYou_0
- ; "Thanks for your register. If you have a"...
- CODE:004CCDE9 call sub_4049AC
- CODE:004CCDEE mov eax, ds:off_4D02F4
- CODE:004CCDF3 mov eax, [eax]
- CODE:004CCDF5 mov eax, [eax+2FCh]
- CODE:004CCDFB xor edx, edx
- CODE:004CCDFD call sub_4461CC
- CODE:004CCE02 mov eax, ds:off_4D02F4
- CODE:004CCE07 mov eax, [eax]
- CODE:004CCE09 mov eax, [eax+2F8h]
- CODE:004CCE0F mov dl, 1
- CODE:004CCE11 call sub_4461CC
- CODE:004CCE16 mov eax, ds:off_4D02F4
- CODE:004CCE1B mov eax, [eax]
- CODE:004CCE1D mov edx, [eax]
- CODE:004CCE1F call dword ptr [edx+0ECh]
- CODE:004CCE25 mov eax, ebx
- CODE:004CCE27 call sub_46288C
- CODE:004CCE2C jmp short loc_4CCE7B
- CODE:004CCE2E ; -----------------------------------------------------
- CODE:004CCE2E loc_4CCE2E:
- CODE:004CCE2E mov eax, ds:off_4D02F4
- CODE:004CCE33 mov eax, [eax]
- CODE:004CCE35 add eax, 31Ch
- ; Сообщение о неправильном серийном номере
- CODE:004CCE3A mov edx, offset aSorryTheRegi_0
- ; "Sorry, the registration code is not cor"...
- CODE:004CCE3F call sub_4049AC
- CODE:004CCE44 mov eax, ds:off_4D02F4
- CODE:004CCE49 mov eax, [eax]
- CODE:004CCE4B mov eax, [eax+2FCh]
- ...

Сообщение об успешной регистрации
Закрываем программу, запускаем ее снова. Опа! Триальное окно на месте, счетчик запусков продолжает тикать. Значит где-то должны быть еще какие-то проверки. Вернемся к коду регистрации, посмотрим на него повнимательнее. Мы видим, что регистрационные данные записываются в файл "\Data\ca.id", для верности можно сходить в эту папку и убедиться, что мы не ошиблись. Логично предположить, что раз туда сохраняется серийный номер, то он должен где-то читаться и проверяться. Поищем это место в дизассемблере по строке "ca.id". Немного ниже по коду находится аналогичная проверка с записью серийника в файл, видимо тупо продублирована процедура регистрации с заходом из другого места. Ее мы пропускаем. А еще ниже находятся интересные манипуляции с файлом ca.id:
Code (Assembler) : Убрать нумерацию
- ...
- CODE:004CD238 call sub_403B28
- CODE:004CD23D mov edx, ds:off_4D0008
- CODE:004CD243 mov edx, [edx]
- CODE:004CD245 lea eax, [ebp-8]
- CODE:004CD248 mov ecx, offset aDataCa_id_1 ; "\\Data\\ca.id"
- CODE:004CD24D call sub_404C64
- CODE:004CD252 mov eax, [ebp-8]
- CODE:004CD255 lea edx, [ebp-4]
- CODE:004CD258 call sub_4C7D14
- CODE:004CD25D mov edx, [ebp-4]
- ; Проверить позицию подстроки "A" в строке серийного номера
- CODE:004CD260 mov eax, offset aA ; "A"
- CODE:004CD265 call sub_404F5C
- CODE:004CD26A test eax, eax
- ; Если подстроки нет, то EAX=-1
- CODE:004CD26C jle short loc_4CD290
- CODE:004CD26E mov edx, [ebp-4]
- ; Проверить позицию подстроки "9" в строке серийного номера
- CODE:004CD271 mov eax, offset a9 ; "9"
- CODE:004CD276 call sub_404F5C
- CODE:004CD27B test eax, eax
- ; Если подстроки нет, то EAX=-1
- CODE:004CD27D jle short loc_4CD290
- CODE:004CD27F mov edx, [ebp-4]
- ; Проверить позицию подстроки "CY" в строке серийного номера
- CODE:004CD282 mov eax, offset aCy ; "CY"
- CODE:004CD287 call sub_404F5C
- CODE:004CD28C test eax, eax
- ; Если подстроки нет, то EAX=-1
- CODE:004CD28E jg short loc_4CD29F
- CODE:004CD290 loc_4CD290:
- CODE:004CD290 mov eax, ds:off_4D037C
- CODE:004CD295 mov eax, [eax]
- CODE:004CD297 mov edx, [eax]
- CODE:004CD299 call dword ptr [edx+0ECh]
- CODE:004CD29F loc_4CD29F:
- CODE:004CD29F xor eax, eax
- CODE:004CD2A1 pop edx
- CODE:004CD2A2 pop ecx
- CODE:004CD2A3 pop ecx
- CODE:004CD2A4 mov fs:[eax], edx
- CODE:004CD2A7 push offset loc_4CD2C1
- CODE:004CD2AC loc_4CD2AC:
- CODE:004CD2AC lea eax, [ebp-8]
- CODE:004CD2AF mov edx, 2
- CODE:004CD2B4 call sub_40497C
- CODE:004CD2B9
- ...

Программа успешно зарегистрирована
На этот раз триальное окно не появляется, значит регистрация считается полностью валидной. Осталось посмотреть, где программа хранит свой триальный счетчик. Для этого найдем место, где формируется строка с указанием количества оставшихся запусков:
Code (Assembler) : Убрать нумерацию
- ...
- CODE:004CCAB4 mov eax, off_438EEC
- CODE:004CCAB9 call sub_438FEC
- CODE:004CCABE mov esi, eax
- CODE:004CCAC0 mov edx, 80000002h
- CODE:004CCAC5 mov eax, esi
- CODE:004CCAC7 call sub_43908C
- CODE:004CCACC mov cl, 1
- ; Открыть ветку реестра HKLM\SOFTWARE\Microsoft\Direcs3D\
- ; "Direcs3D" - это не опечатка, именно в этой ветке прячется триальный счетчик
- CODE:004CCACE mov edx, offset aSoftwareMicros
- ; "\\SOFTWARE\\Microsoft\\Direcs3D\\"
- CODE:004CCAD3 mov eax, esi
- CODE:004CCAD5 call sub_4390F0
- CODE:004CCADA test al, al
- CODE:004CCADC jz loc_4CCC79
- CODE:004CCAE2 mov edx, offset aDirectdraw ; "DirectDraw"
- CODE:004CCAE7 mov eax, esi
- CODE:004CCAE9 call sub_43940C
- CODE:004CCAEE test al, al
- CODE:004CCAF0 jnz short loc_4CCB2B
- CODE:004CCAF2 call sub_40B358
- CODE:004CCAF7 add esp, 0FFFFFFF8h
- CODE:004CCAFA fstp qword ptr [esp]
- CODE:004CCAFD wait
- CODE:004CCAFE lea eax, [ebp-1Ch]
- CODE:004CCB01 call sub_40BF6C
- CODE:004CCB06 mov eax, [ebp-1Ch]
- CODE:004CCB09 lea edx, [ebp-18h]
- CODE:004CCB0C call sub_4CC6B8
- CODE:004CCB11 lea eax, [ebp-18h]
- CODE:004CCB14 lea edx, [ebp-8]
- CODE:004CCB17 call sub_4CC72C
- CODE:004CCB1C mov ecx, [ebp-8]
- CODE:004CCB1F mov edx, offset aDirectdraw ; "DirectDraw"
- CODE:004CCB24 mov eax, esi
- CODE:004CCB26 call sub_43928C
- CODE:004CCB2B loc_4CCB2B:
- CODE:004CCB2B mov edx, offset aDirectinput ; "DirectInput"
- CODE:004CCB30 mov eax, esi
- CODE:004CCB32 call sub_43940C
- CODE:004CCB37 test al, al
- CODE:004CCB39 jnz short loc_4CCB67
- CODE:004CCB3B lea edx, [ebp-18h]
- CODE:004CCB3E mov eax, offset dword_4CCD08
- CODE:004CCB43 call sub_4CC6B8
- CODE:004CCB48 lea eax, [ebp-18h]
- CODE:004CCB4B lea edx, [ebp-20h]
- CODE:004CCB4E call sub_4CC72C
- CODE:004CCB53 mov ecx, [ebp-20h]
- CODE:004CCB56 mov edx, offset aDirectinput ; "DirectInput"
- CODE:004CCB5B mov eax, esi
- CODE:004CCB5D call sub_43928C
- CODE:004CCB62 jmp loc_4CCC79
- CODE:004CCB67 ; --------------------------------------------------
- CODE:004CCB67 loc_4CCB67:
- CODE:004CCB67 lea ecx, [ebp-4]
- CODE:004CCB6A mov edx, offset aDirectinput ; "DirectInput"
- CODE:004CCB6F mov eax, esi
- CODE:004CCB71 call sub_4392B8
- CODE:004CCB76 mov ebx, 1
- CODE:004CCB7B loc_4CCB7B:
- CODE:004CCB7B lea edx, [ebp-28h]
- CODE:004CCB7E mov eax, ebx
- CODE:004CCB80 call sub_40940C
- CODE:004CCB85 lea eax, [ebp-28h]
- CODE:004CCB88 push eax
- CODE:004CCB89 lea edx, [ebp-2Ch]
- CODE:004CCB8C mov eax, ebx
- CODE:004CCB8E call sub_40940C
- CODE:004CCB93 mov edx, [ebp-2Ch]
- CODE:004CCB96 pop eax
- CODE:004CCB97 call sub_404C20
- CODE:004CCB9C mov eax, [ebp-28h]
- CODE:004CCB9F lea edx, [ebp-18h]
- CODE:004CCBA2 call sub_4CC6B8
- CODE:004CCBA7 lea eax, [ebp-18h]
- CODE:004CCBAA lea edx, [ebp-24h]
- CODE:004CCBAD call sub_4CC72C
- CODE:004CCBB2 mov edx, [ebp-24h]
- CODE:004CCBB5 mov eax, [ebp-4]
- CODE:004CCBB8 call sub_404D64
- CODE:004CCBBD jz short loc_4CCBC5
- CODE:004CCBBF inc ebx
- CODE:004CCBC0 cmp ebx, 0Ah
- CODE:004CCBC3 jnz short loc_4CCB7B
- CODE:004CCBC5 loc_4CCBC5:
- CODE:004CCBC5 cmp ebx, 0Ah
- CODE:004CCBC8 jnz short loc_4CCBF6
- CODE:004CCBCA mov dword ptr [edi+31Ch], 1
- CODE:004CCBD4 mov eax, [edi+304h]
- CODE:004CCBDA xor edx, edx
- CODE:004CCBDC mov ecx, [eax]
- CODE:004CCBDE call dword ptr [ecx+64h]
- CODE:004CCBE1 mov eax, [edi+2FCh]
- CODE:004CCBE7 mov edx, offset aYouHaveUsed10T
- ; "You have used 10 times."
- CODE:004CCBEC call sub_4462DC
- CODE:004CCBF1 jmp loc_4CCC79
- CODE:004CCBF6 ; -----------------------------------------------------
- CODE:004CCBF6 loc_4CCBF6:
- CODE:004CCBF6 xor eax, eax
- CODE:004CCBF8 mov [edi+31Ch], eax
- CODE:004CCBFE push offset aYouHaveUsed ; "You have used "
- CODE:004CCC03 lea edx, [ebp-34h]
- CODE:004CCC06 lea eax, [ebx+1]
- CODE:004CCC09 call sub_40940C
- CODE:004CCC0E push dword ptr [ebp-34h]
- CODE:004CCC11 push offset aTimes_ ; " times."
- CODE:004CCC16 lea eax, [ebp-30h]
- CODE:004CCC19 mov edx, 3
- CODE:004CCC1E call sub_404CD8
- CODE:004CCC23 mov edx, [ebp-30h]
- ...
Просмотров: 4285 | Комментариев: 10
Метки: исследование защиты

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье

ezfalc0n
(03.04.2011 в 04:30):
Согласен, Дима, в этом случае кейген по человеко-часам сопоставим с патчем.

ManHunter
(29.03.2011 в 23:42):
Можно. Только тут была задача закейгенить, а не пропатчить.

paralvic(wasm.ru)
(29.03.2011 в 23:09):
Всяко можно ещё JCC(условный переход) занопить.

AyTkACT
(28.03.2011 в 07:15):
ManHunter, красивый разбор проверки. Приятно почитать.

Jadavin
(27.03.2011 в 22:59):
Спасибо. )

Super_DJ
(27.03.2011 в 17:37):
Давно не встречал подобных прог, а тут и лечение есть =)
Респект!
Респект!

sj3.14159
(27.03.2011 в 17:18):
True программа, хорошая статья. Спасибо.

ManHunter
(27.03.2011 в 15:01):
Поднимаю свои варезные архивы :) А где встретил уже и не упомню, давно дело было.

Rustamer
(27.03.2011 в 14:57):
Спасибо. Весьма интересная программа. Если не секрет, где ты ее встретил?

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

Поймать в отладчике наг и перепрыгнуть его сопоставимо с разбором?
- Извените