Blog. Just Blog

Исследование защиты программы Shape Collage

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Скриншот программы Shape Collage
Скриншот программы Shape Collage

Shape Collage - лучшая, на мой взгляд, программа для создания эффектных коллажей из набора фотографий. Коллаж в виде "разбросанных фотографий" создается буквально за несколько кликов, результаты ее работы я частенько использую при оформлении статей. Когда-то давно программа была бесплатной, затем аффтар решил подрезать с нее денег, в незарегистрированной версии добавил маркеры на готовый коллаж и запретил экспорт в .PSD-формат. Предыдущие версии были написаны на Java, регистрация с обязательной онлайн-активацией, поэтому нормально подкорректировать их мне не удавалось. С 3-й версии программа Shape Collage переписана на Qt, размер заметно подрос, но зато появилась возможность вносить в ее работу любые нужные нам изменения.

Скачиваем дистрибутив, устанавливаем, смотрим что у нас получилось. Среди мегатонн библиотек Qt находится главный исполняемый файл ShapeCollage.exe. Он ничем не упакован, отправляем его в дизассемблер и параллельно смотрим на поведение программы. А нам сразу же предлагают обновиться до версии "Pro", где нет маркеров и есть возможность сохранять коллажи в редактируемом формате PhotoShop.

Окно регистрации программы
Окно регистрации программы

При вводе ключа выполняется принудительная онлайн-проверка, она же активация. То есть какой бы мы ключ ни ввели, до момента проверки он будет считаться невалидным. Придется патчить, чтобы программа работала вообще без ключа или около того. Поскольку в Shape Collage заявлен так называемый режим "Pro", то есть полный, то искать надо что-нибудь связанное с этим словом. Например, по строке "Shape Collage Pro" поиск выводит нас на интересный участок кода, по всей видимости как раз отвечающий за реакцию на успешную или неуспешную активацию. Часть кода приходится пропускать, так как он не относится напрямую к интересующей нас ветке алгоритма.
  1. .text:00490047                 mov     [esp+4], esi
  2. .text:0049004B                 lea     ebx, [ebp+var_98]
  3. .text:00490051                 mov     [esp], ebx
  4. ; Вызвать функцию проверки
  5. .text:00490054                 call    sub_47F460
  6. ; Сохранить ее результат из регистра AL в регистре BL
  7. .text:00490059                 mov     bl, al
  8. ...
  9. ; Часть кода пропущена
  10. ...
  11. ; Значение BL нулевое?
  12. .text:00490097                 test    bl, bl
  13. ; Да, переход на сообщение о неправильной регистрации
  14. .text:00490099                 jz      loc_490B60
  15. ...
  16. ; Часть кода пропущена
  17. ...
  18. ; Установить в заголовок, что программа работает в полноценном Pro-режиме
  19. .text:00490163                 mov     dword ptr [esp+4], 0
  20. .text:0049016B                 lea     ebx, [ebp+var_1DC]
  21. .text:00490171                 mov     [esp], ebx
  22. .text:00490174                 call    ds:_ZN11QMessageBoxC1EP7QWidget
  23. .text:0049017A                 mov     dword ptr [esp+4], 0FFFFFFFFh
  24. .text:00490182                 mov     dword ptr [esp], offset aShapeCollage_5
  25. ; "Shape Collage Pro"
  26. .text:00490189                 call    [ebp+var_228]
  27. .text:0049018F                 mov     [ebp+var_A4], eax
  28. .text:00490195                 lea     esi, [ebp+var_A4]
  29. .text:0049019B                 mov     [esp+4], esi
  30. .text:0049019F                 mov     [esp], ebx
  31. .text:004901A2                 call    ds:_ZN11QMessageBox7setTextERK7QString
  32. ...
  33. ...
  34. ; Сюда выполняется переход при BL=0
  35. .text:00490B60 loc_490B60:
  36. .text:00490B60                 mov     dword ptr [esp+4], 0
  37. .text:00490B68                 lea     ebx, [ebp+var_1DC]
  38. .text:00490B6E                 mov     [esp], ebx
  39. ; Сообщение о неправильном серийном номере
  40. .text:00490B71                 call    ds:_ZN11QMessageBoxC1EP7QWidget
  41. .text:00490B77                 lea     edi, [ebp+var_C0]
  42. .text:00490B7D                 mov     dword ptr [esp+0Ch], 0
  43. .text:00490B85                 mov     dword ptr [esp+8], offset aInvalidLicen_0
  44. ; "Invalid License Key"
  45. .text:00490B8D                 mov     dword ptr [esp+4], offset dword_52E148
  46. .text:00490B95                 mov     [esp], edi
Что мы видим? Вызывается функция проверки по адресу 0047F460, на основании ее результата статус и заголовки программы меняются на "Pro" или выводится сообщение о неправильном лицензионном ключе. Значит, чтобы как минимум любой ключ считался правильным, функция проверки должна всегда возвращать AL=1. Для этого патчим ее начало командами MOV AL,1 и RET. Сохраняем изменения.

Программа успешно "зарегистрирована"
Программа успешно "зарегистрирована"

Патченная программа работает прекрасно, никаких ограничений по экспорту в .PSD, никаких маркеров при сохранении. Цель достигнута. При этом регистрационный ключ никуда вводить не пришлось, соответственно, онлайн-активация идет лесом. Но можно ли обойти момент активации, чтобы программа уже как бы проверила серийник и как бы признала его валидным? Предположим, что после активации введенные данные сохраняются где-то в сухом прохладном месте, и в дальнейшем программа проверяет их по мере возможности. Таких мест немного: или реестр, или файлы. Для отлова всех действий программы воспользуемся утилитой Process Monitor с фильтром по имени исполняемого файла.

Обращения программы к реестру
Обращения программы к реестру

Как видно в логе работы монитора, программе надо проверить два ключа в реестре - "name" и "license". Ну раз надо, значит надо. Открываем Блокнот и рисуем в нем файл реестра, в котором по уже известному нам пути пропишем имя и лицензионный ключ. Естественно, значение ключа берется от балды. Сохраняем в файл, например, register.reg, и добавляем данные в реестр.

REGEDIT4

[HKEY_CURRENT_USER\Software\ShapeCollage\OrganizationDefaults]
"license"="1234567890"
"name"="ManHunter / PCL"

Возвращаемся в дизассемблер к функции, которую мы недавно пропатчили, но на этот раз будем работать с оригинальным неизмененным файлом. Посмотрим на функцию проверки повнимательнее, предварительно загуглив назначение некоторых функций Qt:
  1. .text:0047F4B2                 lea     esi, [ebp+var_1C]
  2. .text:0047F4B5                 mov     eax, [ebp+arg_0]
  3. .text:0047F4B8                 mov     [esp+4], eax
  4. .text:0047F4BC                 mov     [esp], esi
  5. ; Перевести строку в верхний регистр
  6. .text:0047F4BF                 call    ds:_ZNK7QString7toUpperEv
  7. .text:0047F4C5                 push    ecx
  8. .text:0047F4C6                 lea     ebx, [ebp+var_20]
  9. .text:0047F4C9                 mov     [esp+4], esi
  10. .text:0047F4CD                 mov     [esp], ebx
  11. .text:0047F4D0                 call    sub_47EA40
  12. .text:0047F4D5                 push    edx
  13. ; Записать в стек значение указателя из регистра EDI
  14. .text:0047F4D6                 mov     [esp+4], edi
  15. ; Записать в стек значение указателя из регистра EBX
  16. .text:0047F4DA                 mov     [esp], ebx
  17. ; Вызвать функцию сравнения строк
  18. .text:0047F4DD                 call    ds:_ZNK7QStringeqERKS_
  19. ; Сохранить в BL результат ее работы
  20. .text:0047F4E3                 mov     bl, al
  21. ...
  22. ; Часть кода пропущена
  23. ...
  24. ; Записать в AL сохраненный результат из BL
  25. .text:0047F543                 mov     al, bl
  26. .text:0047F545                 lea     esp, [ebp-0Ch]
  27. .text:0047F548                 pop     ebx
  28. .text:0047F549                 pop     esi
  29. .text:0047F54A                 pop     edi
  30. .text:0047F54B                 leave
  31. .text:0047F54C                 retn
Оставим матерные комментарии по поводу чистоты и оптимизации кода, так как работа с библиотеками Qt находится где-то за гранью добра и зла. Загрузим программу в отладчик и до запуска поставим точку останова по адресу 0047F4DD, то есть перед непосредственным вызовом функции сравнения, после чего запускаем программу на выполнение. Когда отладчик остановится, посмотрим на стек. Как уже указанно в комментариях к коду, там должны содержаться указатели на сравниваемые строки.

