Исследование защиты программы Picture Reduce
Скриншот программы Picture Reduce
Программа Picture Reduce предназначена для пакетной обработки изображений с целью изменения их размера. Вообще-то аффтар еще сам не определился с названием программы: в окне About одно название, в заголовке главного окна - другое, так что пусть будет Picture Reduce. По функционалу тоже ничего особенного, с этим прекрасно справляется множество бесплатных программ. А вот защита мне понравилась, так что подать пациента на разделочный стол.
Качаем дистрибутив, устанавливаем, запускаем. Кнопка активации в правом верхнем углу, на ввод левых регистрационных данных программа реагирует сообщением "Invalid license code!". Поищем эту строчку в исполняемом файле. Файл ничем не упакован, найдется строчка в юникоде:
Нехорошая строка найдена
Теперь посмотрим код, где это все обрабатывается:
Code (Assembler) : Убрать нумерацию
- ...
- .text:00413F0C lea ecx, [esi+604h]
- .text:00413F12 mov byte ptr [esp+18h], 1
- ; Получить значение полей имени и серийного номера
- .text:00413F17 call ?GetWindowTextW
- .text:00413F1C lea ecx, [esp+4]
- .text:00413F20 push ecx
- .text:00413F21 lea ecx, [esi+658h]
- .text:00413F27 call ?GetWindowTextW
- .text:00413F2C lea ecx, [esp+8]
- ; Удалить лидирующие и хвостовые пробелы
- .text:00413F30 call ds:?Trim@
- .text:00413F36 lea ecx, [esp+4]
- .text:00413F3A call ds:?Trim
- .text:00413F40 lea ecx, [esp+4]
- ; Проверить длину введенного имени, оно должно быть не менее 6 символов
- .text:00413F44 call ds:?GetLength
- .text:00413F4A cmp eax, 6
- .text:00413F4D jl short loc_413F92
- .text:00413F4F lea edx, [esp+4]
- .text:00413F53 push edx
- .text:00413F54 lea eax, [esp+0Ch]
- .text:00413F58 push eax
- .text:00413F59 call sub_413D60
- .text:00413F5E push 4
- ; Вызвать функцию проверки серийного номера
- .text:00413F60 call sub_40AF80
- .text:00413F65 add esp, 0Ch
- .text:00413F68 test eax, eax
- ; Если она вернула EAX=0, то серийный номер неправильный
- .text:00413F6A jz short loc_413F92
- .text:00413F6C push 0
- .text:00413F6E mov ecx, offset dword_4237E4
- .text:00413F73 call ds:??B?$CSimpleStringT
- .text:00413F79 push eax
- ; Сообщение об успешной регистрации
- .text:00413F7A push offset aTheLicenseCode
- ; "The license code is valid, thank you fo"...
- .text:00413F7F mov ecx, esi
- .text:00413F81 call ?MessageBoxW
- .text:00413F86 mov edx, [esi]
- .text:00413F88 mov ecx, esi
- .text:00413F8A call dword ptr [edx+154h]
- .text:00413F90 jmp short loc_413FAC
- .text:00413F92 ; -----------------------------------------------
- .text:00413F92 loc_413F92:
- .text:00413F92 mov ecx, offset dword_4237E4
- .text:00413F97 push 30h
- .text:00413F99 call ds:??B?$CSimpleStringT
- .text:00413F9F push eax
- .text:00413FA0 mov ecx, esi
- ; Сообщение о неудачной регистрации
- .text:00413FA2 push offset aInvalidLicense
- ; "Invalid license code!"
- .text:00413FA7 call ?MessageBoxW
- .text:00413FAC loc_413FAC:
- .text:00413FAC lea ecx, [esp+4]
- .text:00413FB0 call ds:??1?$CStringT
- .text:00413FB6 lea ecx, [esp+8]
- .text:00413FBA call ds:??1?$CStringT
- .text:00413FC0 mov ecx, [esp+0Ch]
- .text:00413FC4 pop esi
- ...
Code (Assembler) : Убрать нумерацию
- ...
- .text:0040AF98 push esi
- .text:0040AF99 push edi
- ; Получить значение таймера
- .text:0040AF9A push 0 ; Time
- .text:0040AF9C call ds:_time64
- .text:0040AFA2 mov esi, [esp+2Ch+arg_0]
- .text:0040AFA6 add esp, 4
- .text:0040AFA9 test esi, esi
- .text:0040AFAB jle short loc_40AFB2
- .text:0040AFAD cmp esi, 6
- .text:0040AFB0 jle short loc_40AFB7
- .text:0040AFB2 loc_40AFB2:
- .text:0040AFB2 mov esi, 6
- .text:0040AFB7 loc_40AFB7:
- .text:0040AFB7 call ds:rand
- ; Получить случайное число с инициализацией генератора значением таймера
- .text:0040AFBD cdq
- .text:0040AFBE idiv esi
- .text:0040AFC0 mov ecx, offset Source ; Source
- .text:0040AFC5 test edx, edx
- ; Вызвать один из вариантов проверки в зависимости от случайного числа
- .text:0040AFC7 jz short loc_40AFD0
- ; Первый вариант проверки
- .text:0040AFC9 call sub_40A6F0
- .text:0040AFCE jmp short loc_40AFD5
- .text:0040AFD0 ; -------------------------------------------------
- .text:0040AFD0 loc_40AFD0:
- ; Второй вариант проверки
- .text:0040AFD0 call sub_40A790
- .text:0040AFD5 loc_40AFD5:
- ; Если любой из вариантов вернул AL=0, то серийный номер неправильный
- .text:0040AFD5 test al, al
- .text:0040AFD7 jz loc_40B081
- .text:0040AFDD mov ecx, offset Source ; Source
- ; Третья проверка - обязательная
- .text:0040AFE2 call sub_40A650
- ; Если проверка вернула AL=0, то серийный номер неправильный
- .text:0040AFE7 test al, al
- .text:0040AFE9 jz loc_40B081
- ; Установить заголовок зарегистрированной версии
- .text:0040AFEF push offset aStrfull ; "strFull"
- .text:0040AFF4 lea ecx, [esp+2Ch+arg_0]
- .text:0040AFF8 mov edi, 1
- .text:0040AFFD call ds:??0?$CStringT
- ...
- ; часть незначимого кода пропущена
- ...
- .text:0040B06E mov eax, edi
- .text:0040B070 pop edi
- .text:0040B071 pop esi
- .text:0040B072 mov ecx, [esp+20h+var_C]
- .text:0040B076 mov large fs:0, ecx
- .text:0040B07D add esp, 20h
- .text:0040B080 retn
- .text:0040B081 ; -------------------------------------------------
- .text:0040B081 loc_40B081:
- ; Установить триальный заголовок
- .text:0040B081 push offset aStrtrial ; "strTrial"
- .text:0040B086 lea ecx, [esp+2Ch+var_20]
- .text:0040B08A xor esi, esi
- ...
Code (Assembler) : Убрать нумерацию
- ; Первая проверка серийного номера
- .text:0040A6F0 sub esp, 14h
- .text:0040A6F3 mov eax, dword_4236F0
- .text:0040A6F8 push esi
- .text:0040A6F9 mov esi, ecx
- .text:0040A6FB mov [esp+18h+var_4], eax
- .text:0040A6FF lea eax, [esi+0Eh]
- ; Проверить длину серийного номера
- .text:0040A702 push eax ; Str
- .text:0040A703 call ds:wcslen
- .text:0040A709 add esp, 4
- .text:0040A70C cmp eax, 12h
- ; Если длина серийника менее 12h (десятичное 18), то он неправильный
- .text:0040A70F jl short loc_40A763
- .text:0040A711 lea ecx, [esp+18h+Str]
- .text:0040A715 push esi ; Source
- .text:0040A716 push ecx ; Dest
- .text:0040A717 call ds:wcscpy
- .text:0040A71D add esp, 8
- .text:0040A720 lea edx, [esp+18h+Str]
- .text:0040A724 push edx ; Str
Code (Assembler) : Убрать нумерацию
- .text:0040A725 mov ecx, esi
- ; Преобразовать первые 6 символов серийного номера
- .text:0040A727 call sub_40A550
- .text:0040A72C lea eax, [esp+18h+Str]
Code (Assembler) : Убрать нумерацию
- ; Преобразование №1
- .text:0040A570 loc_40A570:
- .text:0040A570 xor eax, eax
- ; Получить следующий символ
- .text:0040A572 mov al, [esi+ecx*2]
- .text:0040A575 add al, 53h
- .text:0040A577 mov ebx, 19h
- .text:0040A57C and eax, 0FEh
- .text:0040A581 cdq
- .text:0040A582 idiv ebx
- .text:0040A584 add edx, 41h
- ; Записать его обратно
- .text:0040A587 mov [esi+ecx*2], dx
- .text:0040A58B inc ecx
- .text:0040A58C cmp ecx, edi
- .text:0040A58E jl short loc_40A570
Code (Assembler) : Убрать нумерацию
- .text:0040A730 push eax ; Str
- .text:0040A731 mov ecx, esi
- .text:0040A733 call sub_40A5F0
Code (Assembler) : Убрать нумерацию
- ; Преобразование №2
- .text:0040A610 loc_40A610:
- .text:0040A610 xor eax, eax
- ; Получить следующий символ
- .text:0040A612 mov ax, [esi+ecx*2]
- .text:0040A616 shl ax, 3
- .text:0040A61A mov ebx, 0Ah
- .text:0040A61F add eax, 0C2h
- .text:0040A624 movzx eax, ax
- .text:0040A627 shr eax, 1
- .text:0040A629 cdq
- .text:0040A62A idiv ebx
- .text:0040A62C mov ebx, 19h
- .text:0040A631 xor edx, 3
- .text:0040A634 shl edx, 3
- .text:0040A637 movzx eax, dx
- .text:0040A63A cdq
- .text:0040A63B idiv ebx
- .text:0040A63D add edx, 41h
- ; Записать его обратно
- .text:0040A640 mov [esi+ecx*2], dx
- .text:0040A644 inc ecx
- .text:0040A645 cmp ecx, edi
- .text:0040A647 jl short loc_40A610
Code (Assembler) : Убрать нумерацию
- ; Начало цикла проверки
- .text:0040A738 xor eax, eax
- .text:0040A73A lea ecx, [esi+26h]
- .text:0040A73D lea ecx, [ecx+0]
- .text:0040A740 loc_40A740:
- .text:0040A740 mov dx, [esp+eax*2+18h+Str]
- .text:0040A745 cmp dx, [ecx]
- .text:0040A748 jnz short loc_40A763
- .text:0040A74A inc eax
- .text:0040A74B add ecx, 2
- .text:0040A74E cmp eax, 6
- .text:0040A751 jl short loc_40A740
- .text:0040A753 mov al, 1
- .text:0040A755 pop esi
- .text:0040A756 mov ecx, [esp+14h+var_4]
- .text:0040A75A call sub_415A41
- .text:0040A75F add esp, 14h
- .text:0040A762 retn
- .text:0040A763 ; ------------------------------------------------------
- .text:0040A763 loc_40A763:
- .text:0040A763 mov ecx, [esp+18h+var_4]
- .text:0040A767 xor al, al
- .text:0040A769 pop esi
- .text:0040A76A call sub_415A41
- .text:0040A76F add esp, 14h
- .text:0040A772 retn
Code (Assembler) : Убрать нумерацию
- ; Вторая проверка серийного номера
- .text:0040A790 sub esp, 18h
- .text:0040A793 mov eax, dword_4236F0
- .text:0040A798 push edi
- .text:0040A799 mov edi, ecx
- .text:0040A79B push edi ; Str
- ; Заполнить массив символами "HOTUCQFRE"
- .text:0040A79C mov [esp+20h+var_4], eax
- .text:0040A7A0 mov [esp+20h+var_18], 48h
- .text:0040A7A7 mov [esp+20h+var_16], 4Fh
- .text:0040A7AE mov [esp+20h+var_14], 54h
- .text:0040A7B5 mov [esp+20h+var_12], 55h
- .text:0040A7BC mov [esp+20h+var_10], 43h
- .text:0040A7C3 mov [esp+20h+var_E], 51h
- .text:0040A7CA mov [esp+20h+var_C], 46h
- .text:0040A7D1 mov [esp+20h+var_A], 52h
- .text:0040A7D8 mov [esp+20h+var_8], 45h
- .text:0040A7DF call ds:wcslen
- .text:0040A7E5 add esp, 4
- .text:0040A7E8 cmp eax, 6
- .text:0040A7EB jge short loc_40A7FD
- .text:0040A7ED xor al, al
- .text:0040A7EF pop edi
- .text:0040A7F0 mov ecx, [esp+18h+var_4]
- .text:0040A7F4 call sub_415A41
- .text:0040A7F9 add esp, 18h
- .text:0040A7FC retn
- .text:0040A7FD ; -----------------------------------------
- .text:0040A7FD loc_40A7FD:
- .text:0040A7FD push esi
- ; В цикле проверить, чтобы любой из первых 6 символов серийного номера
- ; был из числа символов, которые были занесены в массив
- .text:0040A7FE xor esi, esi
- .text:0040A800 test eax, eax
- .text:0040A802 jle short loc_40A833
- .text:0040A804 loc_40A804:
- .text:0040A804 mov dx, [edi+esi*2]
- .text:0040A808 xor ecx, ecx
- .text:0040A80A lea ebx, [ebx+0]
- .text:0040A810 loc_40A810:
- .text:0040A810 cmp dx, [esp+ecx*2+20h+var_18]
- .text:0040A815 jz short loc_40A82E
- .text:0040A817 inc ecx
- .text:0040A818 cmp ecx, 9
- .text:0040A81B jl short loc_40A810
- .text:0040A81D pop esi
- .text:0040A81E xor al, al
- .text:0040A820 pop edi
- .text:0040A821 mov ecx, [esp+18h+var_4]
- .text:0040A825 call sub_415A41
- .text:0040A82A add esp, 18h
- .text:0040A82D retn
- .text:0040A82E ; -------------------------------------------
- .text:0040A82E loc_40A82E:
- .text:0040A82E inc esi
- .text:0040A82F cmp esi, eax
- .text:0040A831 jl short loc_40A804
- .text:0040A833 loc_40A833:
- .text:0040A833 mov ecx, [esp+20h+var_4]
- .text:0040A837 pop esi
- .text:0040A838 mov al, 1
- .text:0040A83A pop edi
- .text:0040A83B call sub_415A41
- .text:0040A840 add esp, 18h
- .text:0040A843 retn
Code (Assembler) : Убрать нумерацию
- ; Третья проверка серийного номера
- .text:0040A650 sub esp, 14h
- .text:0040A653 mov eax, dword_4236F0
- .text:0040A658 push esi
- .text:0040A659 mov esi, ecx
- .text:0040A65B push edi
- .text:0040A65C lea edi, [esi+0Eh]
- .text:0040A65F push edi ; Str
- .text:0040A660 mov [esp+20h+var_4], eax
- .text:0040A664 call ds:wcslen
- .text:0040A66A add esp, 4
- .text:0040A66D cmp eax, 6
- .text:0040A670 jl short loc_40A6D4
- .text:0040A672 lea eax, [esp+1Ch+Str]
- .text:0040A676 push esi ; Source
- .text:0040A677 push eax ; Dest
- .text:0040A678 call ds:wcscpy
- .text:0040A67E add esp, 8
- .text:0040A681 lea ecx, [esp+1Ch+Str]
- .text:0040A685 push ecx ; Str
- .text:0040A686 mov ecx, esi
- ; Вызвать преобразование №3
- .text:0040A688 call sub_40A5A0
Code (Assembler) : Убрать нумерацию
- ; Преобразование №3
- .text:0040A5C0 loc_40A5C0:
- ; Получить следующий символ
- .text:0040A5C0 movzx eax, word ptr [esi+ecx*2]
- .text:0040A5C4 xor eax, 0Bh
- .text:0040A5C7 cdq
- .text:0040A5C8 mov ebx, 13h
- .text:0040A5CD idiv ebx
- .text:0040A5CF mov ebx, 0Ah
- .text:0040A5D4 shl edx, 1
- .text:0040A5D6 movzx eax, dx
- .text:0040A5D9 cdq
- .text:0040A5DA idiv ebx
- .text:0040A5DC add edx, 30h
- ; Записать его обратно
- .text:0040A5DF mov [esi+ecx*2], dx
- .text:0040A5E3 inc ecx
- .text:0040A5E4 cmp ecx, edi
- .text:0040A5E6 jl short loc_40A5C0
Code (Assembler) : Убрать нумерацию
- .text:0040A68D lea edx, [esp+1Ch+Str]
- .text:0040A691 push edx ; Str
- .text:0040A692 mov ecx, esi
- ; Вызвать преобразование №2
- .text:0040A694 call sub_40A5F0
- .text:0040A699 lea eax, [esp+1Ch+Str]
- .text:0040A69D push eax ; Str
- .text:0040A69E mov ecx, esi
- ; Вызвать преобразование №1
- .text:0040A6A0 call sub_40A550
- .text:0040A6A5 xor eax, eax
- .text:0040A6A7 mov ecx, edi
- ; Сравнить вторые 6 символов серийного номера с полученной строкой
- .text:0040A6A9 lea esp, [esp+0]
- .text:0040A6B0 loc_40A6B0:
- .text:0040A6B0 mov dx, [esp+eax*2+1Ch+Str]
- .text:0040A6B5 cmp dx, [ecx]
- .text:0040A6B8 jnz short loc_40A6D4
- .text:0040A6BA inc eax
- .text:0040A6BB add ecx, 2
- .text:0040A6BE cmp eax, 6
- .text:0040A6C1 jl short loc_40A6B0
- .text:0040A6C3 pop edi
- .text:0040A6C4 mov al, 1
- .text:0040A6C6 pop esi
- .text:0040A6C7 mov ecx, [esp+14h+var_4]
- .text:0040A6CB call sub_415A41
- .text:0040A6D0 add esp, 14h
- .text:0040A6D3 retn
- .text:0040A6D4 ; -----------------------------------------------
- .text:0040A6D4 loc_40A6D4:
- .text:0040A6D4 mov ecx, [esp+1Ch+var_4]
- .text:0040A6D8 pop edi
- .text:0040A6D9 xor al, al
- .text:0040A6DB pop esi
- .text:0040A6DC call sub_415A41
- .text:0040A6E1 add esp, 14h
- .text:0040A6E4 retn
Программа успешно зарегистрирована
Вводим его и получаем сообщение об успешной регистрации. Так что респект аффтару за интересный алгоритм, мне понравилось. Рабочий кейген теперь напишете самостоятельно.
Просмотров: 4616 | Комментариев: 12
Метки: исследование защиты
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
contango
(29.05.2011 в 20:25):
ManHunter, как всегда на высоте! Да и с твоими мыслями трудно не согласиться. Препарируй и дальше такие чудо-проги. Так держать!!!
Zhelezyaka
(20.05.2011 в 09:57):
Как достали эти - "нельзя так думать", воображение рисует что-то слюнявое, которое грозит пальчиком. Есть хорошая книжка "Конфедерация Меганезия", каждый волен верить во что угодно, но за навязывание своего мнения - ВМН(к стенке).
Спасибо за статью!
Спасибо за статью!
ManHunter
(16.05.2011 в 23:45):
Все мои наработки и так в открытом доступе, а исходники я на ftp не храню. И чужие батоны я не откусываю, мне своих хватает :) Просто я против платного софта, вот и все. И уж тем более против всяких платных говноподелок, собранных на коленке. Любой софт должен быть бесплатным, и программирование должно быть творчеством, а не ремеслом. А то сейчас каждый мудак, научившийся собирать в кучу готовые компоненты и библиотеки считает себя невъебенным "программистом" и наследником Билла Гейтса.
Мнение +
(16.05.2011 в 23:06):
Я считаю, что нельзя так думать, как высказался ManHunter. Если ты считаешь, что автор программы дурак, то не используй его программу. Ищи замену. Зачем откусывать чужой батон с икрой, а потом топать ножкой и кричать "не буду платить, слишком солёно". Ты же сам добровольно в рот каку взял, чего на других свою ошибку списывать. Ломать программы не строить, думаю тебе тоже будет приятно, когда с твоего ftp "вытащат" твои наработки и ты поймёшь, как "круто" ломать чужое. Не желаешь платить - не используй чужой софт, пиши свой. А писать софт высшего качества можно через лет 5, когда опыт будет, начало у всех одно. Продавать или дарить тоже дело автора, также как и право купить/не купить.
Аффтар
(14.05.2011 в 20:07):
ManHunter, согласен, надо писать софт высшего качества, который люди сами захотят купить.
А по поводу помогателей, в том-то и дело, что они помогатели, а не помощники. :(
На твоем сайте есть много полезного, в какой-то мере это можно расценить как помощь. Спасибо, что она не ограничивается триалом. :)
А по поводу помогателей, в том-то и дело, что они помогатели, а не помощники. :(
На твоем сайте есть много полезного, в какой-то мере это можно расценить как помощь. Спасибо, что она не ограничивается триалом. :)
ManHunter
(14.05.2011 в 05:44):
Аффтар, RSDN уже стало не хватать? Там помогателей выше крыши. А по поводу "ломать - не строить", так на этом сайте я делюсь знаниями и своими программами, причем делаю это совершенно бесплатно. И ничего, на батон с черной икрой хватает. В остальном же меня просто вымораживает стремление "программистов", склепавших из сторонних компонентов очередной блокнот или видеоконвертер, сразу же бежать его продавать. Бабло надо зарабатывать на работе, а программировать ради удовольствия. Есть, конечно, другой вариант: надо писать софт высшего качества, который люди сами захотят купить. Это вполне реально, но для этого придется задействовать головной мозг, думать, напрягаться, творить, и количество такого софта можно пересчитать по пальцам. Похожий вариант: распространять по схеме donationware, и пусть пользователи сами решают, во сколько оценить твой труд и пользу от твоего чудо-софта.
Аффтар
(14.05.2011 в 02:02):
ManHunter, а вместо того, чтобы ломать, ты мог бы помочь построить??? Или... Ломать не строить???
DimitarSerg
(13.05.2011 в 12:20):
Я тоже ее ковырял, на правке одного байта остановился :)
Здесь же все грамотно расписанно именно насчет самого алгоритма генерации !
+1
Здесь же все грамотно расписанно именно насчет самого алгоритма генерации !
+1
AyTkACT
(13.05.2011 в 11:22):
Интересная статья! Интересный алго. Разбор на пятёрку!
ManHunter
(13.05.2011 в 10:28):
Я употребляю это слово в качестве презрительного названия шароварщиков.
64-ядерный процессор
(13.05.2011 в 10:12):
Я как вижу статью со словом "аффтар" в начале, так не могу не удержаться, чтоб не дочитать до конца. От подобных выражений настроение подымается сразу =))
Isaev
(13.05.2011 в 04:37):
Зачёт )
Добавить комментарий
Заполните форму для добавления комментария