Исследование защиты программы Perfect Hotkey
Скриншот программы Perfect Hotkey
Perfect Hotkey - один из многих менеджеров "горячих клавиш" под Windows. Позволяет назначать на различные комбинации клавиш различные действия, такие как запуск программы, открытие ссылки, копирование и вставка текста, управление громкостью динамиков, очистка буфера обмена и тому подобное, в том числе и пакеты из нескольких действий. Я подобными программами не пользуюсь, сравнить особо не с чем, а вот от триальности подлечить смогу.
Забираем с офсайта дистрибутив, устанавливаем, смотрим. Исполняемый файл ничем не упакован, отправляем его без моего напоминания прямо в дизассемблер. Разбираемся с функционалом. Через некоторое количество запусков программы при старте начинает появляться вот такое окно:
Триальное окно
При попытке регистрации программа безропотно принимает вообще любые имена и серийники, после чего просит перезапуститься для их проверки. Грамотный ход со стороны автора, так как никаких сообщений о правильной или неправильной регистрации при этом не выводится. Значит действуем иначе. Последовательным поиском по типовым строчкам "registered", "username", "regcode", "license", "trial" и подобным выходим на большую функцию, в которой выполняется активная работа с неким файлом конфигурации. Всю ее приводить не буду, она достаточно объемная.
Code (Assembler) : Убрать нумерацию
- .text:00450552 call sub_401180
- .text:00450557 push ecx ; lpKeyName
- .text:00450558 mov ecx, esp
- .text:0045055A mov [ebp+var_1B8], esp
- .text:00450560 push offset aUsedtimes ; "UsedTimes"
- .text:00450565 mov byte ptr [ebp+var_4], 4
- .text:00450569 call sub_401180
- .text:0045056E push ecx ; lpAppName
- .text:0045056F mov ecx, esp
- .text:00450571 push offset aLicense ; "License"
- .text:00450576 mov byte ptr [ebp+var_4], 5
- .text:0045057A call sub_401180
- .text:0045057F lea eax, [ebp+var_1A0]
- .text:00450585 push eax ; int
- .text:00450586 mov byte ptr [ebp+var_4], 2
- .text:0045058A call sub_416D00
- .text:0045058F push [ebp+var_1A0] ; char *
- .text:00450595 mov byte ptr [ebp+var_4], 6
- .text:00450599 call _atol
- .text:0045059E lea esi, [eax+1]
- .text:004505A1 push 0FEh ; size_t
- .text:004505A6 lea eax, [ebp+FindFileData.cFileName+15h]
- .text:004505AC push 0 ; int
- .text:004505AE push eax ; void *
- .text:004505AF mov [edi+1Ch], esi
- .text:004505B2 mov [ebp+FindFileData.cFileName+14h], 0
- .text:004505B9 call _memset
- .text:004505BE push 0Ah ; Radix
- .text:004505C0 push 0FFh ; Size
- .text:004505C5 lea eax, [ebp+FindFileData.cFileName+14h]
- .text:004505CB push eax ; DstBuf
- .text:004505CC push esi ; Val
- .text:004505CD call __ltoa_s
- .text:004505D2 add esp, 34h
- .text:004505D5 lea ecx, [ebp+lpKeyName]
- .text:004505DB push edi
- .text:004505DC call sub_401010
- .text:004505E1 lea eax, [ebp+FindFileData.cFileName+14h]
- .text:004505E7 push eax ; lpString
- .text:004505E8 lea ecx, [ebp+lpString]
- .text:004505EE mov byte ptr [ebp+var_4], 7
- .text:004505F2 call sub_401180
- .text:004505F7 push offset aUsedtimes ; "UsedTimes"
- .text:004505FC lea ecx, [ebp+lpFileName]
- .text:00450602 mov byte ptr [ebp+var_4], 8
- .text:00450606 call sub_401180
- .text:0045060B push offset aLicense ; "License"
- .text:00450610 lea ecx, [ebp+lpAppName]
- .text:00450616 mov byte ptr [ebp+var_4], 9
- .text:0045061A call sub_401180
- .text:0045061F push [ebp+lpKeyName] ; lpFileName
- .text:00450625 mov ebx, ds:WritePrivateProfileStringA
- .text:0045062B push [ebp+lpString] ; lpString
- .text:00450631 push [ebp+lpFileName] ; lpKeyName
- .text:00450637 push [ebp+lpAppName] ; lpAppName
- .text:0045063D call ebx ; WritePrivateProfileStringA
- .text:0045063F lea ecx, [ebp+lpAppName]
- .text:00450645 call sub_401280
Code (Assembler) : Убрать нумерацию
- .text:00450866 mov ecx, edi
- .text:00450868 mov [edi+24h], eax
- ; Вызывать функцию проверки
- .text:0045086B call sub_442180
- ; Сохранить ее результат
- .text:00450870 mov [edi+28h], eax
- .text:00450873 test eax, eax
- ; Если результат нулевой, то блок с активацией пропустить
- .text:00450875 jz loc_450ACB
- .text:0045087B mov eax, off_4A3024
- .text:00450880 mov [ebp+lpFileName], eax
- .text:00450886 lea eax, [ebp+var_1B0]
- .text:0045088C push eax ; int
- .text:0045088D mov ecx, edi ; lpFileName
- .text:0045088F mov byte ptr [ebp+var_4], 12h
- .text:00450893 call sub_4413A0
- .text:00450898 push dword ptr [eax]
- .text:0045089A lea eax, [ebp+lpFileName]
- .text:004508A0 push offset a_S_firstactiva
- ; "_%s_FirstActivateDate_"
- .text:004508A5 push eax
- .text:004508A6 mov byte ptr [ebp+var_4], 13h
- .text:004508AA call sub_401830
- .text:004508AF add esp, 0Ch
- .text:004508B2 lea ecx, [ebp+var_1B0]
- .text:004508B8 mov byte ptr [ebp+var_4], 12h
- .text:004508BC call sub_401280
- .text:004508C1 push ecx ; lpFileName
- .text:004508C2 mov ecx, esp
- .text:004508C4 mov [ebp+var_1B0], esp
- .text:004508CA push edi
- .text:004508CB call sub_401010
- .text:004508D0 push ecx ; lpDefault
- .text:004508D1 mov ecx, esp
- .text:004508D3 mov [ebp+var_1A0], esp
- .text:004508D9 push offset Default ; lpString
- .text:004508DE mov byte ptr [ebp+var_4], 14h
- .text:004508E2 call sub_401180
- .text:004508E7 push ecx ; lpKeyName
- .text:004508E8 lea eax, [ebp+lpFileName]
- .text:004508EE mov ecx, esp
- .text:004508F0 mov [ebp+lpKeyName], esp
- .text:004508F6 push eax
- .text:004508F7 mov byte ptr [ebp+var_4], 15h
- .text:004508FB call sub_401010
- .text:00450900 push ecx ; lpAppName
- .text:00450901 mov ecx, esp
- .text:00450903 push offset aLicense ; "License"
- .text:00450908 mov byte ptr [ebp+var_4], 16h
- .text:0045090C call sub_401180
- .text:00450911 lea eax, [ebp+var_1B4]
- .text:00450917 push eax ; int
- .text:00450918 mov byte ptr [ebp+var_4], 12h
- .text:0045091C call sub_416D00
- .text:00450921 lea eax, [ebp+var_1BC]
- .text:00450927 push eax
- .text:00450928 lea eax, [ebp+var_1C0]
- .text:0045092E push eax
- .text:0045092F lea eax, [ebp+var_1B8]
- .text:00450935 push eax
- .text:00450936 push offset a04d02d02d
- ; "%04d-%02d-%02d"
- .text:0045093B push [ebp+var_1B4]
- .text:00450941 call unknown_libname_55
- .text:00450946 add esp, 28h
- .text:00450949 cmp eax, 3
- .text:0045094C jnz loc_4509D3
- .text:00450952 lea eax, [ebp+var_40]
- .text:00450955 push eax ; lpSystemTime
- .text:00450956 call esi ; GetLocalTime
- .text:00450958 movzx eax, word ptr [ebp+var_1B8]
- .text:0045095F xorps xmm0, xmm0
- .text:00450962 movq qword ptr [ebp+var_20.wYear], xmm0
- .text:00450967 mov [ebp+var_20.wYear], ax
- .text:0045096B movzx eax, word ptr [ebp+var_1C0]
- .text:00450972 mov [ebp+var_20.wMonth], ax
- .text:00450976 movzx eax, word ptr [ebp+var_1BC]
- .text:0045097D mov [ebp+var_20.wDay], ax
- .text:00450981 push 0 ; int
- .text:00450983 lea eax, [ebp+var_20]
- .text:00450986 push eax ; SYSTEMTIME *
- .text:00450987 lea eax, [ebp+var_40]
- .text:0045098A push eax ; lpSystemTime
- .text:0045098B lea eax, [ebp+var_200]
- .text:00450991 push eax ; int
- .text:00450992 movq qword ptr [ebp+var_20.wHour], xmm0
- .text:00450997 call sub_417110
- .text:0045099C add esp, 10h
- .text:0045099F movq xmm0, qword ptr [eax]
- .text:004509A3 movq qword ptr [ebp+var_1E8], xmm0
- .text:004509AB movq xmm0, qword ptr [eax+8]
- .text:004509B0 movq [ebp+var_1E0], xmm0
- .text:004509B8 movq xmm0, qword ptr [eax+10h]
- .text:004509BD mov eax, [ebp+var_1E8]
- .text:004509C3 movq [ebp+var_1D8], xmm0
- .text:004509CB mov [edi+2Ch], eax
Code (Assembler) : Убрать нумерацию
- ; Выделить из строки 6 групп по 4 hex-цифры
- .text:004421F7 lea ecx, [ebp+var_14]
- .text:004421FA push ecx
- .text:004421FB lea ecx, [ebp+var_18]
- .text:004421FE push ecx
- .text:004421FF lea ecx, [ebp+var_1C]
- .text:00442202 push ecx
- .text:00442203 lea ecx, [ebp+var_20]
- .text:00442206 push ecx
- .text:00442207 lea ecx, [ebp+var_24]
- .text:0044220A push ecx
- .text:0044220B lea ecx, [ebp+var_28]
- .text:0044220E push ecx
- .text:0044220F push offset a04x04x04x04x04
- ; "%04X%04X-%04X%04X-%04X%04X-F703C3AD-9CE"...
- .text:00442214 push eax
- .text:00442215 call unknown_libname_55
- .text:0044221A add esp, 20h
- ; Все извлечено?
- .text:0044221D cmp eax, 6
- ; Нет, серийный номер неправильный
- .text:00442220 jnz loc_442361
- .text:00442226 mov ecx, [ebp+var_28] ; 1-я группа
- .text:00442229 mov eax, 66666667h
- .text:0044222E imul ecx
- .text:00442230 sar edx, 2
- .text:00442233 mov eax, edx
- .text:00442235 shr eax, 1Fh
- .text:00442238 add eax, edx
- .text:0044223A lea eax, [eax+eax*4]
- .text:0044223D add eax, eax
- .text:0044223F sub ecx, eax
- .text:00442241 mov eax, [ebp+var_24] ; 2-я группа
- .text:00442244 inc ecx
- .text:00442245 cdq
- .text:00442246 idiv ecx
- .text:00442248 cmp edx, [esi+4] ; 1
- ; Нет, серийный номер неправильный
- .text:0044224B jnz loc_442361
- .text:00442251 mov eax, [ebp+var_20] ; 3-я группа
- .text:00442254 cdq
- .text:00442255 idiv ecx
- .text:00442257 cmp edx, [esi+8] ; 2
- ; Нет, серийный номер неправильный
- .text:0044225A jnz loc_442361
- .text:00442260 mov eax, [ebp+var_1C] ; 4-я группа
- .text:00442263 cdq
- .text:00442264 idiv ecx
- .text:00442266 cmp edx, [esi+0Ch] ; 2
- ; Нет, серийный номер неправильный
- .text:00442269 jnz loc_442361
- .text:0044226F mov ecx, [ebp+var_18] ; 5-я группа
- .text:00442272 mov eax, 66666667h
- .text:00442277 imul ecx
- .text:00442279 sar edx, 2
- .text:0044227C mov eax, edx
- .text:0044227E shr eax, 1Fh
- .text:00442281 add eax, edx
- .text:00442283 lea eax, [eax+eax*4]
- .text:00442286 add eax, eax
- .text:00442288 sub ecx, eax
- .text:0044228A mov eax, [ebp+var_14] ; 6-я группа
- .text:0044228D inc ecx
- .text:0044228E cdq
- .text:0044228F idiv ecx
- .text:00442291 cmp edx, [esi+10h] ; 1
- ; Нет, серийный номер неправильный
- .text:00442294 jnz loc_442361
Во время трассировки на стеке можно обнаружить указатель на строку имени файла типа C:\Users\{USER}\AppData\Roaming\1119HOTK.dat. Если посмотреть его содержимое, то там обнаружится введенное имя, серийник, дата активации и количество запусков. Соответственно, чтобы сбросить регистрацию надо будет просто удалить этот файл.
Возвращаемся к программе. Чутье мне подсказывает, что на стандартной тип лицензии не заканчивается. Прокручиваем листинг немного ниже:
Code (Assembler) : Убрать нумерацию
- .text:00450ADF lea eax, [ebp+lpFileName]
- .text:00450AE5 push eax ; int
- .text:00450AE6 mov ecx, edi ; lpFileName
- .text:00450AE8 call sub_4413A0
- .text:00450AED lea ecx, [ebp+lpFileName]
- .text:00450AF3 mov byte ptr [ebp+var_4], 1Ch
- .text:00450AF7 call sub_401710
- ; Строку серийника в нижний регистр
- .text:00450AFC push [ebp+lpFileName] ; lpsz
- .text:00450B02 call ds:CharLowerA
- .text:00450B08 push 0
- ; Найти вхождение подстроки "lifetime"
- .text:00450B0A push offset aLifetime ; "lifetime"
- .text:00450B0F lea ecx, [ebp+lpFileName]
- .text:00450B15 call sub_414240
- ; Подстрока не найдена
- .text:00450B1A cmp eax, 0FFFFFFFFh
- .text:00450B1D jz short loc_450B26
- ; Подстрока найдена, установить какой-то флаг
- .text:00450B1F mov dword ptr [edi+44h], 1
- .text:00450B26 loc_450B26:
- .text:00450B26 lea ecx, [ebp+lpFileName]
- .text:00450B2C call sub_401280
- .text:00450B31 loc_450B31:
- .text:00450B31 mov eax, [edi+2Ch]
- .text:00450B34 cmp eax, [ebp+arg_10]
- .text:00450B37 jle short loc_450B46
Программа успешно зарегистрирована
Удаляем файл лицензии, повторяем регистрацию. Вот теперь в главном окне программы красуется пожизненная лицензия и введенное регистрационное имя. Ограничений по функционалу нет, по времени работы тоже, цель достигнута.
Просмотров: 832 | Комментариев: 0
Метки: исследование защиты
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария