Исследование защиты программы Magic Photo Recovery
Скриншот программы Magic Photo Recovery
Программа Magic Photo Recovery предназначена для восстановления файлов изображений с различных носителей. Это могут быть просто удаленные файлы или даже информация на поврежденных носителях. Поиск выполняется по внутренней структуре графических файлов, в том числе и RAW, что позволяет с очень хорошей вероятностью восстановить данные. Без платной регистрации имеются ограничения в работе, что не есть правильно. Давайте решим эту проблему.
Первым делом забираем с сайта дистрибутив портативной версии. Можно скачать и обычный инсталлятор, но при прочих равных мне больше нравится портативный софт. В архиве два варианта софтины, потрошить будем 32-битную версию. Главный исполняемый файл ничем не упакован, сразу отправляем его в дизассемблер. Параллельно посмотрим, к чему можно зацепиться для анализа. При попытке регистрации неправильными данными появляется сообщение:
Сообщение о неправильной регистрации
Программа мультиязычная, все строки содержатся в соответствующих языковых файлах. К сожалению, в данном случае это нам ничем не поможет, все индексы строк числовые, дефолтных строк на случай недоступности файлов локализации в программе не содержится, искать что-то в огромном листинге по одно-двухзначному числу - задача нетривиальная. Значит поищем в файле что-нибудь из списка типа "trial", "license", "registered" и прочих характерных строчек, так или иначе связанных с регистрацией программы. Обнаружится вот такой интересный кусочек данных:
Строка в файле
Тут юникодная строка с характерным названием ветки реестра, а также названия двух ключей - "UserName" и "LicenseKey". Чуть ниже эти строчки дублируются еще раз. Очевидно, что это ключи реестра, в которых хранится регистрационная информация, хотя очень странно наблюдать подобное в портативной версии программы. Ну да ладно, это остается на совести автора. Нас же интересует тот факт, что данные в реестр должны быть как минимум один раз записаны при правильной регистрации, а затем один или более раз считаны оттуда при запуске и работе программы. Давайте вернемся в листинг и посмотрим, где и как используются оба найденных комплекта строк.
Code (Assembler) : Убрать нумерацию
- .text:00794BAD lea ecx, [ebp+var_C]
- .text:00794BB0 mov edx, [ebp+var_8]
- .text:00794BB3 mov eax, [ebp+var_4]
- ; Вызвать функцию проверки
- .text:00794BB6 call sub_795A34
- .text:00794BBB test al, al
- ; Если AL=0, то в реестр ничего не записывать
- .text:00794BBD jz loc_794C76
- .text:00794BC3 mov [ebp+var_D], 1
- .text:00794BC7 mov eax, off_EAE774
- .text:00794BCC mov byte ptr [eax], 1
- .text:00794BCF mov eax, off_EB0AB4
- .text:00794BD4 mov edx, [ebp+var_4]
- .text:00794BD7 call sub_40BCD0
- .text:00794BDC mov eax, off_EB038C
- .text:00794BE1 mov edx, [ebp+var_8]
- .text:00794BE4 call sub_40BCD0
- .text:00794BE9 mov eax, off_EAEBFC
- .text:00794BEE mov edx, [ebp+var_C]
- .text:00794BF1 call sub_40BCD0
- .text:00794BF6 mov eax, off_EAF254
- .text:00794BFB mov edx, [ebp+var_14]
- .text:00794BFE mov [eax], edx
- .text:00794C00 mov dl, 1
- .text:00794C02 mov eax, ds:off_50F2A0
- .text:00794C07 call sub_5103EC
- .text:00794C0C mov [ebp+var_18], eax
- .text:00794C0F xor eax, eax
- .text:00794C11 push ebp
- .text:00794C12 push offset loc_794C6F
- .text:00794C17 push dword ptr fs:[eax]
- .text:00794C1A mov fs:[eax], esp
- .text:00794C1D mov edx, 80000001h
- .text:00794C22 mov eax, [ebp+var_18]
- .text:00794C25 call sub_5104D4
- .text:00794C2A mov cl, 1
- ; Сохранить в реестре введенное имя и серийный номер
- .text:00794C2C mov edx, offset aSoftwareEastIm
- ; "Software\\East Imperial Soft\\Magic Photo"...
- .text:00794C31 mov eax, [ebp+var_18]
- .text:00794C34 call sub_51062C
- .text:00794C39 mov ecx, [ebp+var_4]
- .text:00794C3C mov edx, offset aUsername
- ; "UserName"
- .text:00794C41 mov eax, [ebp+var_18]
- .text:00794C44 call sub_510F84
- .text:00794C49 mov ecx, [ebp+var_8]
- .text:00794C4C mov edx, offset aLicensekey
- ; "LicenseKey"
- .text:00794C51 mov eax, [ebp+var_18]
- .text:00794C54 call sub_510F84
- .text:00794C59 xor eax, eax
- .text:00794C5B pop edx
Программа успешно "зарегистрирована"
Программа благодарит за регистрацию, в заголовке окна появляется странное сообщение с каким-то неимоверным количеством дней до регистрации. После перезапуска в заголовке и окне "О программе" отображается пустое значение типа лицензии, но кнопка регистрации пропала. При попытке восстановить данные никаких ограничений не проявляется, цель достигнута.
Бинарная хирургия - это хорошо и здорово, но давайте теперь копнем поглубже и попробуем зарегистрировать программу правильным серийным номером. Восстанавливаем пропатченный файл и возвращаемся в функцию проверки.
Code (Assembler) : Убрать нумерацию
- .text:00795A52 push dword ptr fs:[eax]
- .text:00795A55 mov fs:[eax], esp
- .text:00795A58 push ebp
- ; Первая проверка
- .text:00795A59 call sub_795918
- .text:00795A5E pop ecx
- .text:00795A5F test al, al
- .text:00795A61 jnz short loc_795A6D
- .text:00795A63 xor eax, eax
- .text:00795A65 pop edx
- .text:00795A66 pop ecx
- .text:00795A67 pop ecx
- .text:00795A68 mov fs:[eax], edx
- .text:00795A6B jmp short loc_795AD4
- .text:00795A6D ; ---------------------------------------
- .text:00795A6D loc_795A6D:
- ; Последовательность проверок на тип лицензии
- .text:00795A6D push ebp
- .text:00795A6E mov eax, offset aHomeEdition
- ; "Home Edition"
- .text:00795A73 call sub_7958BC
- .text:00795A78 pop ecx
- .text:00795A79 test al, al
- .text:00795A7B jnz short loc_795AA7
- .text:00795A7D push ebp
- .text:00795A7E mov eax, offset aOfficeEdition
- ; "Office Edition"
- .text:00795A83 call sub_7958BC
- .text:00795A88 pop ecx
- .text:00795A89 test al, al
- .text:00795A8B jnz short loc_795AA7
- .text:00795A8D push ebp
- .text:00795A8E mov eax, offset aCommercialEdit
- ; "Commercial Edition"
- .text:00795A93 call sub_7958BC
- .text:00795A98 pop ecx
- .text:00795A99 test al, al
- .text:00795A9B jnz short loc_795AA7
- .text:00795A9D xor eax, eax
- .text:00795A9F pop edx
- .text:00795AA0 pop ecx
- .text:00795AA1 pop ecx
- .text:00795AA2 mov fs:[eax], edx
- .text:00795AA5 jmp short loc_795AD4
- .text:00795AA7 ; -------------------------------
- .text:00795AA7 loc_795AA7:
- .text:00795AA7 push ebp
- ; Финальная проверка
- .text:00795AA8 call sub_7952CC
- .text:00795AAD pop ecx
- .text:00795AAE test al, al
- .text:00795AB0 jnz short loc_795ABC
- .text:00795AB2 xor eax, eax
- .text:00795AB4 pop edx
- .text:00795AB5 pop ecx
- .text:00795AB6 pop ecx
- .text:00795AB7 mov fs:[eax], edx
- .text:00795ABA jmp short loc_795AD4
- .text:00795ABC ; ---------------------------------------
- .text:00795ABC loc_795ABC:
- ; Все проверки пройдены, серийный номер правильный
- .text:00795ABC mov [ebp+var_D], 1
- .text:00795AC0 xor eax, eax
- .text:00795AC2 pop edx
- .text:00795AC3 pop ecx
Code (Assembler) : Убрать нумерацию
- .text:00795938 push ebp
- .text:00795939 push offset loc_7959FB
- .text:0079593E push dword ptr fs:[edx]
- .text:00795941 mov fs:[edx], esp
- .text:00795944 mov eax, [ebp+arg_0]
- .text:00795947 mov eax, [eax-4]
- .text:0079594A test eax, eax
- .text:0079594C jz short loc_795953
- .text:0079594E sub eax, 4
- ; Длина серийного номера должна быть не менее 13h (19) символов
- .text:00795951 mov eax, [eax]
- .text:00795953 loc_795953:
- .text:00795953 cmp eax, 13h
- .text:00795956 jl loc_7959F1
Code (Assembler) : Убрать нумерацию
- .text:0079595C lea eax, [ebp+var_4]
- .text:0079595F push eax
- .text:00795960 mov eax, [ebp+arg_0]
- .text:00795963 mov eax, [eax-4]
- .text:00795966 mov ecx, 12h
- .text:0079596B mov edx, 1
- .text:00795970 call sub_40CDEC
- .text:00795975 lea eax, [ebp+var_4]
- .text:00795978 mov ecx, 1
- .text:0079597D mov edx, 0Fh
- .text:00795982 call sub_40CE34
- .text:00795987 lea eax, [ebp+var_4]
- .text:0079598A mov ecx, 1
- .text:0079598F mov edx, 0Ah
- .text:00795994 call sub_40CE34
- .text:00795999 lea eax, [ebp+var_4]
- .text:0079599C mov ecx, 1
- .text:007959A1 mov edx, 5
- .text:007959A6 call sub_40CE34
Code (Assembler) : Убрать нумерацию
- .text:007959AB xor ebx, ebx
- .text:007959AD mov eax, 1
- .text:007959B2 loc_7959B2:
- .text:007959B2 mov edx, [ebp+var_4]
- .text:007959B5 movzx edx, word ptr [edx+eax*2-2]
- .text:007959BA imul edx, eax
- .text:007959BD add ebx, edx
- .text:007959BF inc eax
- .text:007959C0 cmp eax, 10h
- .text:007959C3 jnz short loc_7959B2
- .text:007959C5 lea edx, [ebp+var_8]
- .text:007959C8 mov eax, ebx
- .text:007959CA call sub_4284A0
- .text:007959CF mov eax, [ebp+var_8]
- .text:007959D2 test eax, eax
- .text:007959D4 jz short loc_7959DB
- .text:007959D6 sub eax, 4
- .text:007959D9 mov eax, [eax]
- .text:007959DB loc_7959DB:
- .text:007959DB mov edx, [ebp+var_8]
- .text:007959DE movzx eax, word ptr [edx+eax*2-2]
- .text:007959E3 mov edx, [ebp+arg_0]
- .text:007959E6 mov edx, [edx-4]
- ; Сравнение контрольного значения и последнего символа серийника
- .text:007959E9 cmp ax, [edx+24h]
- .text:007959ED setz [ebp+var_9]
Во второй проверке на тип лицензии последовательно вызывается одна и та же функция, которой в качестве параметра передается строка с типом лицензии. Тут особо ничего интересного кроме вызова очередной функции проверки по адресу 007958DD, если результат в AL будет не равен нулю, то тип лицензии принимается.
Code (Assembler) : Убрать нумерацию
- .text:007958BC push ebp
- .text:007958BD mov ebp, esp
- .text:007958BF push ecx
- .text:007958C0 push ebx
- .text:007958C1 push esi
- .text:007958C2 push edi
- .text:007958C3 mov ebx, eax
- .text:007958C5 mov [ebp+var_1], 0
- .text:007958C9 xor eax, eax
- .text:007958CB push ebp
- .text:007958CC push offset loc_795903
- .text:007958D1 push dword ptr fs:[eax]
- .text:007958D4 mov fs:[eax], esp
- .text:007958D7 mov eax, [ebp+arg_0]
- .text:007958DA push eax
- .text:007958DB mov eax, ebx
- ; Вызывать функцию проверки, по ее результатам принимается решение
- ; о корректности типа лицензии
- .text:007958DD call sub_7955C8
- .text:007958E2 pop ecx
- .text:007958E3 mov [ebp+var_1], al
- .text:007958E6 cmp [ebp+var_1], 0
- .text:007958EA jz short loc_7958F9
- .text:007958EC mov eax, [ebp+arg_0]
- .text:007958EF mov eax, [eax-0Ch]
- .text:007958F2 mov edx, ebx
- .text:007958F4 call sub_40BCD0
Code (Assembler) : Убрать нумерацию
- .text:007955F7 push dword ptr fs:[edx]
- .text:007955FA mov fs:[edx], esp
- .text:007955FD lea eax, [ebp+var_2C]
- .text:00795600 mov edx, [ebp+arg_0]
- .text:00795603 mov edx, [edx-8]
- .text:00795606 call sub_40CABC
- .text:0079560B mov eax, [ebp+var_2C]
- .text:0079560E lea edx, [ebp+var_28]
- .text:00795611 call sub_427968
- .text:00795616 mov edx, [ebp+var_28]
- .text:00795619 lea eax, [ebp+var_24]
- .text:0079561C call sub_40CAA8
- .text:00795621 mov eax, [ebp+var_24]
- .text:00795624 lea edx, [ebp+var_8]
- .text:00795627 call sub_427A48
- .text:0079562C lea eax, [ebp+var_C]
- .text:0079562F call sub_40B8F0
- .text:00795634 lea edx, [ebp+var_34]
- .text:00795637 mov eax, offset aMagicPhotoRe_2
- ; "Magic Photo Recovery"
- .text:0079563C call sub_427968
- .text:00795641 mov edx, [ebp+var_34]
- .text:00795644 lea eax, [ebp+var_30]
- .text:00795647 call sub_40CAA8
- .text:0079564C mov eax, [ebp+var_30]
- .text:0079564F lea edx, [ebp+var_10]
- .text:00795652 call sub_427A48
- .text:00795657 lea eax, [ebp+var_40]
- .text:0079565A mov edx, ebx
- .text:0079565C call sub_40CABC
- .text:00795661 mov eax, [ebp+var_40]
- .text:00795664 lea edx, [ebp+var_3C]
- .text:00795667 call sub_427968
- .text:0079566C mov edx, [ebp+var_3C]
- .text:0079566F lea eax, [ebp+var_38]
- .text:00795672 call sub_40CAA8
- .text:00795677 mov eax, [ebp+var_38]
- .text:0079567A lea edx, [ebp+var_14]
- .text:0079567D call sub_427A48
- .text:00795682 mov dl, 1
- .text:00795684 mov eax, ds:off_68FA7C
- .text:00795689 call sub_68FBB0
- .text:0079568E mov [ebp+var_20], eax
- .text:00795691 xor edx, edx
- .text:00795693 push ebp
- .text:00795694 push offset loc_795785
- .text:00795699 push dword ptr fs:[edx]
- .text:0079569C mov fs:[edx], esp
- .text:0079569F lea eax, [ebp+var_44]
- .text:007956A2 push eax
- .text:007956A3 lea eax, [ebp+var_48]
- .text:007956A6 call sub_679DB4
- .text:007956AB mov eax, [ebp+var_48]
- .text:007956AE push eax
- .text:007956AF push [ebp+var_8]
- .text:007956B2 push [ebp+var_10]
- .text:007956B5 push [ebp+var_14]
- .text:007956B8 push offset a00814250F41b4f
- ; "00814250-F41B-4FCF-BF6A-5841E6E76EF9"
- .text:007956BD lea eax, [ebp+var_4C]
- .text:007956C0 mov edx, 4
- .text:007956C5 call sub_40CCA4
- .text:007956CA mov edx, [ebp+var_4C]
- .text:007956CD mov eax, [ebp+var_20]
- .text:007956D0 pop ecx
- .text:007956D1 call sub_68F2C4
- .text:007956D6 mov eax, [ebp+var_44]
- .text:007956D9 lea edx, [ebp+var_18]
- .text:007956DC call sub_4274B8
Code (Assembler) : Убрать нумерацию
- .text:007956F4 xor esi, esi
- .text:007956F6 loc_7956F6:
- .text:007956F6 mov eax, edi
- .text:007956F8 add eax, eax
- .text:007956FA add eax, eax
- .text:007956FC inc eax
- .text:007956FD add eax, esi
- .text:007956FF mov edx, [ebp+var_18]
- .text:00795702 movzx eax, word ptr [edx+eax*2-2]
- .text:00795707 lea edx, [ebp+var_4]
- .text:0079570A call sub_4284A0
- .text:0079570F mov ebx, [ebp+var_4]
- .text:00795712 test ebx, ebx
- .text:00795714 jz short loc_79571B
- .text:00795716 sub ebx, 4
- .text:00795719 mov ebx, [ebx]
- .text:0079571B loc_79571B:
- .text:0079571B lea eax, [ebp+var_50]
- .text:0079571E mov edx, [ebp+var_4]
- .text:00795721 movzx edx, word ptr [edx+ebx*2-2]
- .text:00795726 call sub_40C9D8
- .text:0079572B mov edx, [ebp+var_50]
- .text:0079572E lea eax, [ebp+var_C]
- .text:00795731 call sub_40CBC4
- .text:00795736 inc esi
- .text:00795737 cmp esi, 4
- .text:0079573A jnz short loc_7956F6
- .text:0079573C inc edi
- .text:0079573D cmp edi, 3
- .text:00795740 jnz short loc_7956E3
- .text:00795742 lea eax, [ebp+var_54]
- .text:00795745 push eax
- .text:00795746 mov eax, [ebp+arg_0]
- .text:00795749 mov eax, [eax-4]
- .text:0079574C mov ecx, 0Eh
- .text:00795751 mov edx, 1
- .text:00795756 call sub_40CDEC
Code (Assembler) : Убрать нумерацию
- .text:0079575B mov edx, [ebp+var_54]
- .text:0079575E mov eax, [ebp+var_C]
- .text:00795761 call sub_40CDB4
- .text:00795766 setz [ebp+var_19]
Code (Assembler) : Убрать нумерацию
- .text:00794DBD push dword ptr fs:[eax]
- .text:00794DC0 mov fs:[eax], esp
- .text:00794DC3 xor eax, eax
- .text:00794DC5 mov [ebp+var_8], eax
- .text:00794DC8 xor ecx, ecx
- .text:00794DCA push ebp
- .text:00794DCB push offset loc_794E82
- .text:00794DD0 push dword ptr fs:[ecx]
- .text:00794DD3 mov fs:[ecx], esp
- .text:00794DD6 xor eax, eax
- .text:00794DD8 mov [ebp+var_C], eax
- .text:00794DDB xor edx, edx
- .text:00794DDD loc_794DDD:
- .text:00794DDD xor eax, eax
- .text:00794DDF loc_794DDF:
- .text:00794DDF lea ecx, [edx+edx*4]
- .text:00794DE2 inc ecx
- .text:00794DE3 add ecx, eax
- .text:00794DE5 mov esi, [ebx]
- .text:00794DE7 movzx ecx, word ptr [esi+ecx*2-2]
- .text:00794DEC add [ebp+var_C], ecx
- .text:00794DEF inc eax
- .text:00794DF0 cmp eax, 4
- .text:00794DF3 jnz short loc_794DDF
- .text:00794DF5 inc edx
- .text:00794DF6 cmp edx, 3
- .text:00794DF9 jnz short loc_794DDD
- .text:00794DFB lea eax, [ebp+var_4]
- .text:00794DFE push eax
- .text:00794DFF push offset dword_794ECC
- .text:00794E04 lea edx, [ebp+var_18]
- .text:00794E07 mov eax, [ebp+var_C]
- .text:00794E0A call sub_4284A0
- .text:00794E0F push [ebp+var_18]
- .text:00794E12 push offset dword_794EDC
- .text:00794E17 lea eax, [ebp+var_14]
- .text:00794E1A mov edx, 3
- .text:00794E1F call sub_40CCA4
- .text:00794E24 mov eax, [ebp+var_14]
- .text:00794E27 mov ecx, 3
- .text:00794E2C mov edx, 1
- .text:00794E31 call sub_40CDEC
- .text:00794E36 lea eax, [ebp+var_1C]
- .text:00794E39 push eax
Code (Assembler) : Убрать нумерацию
- .text:00794E4B mov eax, [ebp+var_1C]
- .text:00794E4E lea edx, [ebp+var_10]
- .text:00794E51 call sub_42888C
- .text:00794E56 test al, al
- .text:00794E58 jz short loc_794E78
- .text:00794E5A lea edx, [ebp+var_C]
- .text:00794E5D mov eax, [ebp+var_4]
- .text:00794E60 call sub_42888C
- .text:00794E65 test al, al
Программа успешно зарегистрирована
Программа благодарит за регистрацию, никаких счетчиков дней нет, в окне "О программе" указывается регистрационное имя. Цель достигнута. Таким же образом регистрируются все остальные программы этого разработчика.
Просмотров: 1502 | Комментариев: 1
Метки: исследование защиты
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
xussr
(28.12.2019 в 22:10):
Этот пример более понятен и доступен спасибо!
Добавить комментарий
Заполните форму для добавления комментария