Исследование защиты программы WinCHM Pro
Скриншот программы WinCHM
WinCHM - небольшой по размерам, но сильный по возможностям редактор для создания файлов справок в формате CHM, HLP а также PDF- и DOC-файлов. Про все возможности этой замечательной программы во можете почитать на офсайте, и там же вдруг обнаружится ссылка на страницу покупки. Туда ходить не надо, обойдемся своими силами.
Первым делом качаем дистрибутив, устанавливаем, запускаем. Сразу получаем триальное окно:
Триальное окно
Окей, введем какой-нибудь левак в качестве регистрационного имени и номера. Получаем сообщение "Illegal registration code!". Начальные данные для анализа у нас есть, переходим к стадии кодокопания. Файл ничем не упакован, поэтому сразу загоним его в дизассемблер, а пока тот работает, поищем нехорошую строчку.
Нехорошая строка найдена
Если приглядеться повнимательнее, то там же рядышком есть сообщение об успешной регистрации, а также какие-то интересные строки типа названий ключей реестра для хранения регистрационных данных, строки с вариантами лицензий программы и т.п. В дизассемблере смотрим откуда это все добро запрашивается:
Code (Assembler) : Убрать нумерацию
- ...
- CODE:0051017E mov eax, ebx
- CODE:00510180 call sub_403574
- CODE:00510185 call sub_50FB80
- ; Проверить, если DWORD по адресу 54B184 имеет не нулевое значение,
- ; то программа считается зарегистрированной
- CODE:0051018A mov eax, ds:off_54B184
- CODE:0051018F cmp dword ptr [eax], 0
- CODE:00510192 jz short loc_5101EB
- ; Сообщение об удачной регистрации
- CODE:00510194 mov ecx, ds:off_54B184
- CODE:0051019A mov ecx, [ecx]
- CODE:0051019C lea eax, [ebp+var_4]
- CODE:0051019F mov edx, offset aThankYouForPur
- ; "Thank you for purchasing our product!\r\n"...
- CODE:005101A4 call sub_404670
- CODE:005101A9 mov eax, ds:off_54B4E8
- CODE:005101AE cmp dword ptr [eax], 1
- CODE:005101B1 jnz short loc_5101CF
- CODE:005101B3 push [ebp+var_4]
- CODE:005101B6 push offset dword_5102B8
- CODE:005101BB push offset aVersionWinchmP
- ; "Version: WinCHM Pro"
- CODE:005101C0 lea eax, [ebp+var_4]
- CODE:005101C3 mov edx, 3
- CODE:005101C8 call sub_4046E4
- CODE:005101CD jmp short loc_5101F8
- CODE:005101CF ; ------------------------------------------------------
- CODE:005101CF loc_5101CF:
- CODE:005101CF push [ebp+var_4]
- CODE:005101D2 push offset dword_5102B8
- CODE:005101D7 push offset aVersionWinchmS
- ; "Version: WinCHM (Standard)"
- CODE:005101DC lea eax, [ebp+var_4]
- CODE:005101DF mov edx, 3
- CODE:005101E4 call sub_4046E4
- CODE:005101E9 jmp short loc_5101F8
- CODE:005101EB ; ------------------------------------------------------
- ; Сообщение о некорректной регистрации
- CODE:005101EB loc_5101EB:
- CODE:005101EB lea eax, [ebp+var_4]
- CODE:005101EE mov edx, offset aIllegalRegistr
- ; Указатель на строку "Illegal registration code!"
- CODE:005101F3 call sub_4043E0
- ...
Code (Assembler) : Убрать нумерацию
- ...
- CODE:0050FC75 mov eax, [ebp+var_4]
- CODE:0050FC78 call sub_403574
- ; Загрузить в регистр EDX ссылку на регистрационный код из реестра
- CODE:0050FC7D mov edx, ds:off_54B33C
- CODE:0050FC83 mov edx, [edx]
- CODE:0050FC85 mov eax, ds:off_54B5E8
- ; Загрузить в регистр EAX ссылку на регистрационное имя из реестра
- CODE:0050FC8A mov eax, [eax]
- ; Передать результаты в какую-то функцию проверки
- CODE:0050FC8C call sub_50F3B4
- ; Результат проверки вернулся в регистре EAX
- CODE:0050FC91 mov ebx, eax
- CODE:0050FC93 mov eax, ebx
- ; Если EAX был = 0, то выполнится следующий условный переход
- CODE:0050FC95 sub eax, 1
- CODE:0050FC98 jb short loc_50FCA5
- ; Если EAX было = 1, то будет переход на Single-user License
- CODE:0050FC9A jz short loc_50FCB1
- ; Если EAX было = 270Eh, то переход на Unlimited-user License
- CODE:0050FC9C sub eax, 270Eh
- CODE:0050FCA1 jz short loc_50FCC2
- ; Иначе переход на NN-user License
- CODE:0050FCA3 jmp short loc_50FCD3
- CODE:0050FCA5 ; -------------------------------------------------
- CODE:0050FCA5 loc_50FCA5:
- CODE:0050FCA5 mov eax, ds:off_54B184
- CODE:0050FCAA call sub_404348
- CODE:0050FCAF jmp short loc_50FCEF
- CODE:0050FCB1 ; -------------------------------------------------
- CODE:0050FCB1 loc_50FCB1:
- CODE:0050FCB1 mov eax, ds:off_54B184
- CODE:0050FCB6 mov edx, offset aSingleUserLice
- ; "Single-user License"
- CODE:0050FCBB call sub_40439C
- CODE:0050FCC0 jmp short loc_50FCEF
- CODE:0050FCC2 ; -------------------------------------------------
- CODE:0050FCC2 loc_50FCC2:
- CODE:0050FCC2 mov eax, ds:off_54B184
- CODE:0050FCC7 mov edx, offset aUnlimitedUserL
- ; "Unlimited-user License"
- CODE:0050FCCC call sub_40439C
- CODE:0050FCD1 jmp short loc_50FCEF
- CODE:0050FCD3 ; -------------------------------------------------
- CODE:0050FCD3 loc_50FCD3:
- CODE:0050FCD3 lea edx, [ebp+var_18]
- CODE:0050FCD6 mov eax, ebx
- CODE:0050FCD8 call sub_4094E8
- CODE:0050FCDD mov edx, [ebp+var_18]
- CODE:0050FCE0 mov eax, ds:off_54B184
- CODE:0050FCE5 mov ecx, offset aUserLicense
- ; "-user License"
- CODE:0050FCEA call sub_404670
- CODE:0050FCEF loc_50FCEF:
- CODE:0050FCEF mov eax, ds:off_54B184
- CODE:0050FCF4 cmp dword ptr [eax], 0
- CODE:0050FCF7 jnz short loc_50FD0A
- CODE:0050FCF9 mov eax, ds:off_54B3B4
- CODE:0050FCFE mov edx, offset aUnregistered
- ; " [Unregistered]"
- CODE:0050FD03 call sub_40439C
- CODE:0050FD08 jmp short loc_50FD14
- ...
Code (Assembler) : Убрать нумерацию
- CODE:0050F3B4 push ebp
- CODE:0050F3B5 mov ebp, esp
- CODE:0050F3B7 mov ecx, 4
- CODE:0050F3BC loc_50F3BC:
- CODE:0050F3BC push 0
- CODE:0050F3BE push 0
- CODE:0050F3C0 dec ecx
- CODE:0050F3C1 jnz short loc_50F3BC
- CODE:0050F3C3 push ecx
- CODE:0050F3C4 push ebx
- CODE:0050F3C5 mov [ebp+var_8], edx
- CODE:0050F3C8 mov [ebp+var_4], eax
- CODE:0050F3CB mov eax, [ebp+var_4]
- CODE:0050F3CE call sub_404814
- CODE:0050F3D3 mov eax, [ebp+var_8]
- CODE:0050F3D6 call sub_404814
- CODE:0050F3DB xor eax, eax
- CODE:0050F3DD push ebp
- CODE:0050F3DE push offset loc_50F9B9
- CODE:0050F3E3 push dword ptr fs:[eax]
- CODE:0050F3E6 mov fs:[eax], esp
- CODE:0050F3E9 lea eax, [ebp+var_14]
- CODE:0050F3EC mov edx, [ebp+var_8]
- CODE:0050F3EF call sub_4043E0
- CODE:0050F3F4 mov eax, [ebp+var_14]
- CODE:0050F3F7 call sub_404624
- CODE:0050F3FC mov ebx, eax
- CODE:0050F3FE mov eax, ds:off_54B4E8
- CODE:0050F403 mov dword ptr [eax], 0FFFFFFFFh
- ; В регистр EAX занести ссылку на серийный номер
- CODE:0050F409 mov eax, [ebp+var_14]
- ; Вызвать очередную функцию проверки
- CODE:0050F40C call sub_50EBD0
- ; Результат функции возвращается в регистрах EDX и EAX
- CODE:0050F411 mov [ebp+var_10], eax
- CODE:0050F414 mov [ebp+var_C], edx
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F417 cmp [ebp+var_C], 0
- CODE:0050F41B jnz short loc_50F430
- ; Если EAX=2B77h, то результат всей функции будет 1
- CODE:0050F41D cmp [ebp+var_10], 2B77h
- CODE:0050F424 jnz short loc_50F430
- CODE:0050F426 mov ebx, 1
- CODE:0050F42B jmp loc_50F991
- CODE:0050F430 ; ----------------------------------------------
- CODE:0050F430 loc_50F430:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F430 cmp [ebp+var_C], 0
- CODE:0050F434 jnz short loc_50F449
- ; Если EAX=2B81h, то результат всей функции будет 2
- CODE:0050F436 cmp [ebp+var_10], 2B81h
- CODE:0050F43D jnz short loc_50F449
- CODE:0050F43F mov ebx, 2
- CODE:0050F444 jmp loc_50F991
- CODE:0050F449 ; ----------------------------------------------
- CODE:0050F449 loc_50F449:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F449 cmp [ebp+var_C], 0
- CODE:0050F44D jnz short loc_50F462
- ; Если EAX=2EF2h, то результат всей функции будет 3
- CODE:0050F44F cmp [ebp+var_10], 2EF2h
- CODE:0050F456 jnz short loc_50F462
- CODE:0050F458 mov ebx, 3
- CODE:0050F45D jmp loc_50F991
- CODE:0050F462 ; ----------------------------------------------
- CODE:0050F462 loc_50F462:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F462 cmp [ebp+var_C], 0
- CODE:0050F466 jnz short loc_50F47B
- ; Если EAX=2FA7h, то результат всей функции будет 5
- CODE:0050F468 cmp [ebp+var_10], 2FA7h
- CODE:0050F46F jnz short loc_50F47B
- CODE:0050F471 mov ebx, 5
- CODE:0050F476 jmp loc_50F991
- CODE:0050F47B ; ----------------------------------------------
- CODE:0050F47B loc_50F47B:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F47B cmp [ebp+var_C], 0
- CODE:0050F47F jnz short loc_50F494
- ; Если EAX=2D80h, то результат всей функции будет 10
- CODE:0050F481 cmp [ebp+var_10], 2D80h
- CODE:0050F488 jnz short loc_50F494
- CODE:0050F48A mov ebx, 0Ah
- CODE:0050F48F jmp loc_50F991
- CODE:0050F494 ; ----------------------------------------------
- CODE:0050F494 loc_50F494:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F494 cmp [ebp+var_C], 0
- CODE:0050F498 jnz short loc_50F4AD
- ; Если EAX=2CE2h, то результат всей функции будет 20
- CODE:0050F49A cmp [ebp+var_10], 2CE2h
- CODE:0050F4A1 jnz short loc_50F4AD
- CODE:0050F4A3 mov ebx, 14h
- CODE:0050F4A8 jmp loc_50F991
- CODE:0050F4AD ; ----------------------------------------------
- CODE:0050F4AD loc_50F4AD:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F4AD cmp [ebp+var_C], 0
- CODE:0050F4B1 jnz short loc_50F4C6
- ; Если EAX=388Ah, то результат всей функции будет 50
- CODE:0050F4B3 cmp [ebp+var_10], 388Ah
- CODE:0050F4BA jnz short loc_50F4C6
- CODE:0050F4BC mov ebx, 32h
- CODE:0050F4C1 jmp loc_50F991
- CODE:0050F4C6 ; ----------------------------------------------
- CODE:0050F4C6 loc_50F4C6:
- ; Если EDX не равен 0, то перейти к следующей проверке
- CODE:0050F4C6 cmp [ebp+var_C], 0
- CODE:0050F4CA jnz short loc_50F4DF
- ; Если EAX=25C1h, то результат всей функции будет 270Fh
- CODE:0050F4CC cmp [ebp+var_10], 25C1h
- CODE:0050F4D3 jnz short loc_50F4DF
- CODE:0050F4D5 mov ebx, 270Fh
- CODE:0050F4DA jmp loc_50F991
- ...
Code (Assembler) : Убрать нумерацию
- ...
- ; Счетчик символов
- CODE:0050EC1C mov ecx, 1
- CODE:0050EC21 loc_50EC21:
- ; Указатель на серийный номер
- CODE:0050EC21 mov eax, [ebp+var_14]
- ; Записать в EAX символ из серийного номера на позиции ECX
- CODE:0050EC24 movzx eax, byte ptr [eax+ecx-1]
- ; Умножить его код на значение ECX
- CODE:0050EC29 imul ecx
- CODE:0050EC2B cdq
- ; Прибавить к счетчику
- CODE:0050EC2C add eax, [ebp+var_20]
- CODE:0050EC2F adc edx, [ebp+var_1C]
- CODE:0050EC32 mov [ebp+var_20], eax
- CODE:0050EC35 mov [ebp+var_1C], edx
- ; Взять следующий символ
- CODE:0050EC38 inc ecx
- CODE:0050EC39 dec ebx
- ; Достигнут конец серийника?
- CODE:0050EC3A jnz short loc_50EC21
- ...
Просмотров: 5729 | Комментариев: 12
Метки: исследование защиты, файлы справки
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(22.09.2011 в 16:54):
В 4.21 опять константы сменили, кейген не подходит
Isaev
(22.09.2011 в 16:51):
Похоже с таким подходом мы получаем "Version: WinCHM (Standard)", а Pro не получается )
mrbelyash
(17.08.2011 в 18:05):
Жаль что не Help&Manual ;(
ManHunter
(16.08.2011 в 09:36):
Isaev, путаешь, сколько я ее помню, она всегда без упаковщика шла. По молодости я ее тоже патчами до ума доводил.
Isaev
(16.08.2011 в 02:23):
На счёт битхаков это вы зря :)
Хороший разбор! А константы можно дёргать из exe если совсем уж хочется универсально ))
Раньше она под аспротом вроде была... или путаю чего
Хороший разбор! А константы можно дёргать из exe если совсем уж хочется универсально ))
Раньше она под аспротом вроде была... или путаю чего
ManHunter
(15.08.2011 в 23:12):
У 1С это хорошо получается. Сперва подсадили всех на варез, потом всех закошмарили санкциями и сняли бабло за лицензирование + регулярный и гарантированный съем бабла за поддержку. Еще мне нравится как работает MySQL: все бесплатно, но если хотите внеочередную фичу конкретно под свои нужды - бабло в кассу. А вообще для корпоративного и узкоспециализированного софта я ничего не имею против оплаты и платной поддержки, здесь расходуются деньги компаний, а не пользователей. Персональный софт должен быть максимум donationware.
Wirtmih
(15.08.2011 в 21:00):
Я не автор программы, но всё-таки спрошу. За корпоративный софт денег требовать можно или тоже, по вашему мнению, лучше зарабатывать на его поддержке?
AyTkACT
(14.08.2011 в 22:21):
ManHunter, ну дык не все программы для людей пишут. А если уж так, то лучше как уже писал ниже.
ManHunter
(14.08.2011 в 19:27):
Бабло надо зарабатывать на работе, а программы писать бесплатно, для души и для людей.
AyTkACT
(14.08.2011 в 15:17):
Ввиду того что проверка идёт по константам, а константы меняются от версии или даже от билда - имхо, самое кучерявое в данном случае - битхак.
В очередной раз удивляюсь крутости алго проверок.
з.ы. Лучший вариант коммерциализации софта является добровольные пожертвования или акции по раскрутки сабжа а ля _http://adguard.ru/license.html#free
В очередной раз удивляюсь крутости алго проверок.
з.ы. Лучший вариант коммерциализации софта является добровольные пожертвования или акции по раскрутки сабжа а ля _http://adguard.ru/license.html#free
Dimas
(14.08.2011 в 06:31):
А я по старинке бит хаком - замена двух прыжков и получил портабл Unlimited версию размером 3,5 метра.
ЗЫ сегодня проскочила прожка AP Tuner - очень обрадовался увидев - PCL.NFO ;-)
ЗЫ сегодня проскочила прожка AP Tuner - очень обрадовался увидев - PCL.NFO ;-)
Добавить комментарий
Заполните форму для добавления комментария
CODE:005101A9 mov eax, ds:off_54B4E8
CODE:005101AE cmp dword ptr [eax], 1
CODE:005101B1 jnz short loc_5101CF
обламывается...
399F она в 4.21