Переходим в дампе на адрес из стека
Переходим в дампе на адрес из стека

Переходим из стека в дамп по первому адресу.

Переходим в дампе на адрес из дампа
Переходим в дампе на адрес из дампа

На строку это не очень похоже, зато похоже на адрес в памяти. Попробуем перейти по нему и посмотреть, что находится там.

Серийник из реестра
Серийник из реестра

Вот, уже лучше. Значит в стек кладется не просто указатель на строку, а указатель на указатель на строку. Это Qt, детка, улыбаемся и машем. В дампе на небольшом смещении от адреса, на который указывает указатель, отчетливо виден наш левый серийник из реестра. Проделаем тот же фокус со вторым адресом из стека.

Строка для сравнения
Строка для сравнения

Похожая структура, но строчка уже другая. Несмотря на все навороты Qt с какими-то префиксами данных, все сводится к сравнению двух юникодных строк: лицензионный ключ из реестра и строка "YXJT4QZDMA". Логично предположить, что это и есть правильный ключ для указанного имени. Заменяем строку лицензии в регистрационном файле на найденную строку из отладчика. Снова добавляем данные в реестр.

REGEDIT4

[HKEY_CURRENT_USER\Software\ShapeCollage\OrganizationDefaults]
"license"="YXJT4QZDMA"
"name"="ManHunter / PCL"

Запускаем программу, не забывая заблокировать онлайн-проверку фаерволом. На этот раз никаких окон регистрации нет, в заголовке указана Pro-версия, а в меню регистрационной информации красуется лицензионный ключ и имя из реестра.

Программа успешно зарегистрирована
Программа успешно зарегистрирована

Программа успешно зарегистрирована, на этот раз практически официально. Онлайн-проверку регистрации блокируем фаерволом. Можно было бы поставить точку, если бы не одно "НО". На своих компьютерах я наблюдал странное поведение программы, оно заключается в том, что при блокировке фаерволом, после завершения работы исполняемый файл ShapeCollage.exe остается в памяти. Не знаю, с чем связан такой косяк, кривизна рук аффтара, особенности работы библиотек Qt или все в совокупности, но факт остается фактом. Или патченный файл, выпущенный в интернет, или корректная регистрация под присмотром фаервола и последующие танцы с бубном по принудительному убиванию зависшего в памяти процесса. Для себя я решил проблему следующим образом. Я просто пропатчил в файле адрес URL, по которому выполняется проверка ключа.

URL для проверки ключа онлайн
URL для проверки ключа онлайн

Скучные логи снифферов трафика приводить не буду, главное, что был найден злополучный адрес. Теперь достаточно его пропатчить, забив нулями, и программу можно смело выпускать в сеть. Лицензия больше не слетит.

Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 5680 | Комментариев: 8

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (12.09.2014 в 20:25):
Никаких готовых патчей на этом сайте никогда не будет.
Евгений. (12.09.2014 в 18:27):
Для непосвященных к таким мануалам неплохо бы и образец патчика прикладывать.
Для ознакомления, так сказать.;-)
104261 (31.08.2014 в 00:15):
DagalProject,
Можно заменить MOV AL,BL по адресу 47А543 на MOV AL,1 без RET.
Спасибо за 'лекцию'.
ManHunter (28.08.2014 в 07:38):
Не обязательно же нулить всю строку целиком, достаточно поменять первый символ, эффект будет точно такой же. Итог = 1 байт :)
AyTkACT (28.08.2014 в 00:42):
Как-то не укладывается в голове понятие "элегантно" и зануление тридцати с лишним байт.  Хотя, сабж не крутил и функцию обработки ответа сервера не видел.
Думаю, что Manhunter'у видней когда 30+ байт патчить, а когда ограничиться патчем в 1 (или 3) байт(а).
voila (27.08.2014 в 21:03):
ммм, какое элегантное решение)
И чтение доставило, спасибо, Хантер!
ManHunter (27.08.2014 в 17:48):
0047F460
DagalProject (27.08.2014 в 17:47):
Здравствуйте! Скажите пожалуйста, для патча по какому адресу должна быть команда MOV AL,1 и команда RET. Спасибо.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2017
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.06 сек. / MySQL: 2 (0.0036 сек.) / Память: 4.5 Mb
Наверх