
Скриншот программы WinPatrol
Программа
WinPatrol - монитор безопасности системы, показывающий связи файлов, сервисы, программы из автозапуска, скрытые файлы, указанные ключи реестра и некоторую другую информацию, которая якобы способствует лучшей защите вашего компьютера. Особого доверия я к этой программе не испытываю, так как предпочитаю пользоваться только проверенным инструментарием, поэтому интерес у меня к ней исключительно исследовательский.
Скачиваем
дистрибутив, устанавливаем. Исполняемых файлов в папке с программой два, нас интересует только WinPatrolEx.exe, так как второй файл WinPatrol.exe, похоже, является сервисом мониторинга и для настроек вызывает именно WinPatrolEx.exe. Исполняемый файл ничем не упакован, отправим его в дизассемблер и, пока тот работает, посмотрим на поведение при неправильной регистрации и все такое. Часть функций доступна только в так называемой PLUS-версии, то есть после регистрации, а так WinPatrol прекрасно работает в бесплатном FREE-режиме. На ввод левого серийника программа реагирует следующим сообщением:

Окно регистрации программы
Юникодная строка сообщения находится в ресурсах файла WinPatrolEx.exe, пока никаких трудностей с исследованием у нас не возникает.

Нехорошая строка найдена
Строка в ресурсах имеет индекс 620, или 26Ch в шестнадцатеричной системе счисления. Поищем и дизассемблере то место, где используется этот индекс. Вот оно:
...
.text:0041EC77 push offset byte_44D5C0 ; lpString
.text:0041EC7C mov byte_44D5C0[ecx], 0
; Вызвать функцию проверки регистрации
.text:0041EC83 call sub_4086FE
.text:0041EC88 pop ecx
; Если она вернула EAX=0, то регистрация неправильная
.text:0041EC89 test eax, eax
.text:0041EC8B jnz short loc_41ECCC
.text:0041EC8D lea eax, [esp+668h+File]
.text:0041EC94 push eax
.text:0041EC95 push 26Ch ; int
; Загрузить строку сообщения из ресурсов
.text:0041EC9A mov ecx, 200h ; cchBufferMax
.text:0041EC9F call sub_4089D7
.text:0041ECA4 movzx eax, word_45619C
.text:0041ECAB pop ecx
.text:0041ECAC pop ecx
.text:0041ECAD push eax ; wLanguageId
.text:0041ECAE push 40040h ; uType
.text:0041ECB3 push offset Caption ; lpCaption
.text:0041ECB8 lea eax, [esp+674h+File]
.text:0041ECBF push eax ; lpText
.text:0041ECC0 push esi ; hWnd
; Вывести сообщение на экран
.text:0041ECC1 call ds:MessageBoxExA
...
Первый вариант решения - пропатчить функцию проверки, чтобы она всегда возвращала правильный результат. Пара команд MOV EAX,1 и RET по адресу 004086FE гарантированно решают проблему с регистрацией. Теперь программа работает в PLUS-режиме даже без ввода серийного номера. Но это слишком просто и неспортивно, поэтому лучше разберем алгоритм проверки серийного номера. Для этого в отладчике поставим точку останова по адресу 004086FE на начало функции проверки регистрации, а затем пройдем ее в пошаговом режиме.
Первая часть проверки. Длина серийного номера должна быть ровно 7 символов. Второй символ равен '@'+длина регистрационного имени.
.text:00408710 xor edi, edi
; Первая проверка - считается длина введенного регистрационного имени
.text:00408712 call esi ; lstrlenA
.text:00408714 mov ecx, [ebp+lpString]
; К длины значению прибавляется 40h ('@')
.text:00408717 add al, 40h
; Второй символ серийного номера должен быть '@'+(длина имени)
.text:00408719 cmp [ecx+1], al
.text:0040871C jnz loc_408807
.text:00408722 push ecx ; lpString
.text:00408723 inc edi
; Вторая проверка - длина серийного номера должна быть ровно 7 символов
.text:00408724 call esi ; lstrlenA
.text:00408726 cmp eax, 7
.text:00408729 jle short loc_408730
.text:0040872B xor edi, edi
.text:0040872D cmp eax, 7
.text:00408730 loc_408730:
.text:00408730 jge short loc_408734
.text:00408732 xor edi, edi
.text:00408734 loc_408734:
Едем дальше. Вторая часть проверки - регистрационное имя не должно быть в "черном списке". Похоже, что крякерская команда BRD (Black Riders) напрягала авторов особенно сильно.
; Проверки на запрещенные регистрационные имена. Привет крякерам :)
.text:00408734 mov esi, [ebp+lpString]
.text:00408737 mov edx, offset asc_446AB8 ; "-"
.text:0040873C mov ecx, esi ; lpString
.text:0040873E call sub_4326C2
.text:00408743 test eax, eax
.text:00408745 jz short loc_408749
.text:00408747 xor edi, edi
.text:00408749 loc_408749:
.text:00408749 mov edx, offset aFlintstone ; "Flintstone"
.text:0040874E mov ecx, ebx ; lpString
.text:00408750 call sub_4326C2
.text:00408755 test eax, eax
.text:00408757 jz short loc_40875B
.text:00408759 xor edi, edi
.text:0040875B loc_40875B:
.text:0040875B mov edx, offset aRadikalModds ; "Radikal Modds"
.text:00408760 mov ecx, ebx ; lpString
.text:00408762 call sub_4326C2
.text:00408767 test eax, eax
.text:00408769 jz short loc_40876D
.text:0040876B xor edi, edi
.text:0040876D loc_40876D:
.text:0040876D mov edx, offset aBrdCult ; "BRD Cult"
.text:00408772 mov ecx, ebx ; lpString
.text:00408774 call sub_4326C2
.text:00408779 test eax, eax
.text:0040877B jz short loc_40877F
.text:0040877D xor edi, edi
.text:0040877F loc_40877F:
.text:0040877F mov edx, offset aTeam ; "Team"
.text:00408784 mov ecx, ebx ; lpString
.text:00408786 call sub_4326C2
.text:0040878B test eax, eax
.text:0040878D jz short loc_408791
.text:0040878F xor edi, edi
.text:00408791 loc_408791:
Дальше проверяется каждый символ серийного номера. В листинге не совсем очевидно, но под отладчиком все становится понятно. 4-й и 7-й символы должны быть цифрами, а остальные - буквами от 'A' до 'Z'.
; Первый символ должен быть буквой 'A'-'Z'
.text:00408791 movsx eax, byte ptr [esi]
.text:00408794 push eax
.text:00408795 call sub_4016F2
.text:0040879A pop ecx
.text:0040879B test eax, eax
.text:0040879D jz short loc_4087A1
.text:0040879F xor edi, edi
.text:004087A1 loc_4087A1:
; Второй символ должен быть буквой 'A'-'Z'
.text:004087A1 movsx eax, byte ptr [esi+1]
.text:004087A5 push eax
.text:004087A6 call sub_4016F2
.text:004087AB pop ecx
.text:004087AC test eax, eax
.text:004087AE jz short loc_4087B2
.text:004087B0 xor edi, edi
.text:004087B2 loc_4087B2:
; Третий символ должен быть буквой 'A'-'Z'
.text:004087B2 movsx eax, byte ptr [esi+2]
.text:004087B6 push eax
.text:004087B7 call sub_4016F2
.text:004087BC pop ecx
.text:004087BD test eax, eax
.text:004087BF jz short loc_4087C3
.text:004087C1 xor edi, edi
.text:004087C3 loc_4087C3:
; Четвертый символ НЕ должен быть буквой 'A'-'Z'
.text:004087C3 movsx eax, byte ptr [esi+3]
.text:004087C7 push eax
.text:004087C8 call sub_4016F2
.text:004087CD pop ecx
.text:004087CE test eax, eax
.text:004087D0 jnz short loc_4087D4
.text:004087D2 xor edi, edi
.text:004087D4 loc_4087D4:
; Пятый символ должен быть буквой 'A'-'Z'
.text:004087D4 movsx eax, byte ptr [esi+4]
.text:004087D8 push eax
.text:004087D9 call sub_4016F2
.text:004087DE pop ecx
.text:004087DF test eax, eax
.text:004087E1 jz short loc_4087E5
.text:004087E3 xor edi, edi
.text:004087E5 loc_4087E5:
; Шестой символ должен быть буквой 'A'-'Z'
.text:004087E5 movsx eax, byte ptr [esi+5]
.text:004087E9 push eax
.text:004087EA call sub_4016F2
.text:004087EF pop ecx
.text:004087F0 test eax, eax
.text:004087F2 jz short loc_4087F6
.text:004087F4 xor edi, edi
.text:004087F6 loc_4087F6:
; Седьмой символ НЕ должен быть буквой 'A'-'Z'
.text:004087F6 movsx eax, byte ptr [esi+6]
.text:004087FA push eax
.text:004087FB call sub_4016F2
.text:00408800 pop ecx
.text:00408801 test eax, eax
.text:00408803 jnz short loc_408807
.text:00408805 xor edi, edi
.text:00408807 loc_408807:
; Код возврата после всех проверок
.text:00408807 mov eax, edi
.text:00408809 pop edi
.text:0040880A pop esi
.text:0040880B pop ebx
.text:0040880C pop ebp
.text:0040880D retn
Вот и весь алгоритм проверки. Так, к примеру, правильной регистрационной парой будут имя "ManHunter / PCL" и серийный номер "AOA7AA7". После ввода программа благодарит за регистрацию:

Программа успешно зарегистрирована
Но обратите внимание, что программа лезет сверять серийный номер на свой сайт (если интересно, то это функция по адресу 00434797, сразу же перед сообщением о правильной регистрации), поэтому в обязательном порядке WinPatrol надо блокировать на фаерволе. Вот такая не особо сложная, но, на мой взгляд, интересная защита. Кейген теперь вы можете написать самостоятельно.