Исследование защиты программы FabulousMP3
Скриншот программы FabulousMP3
FabulousMP3 - очень толковый "улучшайзер" для музыкальных файлов в формате MP3 и WAV, позволяющий в автоматическом режиме добавить полноту звука, выровнять громкость звучания, выделить голос, скорректировать баланс частот и динамический диапазон, после чего даже самая обычная композиция будет звучать чуть ли не профессионально даже на бытовой аудиоаппаратуре. Готовый результат не обязательно сохранять на диск, программа умеет работать как плеер, естественно, со всеми настройками звука. Лично мне программа понравилась. А вот идея выкладывать 38 баксов за лицензию не понравилась.
Забираем с офсайта портативный дистрибутив, куда-нибудь распаковываем, смотрим. Единственный исполняемый файл ничем не упакован, отправляем его в дизассемблер. Дальше посмотрим проявления триальности. Основное функциональное ограничение триальной программы - каждая композиция воспроизводится не более 90 секунд, после чего появляется сообщение с предложением метнуться в кассу. Из визуальных признаков сразу бросается в глаза наг-окно при старте программы, надпись в заголовке окна и в окне "О программе". На попытку регистрации левыми данными софтинка реагирует следующим сообщением:
Сообщение о неправильном серийнике
Это не обычное окно сообщения, оно оформлено как полноценное диалоговое окно и хранится в ресурсах под индексом 167, оно же 0A7h в шестнадцатеричной системе счисления.
Окно сообщения в ресурсах
Поиском этого значения по листингу дизассемблера обнаруживается следующий код. Тут ничего сложного нет, обычная проверка, по ее результатам программа или ругается на неправильный серийник, либо благодарит за регистрацию и обновляет заголовок главного окна.
Code (Assembler) : Убрать нумерацию
- .text:004065AB mov esi, ds:GetDlgItemTextA
- .text:004065B1 lea eax, [ebp+String]
- .text:004065B7 push 0FFh ; cchMax
- .text:004065BC push eax ; lpString
- .text:004065BD push 3E9h ; nIDDlgItem
- .text:004065C2 push edi ; hDlg
- .text:004065C3 call esi ; GetDlgItemTextA
- .text:004065C5 push 0FFh ; cchMax
- .text:004065CA lea eax, [ebp+String2]
- .text:004065D0 push eax ; lpString
- .text:004065D1 push 40Fh ; nIDDlgItem
- .text:004065D6 push edi ; hDlg
- .text:004065D7 call esi ; GetDlgItemTextA
- .text:004065D9 lea eax, [ebp+String]
- .text:004065DF push eax
- .text:004065E0 lea eax, [ebp+String2]
- .text:004065E6 push eax
- ; Вызвать функцию проверки
- .text:004065E7 call loc_412E20
- .text:004065EC add esp, 8
- .text:004065EF push 100h
- .text:004065F4 push 0
- .text:004065F6 push offset String1
- ; Если она вернула EAX=7115h, то регистрация успешна
- .text:004065FB cmp eax, 7115h
- ; Серийный номер неправильный
- .text:00406600 jnz loc_406697
- .text:00406606 mov dword_496788, 1
- .text:00406610 call sub_4462B0
- .text:00406615 push 100h
- .text:0040661A push 0
- .text:0040661C push offset byte_6FC520
- .text:00406621 call sub_4462B0
- .text:00406626 mov esi, ds:lstrcpyA
- .text:0040662C lea eax, [ebp+String2]
- .text:00406632 add esp, 18h
- .text:00406635 push eax ; lpString2
- .text:00406636 push offset String1 ; lpString1
- .text:0040663B call esi ; lstrcpyA
- .text:0040663D lea eax, [ebp+String]
- .text:00406643 push eax ; lpString2
- .text:00406644 push offset byte_6FC520 ; lpString1
- .text:00406649 call esi ; lstrcpyA
- .text:0040664B push 0 ; dwInitParam
- .text:0040664D push offset DialogFunc ; lpDialogFunc
- .text:00406652 push edi ; hWndParent
- .text:00406653 push 0A6h ; lpTemplateName
- .text:00406658 push ebx ; hInstance
- .text:00406659 call ds:DialogBoxParamA
- .text:0040665F push offset byte_6FC520 ; lpString
- .text:00406664 push offset String1 ; int
- .text:00406669 call sub_412F30
- .text:0040666E add esp, 8
- .text:00406671 xor ecx, ecx
- .text:00406673 cmp eax, 7115h
- .text:00406678 setz cl
- .text:0040667B push offset String ; "FabulousMP3 V3.04"
- .text:00406680 push dword_4965E4 ; hWnd
- .text:00406686 mov dword_496788, ecx
- .text:0040668C call ds:SetWindowTextA
- .text:00406692 jmp loc_40658A
- .text:00406697 ; ---------------------------------------
- .text:00406697 loc_406697:
- .text:00406697 mov dword_496788, 0
- .text:004066A1 call sub_4462B0
- .text:004066A6 push 100h
- .text:004066AB push 0
- .text:004066AD push offset byte_6FC520
- .text:004066B2 call sub_4462B0
- .text:004066B7 push 0BB8h
- .text:004066BC call sub_4131D0
- .text:004066C1 add esp, 1Ch
- ; Вывести сообщение о неправильной регистрации
- .text:004066C4 push 0 ; dwInitParam
- .text:004066C6 push offset DialogFunc ; lpDialogFunc
- .text:004066CB push edi ; hWndParent
- .text:004066CC push 0A7h ; lpTemplateName
- .text:004066D1 push ebx ; hInstance
- .text:004066D2 call ds:DialogBoxParamA
Code (Assembler) : Убрать нумерацию
- .text:00412E20 push ebp
- .text:00412E21 mov ebp, esp
- .text:00412E23 mov eax, [ebp+8]
- .text:00412E26 sub esp, 8
- .text:00412E29 mov ecx, offset byte_462483
- .text:00412E2E mov edi, edi
- ...
- ...
- ...
- ; Подсчитать длину строки серийного номера
- .text:00412E91 mov ecx, ebx
- .text:00412E93 lea edx, [ecx+1]
- .text:00412E96 loc_412E96:
- .text:00412E98 inc ecx
- .text:00412E99 test al, al
- .text:00412E9B jnz short loc_412E96
- .text:00412E9D sub ecx, edx
- ; Длина строки должна быть 29 (1Dh) символов
- .text:00412E9F cmp ecx, 1Dh
- .text:00412EA2 jnz short loc_412EB6
- ; Строка серийника должна начинаться с "FAB1-"
- .text:00412EA4 push offset aFab1 ; "FAB1-"
- .text:00412EA9 push ebx
- .text:00412EAA call sub_413260
- .text:00412EAF add esp, 8
- .text:00412EB2 test eax, eax
- .text:00412EB4 jnz short loc_412EBD
- .text:00412EB6 loc_412EB6:
- .text:00412EB6 xor eax, eax
- .text:00412EB8 pop ebx
- .text:00412EB9 mov esp, ebp
- .text:00412EBB pop ebp
- .text:00412EBC retn
- .text:00412EBD ; ---------------------------------------
- .text:00412EBD loc_412EBD:
- .text:00412EBD push edi
- ; Антиотладка: фиксация тайминга выполнения программы
- .text:00412EBE call sub_4479C1
- .text:00412EC3 cdq
- .text:00412EC4 mov edi, offset unk_492F88
- .text:00412EC9 mov [ebp-4], eax
- .text:00412ECC mov [ebp-8], edx
- .text:00412ECF push esi
- .text:00412ED0 loc_412ED0:
- .text:00412ED0 mov esi, [edi]
- .text:00412ED2 push esi
- .text:00412ED3 push dword ptr [ebp+8]
- .text:00412ED6 call sub_404ED0
- .text:00412EDB add esp, 8
- ; Посимвольное сравнение строки серийника с правильным результатом
- .text:00412EDE cmp al, [esi+ebx]
- .text:00412EE1 jnz short loc_412F1B
- ; Антиотладка: проверка тайминга выполнения программы
- .text:00412EE3 call sub_4479C1
- .text:00412EE8 cdq
- .text:00412EE9 mov esi, eax
- .text:00412EEB mov ecx, edx
- .text:00412EED sub esi, [ebp-4]
- .text:00412EF0 sbb ecx, [ebp-8]
- .text:00412EF3 test ecx, ecx
- .text:00412EF5 jg short loc_412F24
- .text:00412EF7 jl short loc_412EFE
- ; Если код выполнялся больше 100 микросекунд, то на выход
- .text:00412EF9 cmp esi, 64h
- .text:00412EFC ja short loc_412F24
- .text:00412EFE loc_412EFE:
- ; Следующая позиция
- .text:00412EFE add edi, 4
- .text:00412F01 mov [ebp-4], eax
- .text:00412F04 mov [ebp-8], edx
- ; Достигнут конец списка позиций?
- .text:00412F07 cmp edi, offset unk_492FE8
- .text:00412F0D jl short loc_412ED0
- .text:00412F0F pop esi
- .text:00412F10 pop edi
- ; Серийник правильный
- .text:00412F11 mov eax, 7115h
- .text:00412F16 pop ebx
- .text:00412F17 mov esp, ebp
- .text:00412F19 pop ebp
- .text:00412F1A retn
- .text:00412F1B ; ---------------------------------------
- .text:00412F1B loc_412F1B:
- ; Серийник неправильный
- .text:00412F1B pop esi
- .text:00412F1C pop edi
- .text:00412F1D xor eax, eax
- .text:00412F1F pop ebx
- .text:00412F20 mov esp, ebp
- .text:00412F22 pop ebp
- .text:00412F23 retn
- .text:00412F24 ; ---------------------------------------
- .text:00412F24 loc_412F24:
- ; Антиотладка: завершить работу программы
- .text:00412F24 push 0
- .text:00412F26 call sub_446FF2
Но похоже, что автор программы попытался предусмотреть подобный вариант подбора серийника и добавил простейшую антиотладку, подвязанную на время исполнения определенного участка кода. Если на проход цикла сравнения потребовалось больше времени, чем это надо в обычном "машинном" исполнении, то значит кто-то ковыряется в программе под отладчиком в пошаговом режиме и поэтому будьте любезны проследовать на выход. Программа принудительно завершит работу. Чтобы этого не произошло, достаточно прямо в отладчике заNOP'ить условные переходы по адресам 00412EF5 и 00412EFC.
Цикл проверки серийника
Теперь ставим точку останова на адрес 00412EDE внутри цикла проверки и отпускаем программу на выполнение. На каждое срабатывание в поле информации будут видны параметры сравнения: символ левого серийника в памяти, а в регистре AL правильное значение. Нам останется только заменить каждый неправильный символ на правильное значение. Долго и нудно. Давайте сделаем хитрее, а конкретно заменим команду проверки на команду записи правильного значения в проверяемую ячейку памяти. Таким образом программа превратится в кейген серийников для любого имени.
Автогенерация правильного серийника
Ставим точку останова после цикла и отпускаем программу на выполнение. Когда точка останова сработает, неправильный серийник будет перезаписан правильным, останется его только скопировать из дампа. Так, для имени "ManHunter / PCL" корректным будет серийный номер FAB1-MT8G-D52V-UEE7-LO0D-2072. Закрываем отладчик, запускаем программу как обычно, повторяем регистрацию.
Программа успешно зарегистрирована
На этот раз программа принимает имя и серийник, благодарит за регистрацию. Не забудьте сохранить серийный номер в сухом прохладном месте, как советует автор, ведь его невозможно выпустить заново. Шутка.
Программа успешно зарегистрирована
Проверяем функционал. Все работает, ограничений по времени нет, триальное окно при запуске пропало, в заголовке окна больше нет сообщения о незарегистрированной программе. Цель достигнута. Спасибо автору за отличную софтину.
Просмотров: 1169 | Комментариев: 6
Метки: исследование защиты, мультимедиа
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
user
(22.04.2023 в 15:39):
Программа сырая - падает на разборе ID3-тегов при загрузке файла.
Илья
(17.04.2023 в 17:57):
Спасибо! Небольшая неточность - длина строки серийника 29 символов
ManHunter
(17.04.2023 в 16:03):
OllyDebug
Илья
(17.04.2023 в 15:56):
Как называется используемая вами программа-отладчик?
ManHunter
(21.02.2023 в 21:44):
Все тлен и безысходность. А в конце ждет смерть и небытие.
Ярослав
(21.02.2023 в 11:03):
А стоит ли вообще авторам софта заморачиваться с защитой, если так или иначе её можно снять? Походу самый надёжный способ это вырезать куски кода, а после оплаты высылать полную версию.
Добавить комментарий
Заполните форму для добавления комментария