
Скриншот программы ExtraCHM
ExtraCHM - неплохая замена стандартному просмотрщику CHM-файлов, который используется в Windows. Программа обладает удобным многовкладочным интерфейсом, возможностью поиска по файлу справки, даже если в нем отсутствует поисковый индекс, с помощью ExtraCHM можно декомпилировать CHM-файл и даже подключить его к голосовому движку для чтения содержимого. Такая куча ништяков просто обязана быть бесплатной, но аффтар почему-то имеет на этот счет другое мнение. Я же, в свою очередь, это мнение не поддерживаю.
Скачиваем
дистрибутив, устанавливаем, смотрим. Единственный исполняемый файл ничем не упакован, сразу отправляем его в дизассемблер, чтобы не терять время. Пока тот работает, проверим реакцию программы на неправильную регистрацию.

Сообщение о неправильной регистрации
Юникодная строка сообщения в исполняемом файле находится легко.
https://pp.vk.me/c9463/v9463982/3486/aunzz6_DhYY.jpg
Строка сообщения найдена
К этому времени дизассемблер закончил свою работу, и мы можем посмотреть участок кода, который ссылается на эту строку. Ну и конечно же посмотреть условия срабатывания этой ветки алгоритма.
; Вызывать функцию проверки регистрации
.text:0040C809 call sub_421F20
.text:0040C80E push 0 ; int
.text:0040C810 push 0 ; uType
; Если она вернула AL=0, то регистрация неправильная
.text:0040C812 test al, al
.text:0040C814 jnz short loc_40C822
.text:0040C816 push offset aThisDoesNotApp
; "This does not appear to be a valid regi"...
.text:0040C81B call ?AfxMessageBox@@YGHPB_WII@Z
; AfxMessageBox(wchar_t const *,uint,uint)
.text:0040C820 jmp short loc_40C85A
.text:0040C822 ; -----------------------------------------
.text:0040C822 loc_40C822:
; Сообщение об успешной регистрации
.text:0040C822 push offset aThankYouForReg
; "Thank you for registering your copy of "...
.text:0040C827 call ?AfxMessageBox@@YGHPB_WII@Z
; AfxMessageBox(wchar_t const *,uint,uint)
.text:0040C82C mov edi, dword_5E1DC0
Вся проверка уместилась в несколько строчек. Простой и максимально эффективный способ решения нашей проблемы - пропатчить функцию проверки по адресу
00421F20, записав в ее начало две любимые команды - MOV AL,1 и RET. После этого программа будет с радостью принимать любые регистрационные данные. Быстро, надежно, но некрасиво. Чтобы стало красиво, посмотрим функцию проверки введенных регистрационных данных. Желательно под отладчиком, так будет гораздо интереснее и понятнее.
.text:00421F20 push 0FFFFFFFFh
.text:00421F22 push offset loc_572C18
.text:00421F27 mov eax, large fs:0
.text:00421F2D push eax
.text:00421F2E sub esp, 78h
.text:00421F31 mov eax, dword_5D8760
.text:00421F36 xor eax, esp
.text:00421F38 mov [esp+84h+var_10], eax
.text:00421F3C push ebx
.text:00421F3D push esi
.text:00421F3E mov eax, dword_5D8760
.text:00421F43 xor eax, esp
.text:00421F45 push eax
.text:00421F46 lea eax, [esp+90h+var_C]
.text:00421F4D mov large fs:0, eax
.text:00421F53 xor ebx, ebx
.text:00421F55 mov esi, ecx
.text:00421F57 cmp [edi], bx
; Серийный номер вообще введен?
.text:00421F5A jz short loc_421FD2
; Вызвать функцию проверки серийного номера
.text:00421F5C push edi
.text:00421F5D call sub_421EB0
.text:00421F62 add esp, 4
.text:00421F65 test al, al
; Если он неправильный, то переход на возврат AL=0
.text:00421F67 jz short loc_421FD2
.text:00421F69 push 8 ; size_t
.text:00421F6B lea eax, [esp+94h+Buffer]
...
Дальше смотреть нет смысла, там только работа с файлом ключа и все такое прочее. Это неинтересно, так как непосредственно к проверке регистрации никак не относится. Зато нас интересует следующий уровень проверки - функция по адресу
00421EB0.
.text:00421EB0 push ecx
.text:00421EB1 mov eax, esi
; Подсчитать длину строки серийного номера
.text:00421EB3 lea edx, [eax+2]
.text:00421EB6 loc_421EB6:
.text:00421EB6 mov cx, [eax]
.text:00421EB9 add eax, 2
.text:00421EBC test cx, cx
.text:00421EBF jnz short loc_421EB6
.text:00421EC1 sub eax, edx
; Длина пополам, так как строка в юникоде
.text:00421EC3 sar eax, 1
; Первая проверка - длина серийного номера должна быть 8 символов
.text:00421EC5 cmp eax, 8
.text:00421EC8 jz short loc_421ECE
; Иначе выход с ошибкой
.text:00421ECA xor al, al
.text:00421ECC pop ecx
.text:00421ECD retn
.text:00421ECE ; -------------------------------------------------
.text:00421ECE loc_421ECE:
.text:00421ECE mov ecx, [esp+4+arg_0]
; Сгенерировать из регистрационного имени проверочную строку
.text:00421ED2 call sub_421E20
.text:00421ED7 mov [esp+4+var_4], eax
.text:00421EDA xor ecx, ecx
.text:00421EDC push edi
.text:00421EDD lea ecx, [ecx+0]
.text:00421EE0 loc_421EE0:
; Сравнить по два символа из серийного номера с проверочной строкой
.text:00421EE0 movzx eax, byte ptr [esp+ecx+8+var_4]
.text:00421EE5 movzx edx, word ptr [esi+ecx*4]
.text:00421EE9 mov edi, eax
.text:00421EEB and edi, 0Fh
.text:00421EEE add edi, 41h
; EDX = правильный символ серийного номера
.text:00421EF1 cmp edx, edi
; Не совпало, возврат с ошибкой
.text:00421EF3 jnz short loc_421F0F
.text:00421EF5 movzx edx, word ptr [esi+ecx*4+2]
.text:00421EFA shr eax, 4
.text:00421EFD add eax, 41h
; EDX = правильный символ серийного номера
.text:00421F00 cmp edx, eax
; Не совпало, возврат с ошибкой
.text:00421F02 jnz short loc_421F0F
.text:00421F04 inc ecx
; Проверить 4 пары (8 символов серийного номера)
.text:00421F05 cmp ecx, 4
.text:00421F08 jl short loc_421EE0
.text:00421F0A mov al, 1
.text:00421F0C pop edi
.text:00421F0D pop ecx
.text:00421F0E retn
.text:00421F0F ; ----------------------------------------------------
.text:00421F0F loc_421F0F:
.text:00421F0F xor al, al
.text:00421F11 pop edi
.text:00421F12 pop ecx
.text:00421F13 retn
Честно скажу, мне лениво разбирать процедуру получения проверочной строки из регистрационного имени. Поэтому ограничусь сниффингом правильного серийника под отладчиком. Для этого достаточно поставить точки останова по адресам
00421EF1 и
00421F00, ввести нужное имя и произвольный восьмизначный серийный номер, а затем за четыре прохода узнать все правильные символы. Так, для регистрационного имени "
manhunter@pcl" регистрационный код будет "
BCOFAFOK". Можно получить все символы и за один проход, достаточно в отладчике заменить условные переходы после сравнения символов на команды NOP. Проверим найденный серийный номер:

Программа успешно зарегистрирована
Все прекрасно работает. Точно так же вы можете подобрать серийный номер для любого другого имени. Но вариант с патчем тоже нельзя списывать со счетов, ведь в этом случае программа становится портативной.