Blog. Just Blog

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

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

Недавно вышла финальная версия программы Pano2VR, предназначенной для создания трехмерных Flash-панорам из двухмерных сшитых панорам, создания виртуальных туров, панорам с множественным разрешением, панорамных видео и еще много-много другого интересного (примеры работ можете посмотреть на офсайте). Все действия выполняются буквально за несколько кликов, а результат превосходит все ожидания. И все бы ничего, но в триальной версии программа портит создаваемые панорамы своими логотипами, а за лицензию надо выложить совершенно нереальные деньги.

Скачиваем дистрибутив, устанавливаем, смотрим что у нас получается. Исполняемый файл ничем не упакован, отправляем его в дизассемблер для предварительного анализа. Пока он работает, запустим программу и посмотрим что она умеет.

Окно ввода серийного номера
Окно ввода серийного номера

Сразу после запуска открывается окно ввода серийного номера, а также два варианта работы в триальном режиме - просто Trial и Trial Pro. Причем во втором варианте открываются все самые вкусные плюшки программы - создание виртуальных туров из нескольких панорам, добавление своих данных в готовый ролик и удаление информации о самой программе (так называемая unbranded-лицензия), и еще много всего полезного. В обычной версии эти функции недоступны. Значит наша задача получить на выходе именно версию Pro. Поищем в файле какие-нибудь упоминания о лицензиях, триале и тому подобном:

Информация о лицензии
Информация о лицензии

Как много всего! Тут и лицензии для студентов, и образовательные, и еще какие-то ограниченные по времени. Посмотрим, как и на основании чего они подразделяются:
  1. ...
  2. ; Если DWORD по адресу B74CE0 равен 92h, то лицензия "NFR"
  3. .text:0049EE82                 cmp     dword_B74CE0, 92h
  4. .text:0049EE8C                 jnz     loc_49EF16
  5. .text:0049EE92                 push    0
  6. .text:0049EE94                 lea     ecx, [esp+0C8h+var_50]
  7. .text:0049EE98                 push    offset aNfr     ; "NFR"
  8. .text:0049EE9D                 push    ecx
  9. .text:0049EE9E                 call    sub_494220
  10. ...
  11. ...
  12. ; Если DWORD по адресу B74CE0 равен 93h, то лицензия "Student"
  13. .text:0049EF16                 cmp     dword_B74CE0, 93h
  14. .text:0049EF20                 jnz     loc_49EFAA
  15. .text:0049EF26                 push    0
  16. .text:0049EF28                 lea     eax, [esp+0C8h+var_50]
  17. .text:0049EF2C                 push    offset aStudent ; "Student"
  18. .text:0049EF31                 push    eax
  19. .text:0049EF32                 call    sub_494220
  20. ...
На основании этих фрагментов кода мы выяснили, что за тип лицензии отвечает DWORD по адресу 00B74CE0. Посмотрим по перекрестным ссылкам, где же инициализируется это значение.

Перекрестные ссылки на DWORD
Перекрестные ссылки на DWORD

Как видите, все изменения значения типа лицензии происходят в процедуре по адресу 004849D0. Она большая, я ее тут не буду приводить. Первая мысль - пропатчить все "неправильные" значения инициализации, например, на "студенческую" лицензию, то есть 93h. Логично, но в данном случае абсолютно неэффективно. Программа в этом случае все равно работает в триальном режиме. Похоже, что если вообще никакого ключа у программы нет, то при проверке типа лицензии срабатывают какие-то иные ветки алгоритма. Надо искать другой путь. Посмотрим еще раз на перекрестные ссылки. Кроме инициализации в коде выполняется куча проверок типа лицензии. Так почему бы нам не заменить одну из проверок на инициализацию типа лицензии нужным нам значением? Тем более, что раз код инициализации уже отработал, то ничего наше предустановленное значение больше не изменит.

Ставим точку останова на доступ к памяти
Ставим точку останова на доступ к памяти

Поставим в отладчике точку останова на адрес памяти 00B74CE0. Теперь при любом обращении программы к этой ячейке памяти мы об этом сразу же узнаем. Запускаем программу. Первая остановка будет на коде инициализации:
  1. ...
  2. .text:004856AC                 mov     ecx, offset dword_B74CF8
  3. .text:004856B1                 mov     dword_B74CE0, 1
  4. .text:004856BB                 call    ds:??4QString@@QAEAAV0@PBD@Z
  5. ...
Пропускаем ее и снова запускаем программу. Вторая остановка гораздо интереснее:
  1. ...
  2. .text:0049EBE6                 mov     ecx, [esi+88h]
  3. .text:0049EBEC                 lea     edx, [esp+0C4h+var_78]
  4. .text:0049EBF0                 push    edx
  5. .text:0049EBF1                 call    ds:?setText@QLabel@@QAEXABVQString@@@Z
  6. ; Если DWORD по адресу B74CE0 меньше 80h, то лицензии нет или она
  7. ; ограничена по времени
  8. .text:0049EBF7                 cmp     dword_B74CE0, 80h
  9. .text:0049EC01                 jl      loc_49F1F2
  10. .text:0049EC07                 push    0
  11. .text:0049EC09                 lea     eax, [esp+0C8h+var_68]
  12. .text:0049EC0D                 push    offset aLicense ; "License:"
  13. .text:0049EC12                 push    eax
  14. .text:0049EC13                 call    sub_494220
  15. .text:0049EC18                 add     esp, 0Ch
  16. .text:0049EC1B                 mov     eax, ds:?shared_null@QString@@0UData@1@A
  17. .text:0049EC20                 mov     [esp+0C4h+var_7C], eax
  18. .text:0049EC24                 mov     ecx, 1
  19. .text:0049EC29                 lock xadd [eax], ecx
  20. ; Если байт по адресу B74CE4 не равен 0, то лицензия "Pro"
  21. .text:0049EC2D                 cmp     byte_B74CE4, 0
  22. .text:0049EC34                 mov     byte ptr [esp+0C4h+var_4], 7Bh
  23. .text:0049EC3C                 jz      loc_49ECC6
  24. .text:0049EC42                 push    0
  25. .text:0049EC44                 lea     edx, [esp+0C8h+var_50]
  26. .text:0049EC48                 push    offset aPro     ; "pro"
  27. .text:0049EC4D                 push    edx
  28. .text:0049EC4E                 call    sub_494220
  29. .text:0049EC53                 push    offset unk_6D4C50
  30. ...
Ну просто подарок на блюдечке. Тут нам и проверка типа лицензии, и проверка на версию "Pro", которая, оказывается, хранится в байте по адресу 00B74CE4. Приступаем к патчу.

Патчим проверки
Патчим проверки

Заменяем две проверки на команды MOV и нужные нам значения, а чтобы не нарушалась логика работы, также забиваем последующие команды условных переходов на NOP. Сохраняем изменения. Запускаем программу и видим окно с расширенными функциями и греющую душу надпись в правом нижнем углу:

"Студенческая лицензия Pro"
"Студенческая лицензия Pro"

Запускаем, проверяем, все расширенные функции программы работают. Можно на этом остановиться, но есть еще одно маленькое "но". У нас получилась программа, зарегистрированная на именную персональную лицензию, информация о которой будет добавляться в контекстное меню всех создаваемых Flash-роликов, причем эта информация до кучи является ссылкой на сайт программы. Оно вам надо? Вот и мне не надо. Поэтому сейчас будем расширять нашу лицензию до максимально возможной, то есть "unbranded". Никаких прямых упоминаний об этом типе в коде программы нет, поэтому надо подумать и снова призвать на помощь логику. Раз этот пункт меню добавляется в панораму, значит он где-то в программе должен обрабатываться. Поищем что-то подобное в листинге дизассемблера, используя в качестве сигнатуры уже известную нам строчку "Student".
  1. ...
  2. .text:004732F1                 push    offset dword_B74CF8
  3. ; jumptable 004731D9 case 3
  4. .text:004732F6                 lea     eax, [esp+4Ch+var_18]
  5. .text:004732FA                 push    offset aStudentLicense
  6. ; "Student License: "
  7. .text:004732FF                 push    eax
  8. .text:00473300                 call    sub_40AAE0
  9. .text:00473305                 add     esp, 0Ch
  10. .text:00473308                 push    eax
  11. .text:00473309                 lea     ecx, [esp+4Ch+var_2C]
  12. .text:0047330D                 mov     byte ptr [esp+4Ch+var_4], 0Eh
  13. .text:00473312                 call    ds:??4QString@@QAEAAV0@ABV0@@Z
  14. ; QString::operator=(QString const &)
  15. .text:00473318                 mov     ecx, [esp+48h+var_18]
  16. .text:0047331C                 mov     byte ptr [esp+48h+var_4], 0Ah
  17. .text:00473321                 or      edx, 0FFFFFFFFh
  18. .text:00473324                 lock xadd [ecx], edx
  19. .text:00473328                 jnz     short loc_473338
  20. .text:0047332A                 mov     eax, [esp+48h+var_18]
  21. .text:0047332E                 push    eax
  22. .text:0047332F                 call    ds:?free@QString@@CAXPAUData@1@@Z
  23. .text:00473335                 add     esp, 4
  24. .text:00473338 loc_473338:
  25. .text:00473338                 push    offset aHttpGardengn_5
  26. ; "http://gardengnomesoftware.com/pano2vr?"...
  27. .text:0047333D                 lea     ecx, [esp+4Ch+var_28]
  28. .text:00473341                 call    ds:??4QString@@QAEAAV0@PBD@Z
  29. ...
Первое же совпадение и сразу удача. Тут сразу же видны и манипуляции со строкой лицензии, и ссылку на сайт, которая добавляется в контекстное меню, в общем, копать надо здесь. Смотрим на код, с которого выполняется переход:
  1. ...
  2. .text:004731C1                 mov     eax, dword_B74CE0
  3. .text:004731C6                 add     eax, 0FFFFFF70h
  4. .text:004731CB                 mov     byte ptr [esp+48h+var_4], 0Ah
  5. .text:004731D0                 cmp     eax, 3          ; switch 4 cases
  6. .text:004731D3                 ja      loc_473349      ; default
  7. .text:004731D9                 jmp     ds:off_473610[eax*4] ; switch jump
  8. ...
Код короткий, но все-таки требует пояснения. Сперва в регистр EAX записывается значение типа лицензии, затем к нему прибавляется константа 0FFFFFF70h. Если полученный результат больше 3, то выполняется прыжок в обход всех вариантов лицензии (unbranded-версия), иначе в зависимости от полученного значения в меню добавляется информация о лицензии. Теперь чуток математики: 93h + 0FFFFFF70h = 3h. Значит, чтобы получить значение больше 3, надо тип лицензии увеличить как минимум на единицу, то есть в коде инициализации вписывать не 93h, а 94h. Проверим нашу догадку на практике.

Финальный патч
Финальный патч

Сохраняем изменения, запускаем программу. Вот теперь действительно полный порядок. У нас получилась unbranded-версия программы со всем доступными опциями режима Pro. Я даже боюсь представить, сколько это стоило бы в евро, если вдруг кто-то захотел бы ее купить.

"Лицензия Unbranded Pro"
"Лицензия Unbranded Pro"

В принципе, можно даже выделить сигнатуру для универсального патча, чтобы потом не заморачиваться с обновлениями. Автору спасибо за классную программу и интересную защиту, а всем вам спасибо за внимание и успехов в творчестве.

Поделиться ссылкой ВКонтакте
Просмотров: 12204 | Комментариев: 26

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (06.04.2017 в 15:33):
А сейчас мне абсолютно пофиг как, даже если что-то поменялось в защите. Я два раза статьи не пишу и актуальность поддерживать не собираюсь.
nadezda (06.04.2017 в 14:23):
Это было в 2012 году, а сейчас как?
Руслан (02.07.2015 в 16:17):
Прочитал как взломать ) у самого не получается ! помочь кто может ? если да то в контакте [del] буду очень признателен
user0 (09.08.2014 в 20:28):
Спасибо за полезный ресурс.

Вот бы еще почитать про трепанацию PTGui Pro, сейчас как раз они выпустили новую 10 версию со всякими плюшками. Правда с офсайта качается только триал (водяной знак, невозможность сохранить, отсутствие пары функций), но на руборде должны появиться ретейл версии.

ps: кстати, еще одно применение сабжевых программ - склейка Бокерам, фото с широким уголом обзора и малой глубиной резкости, снятых по методу популяризованому свадебным фотографом Райаном Бренайзера (Brenizer method).
ManHunter (15.02.2014 в 13:03):
Ничо не будет. "Мне панораму друг собрал на честно купленной лицензионной программе". И пусть докажут обратное.
артем (15.02.2014 в 13:00):
что будет за такое если выложить панораму на сайт ?
adviser (22.04.2013 в 17:43):
Понятно, спасибо. Отличный результат, хорошая софтина, буду иметь ввиду.
ManHunter (22.04.2013 в 17:07):
Во время съемки пришлось крутиться стоя практически на одной ноге на камне, при этом все вокруг очень активно двигались. Я вообще был удивлен, что панорама собралась относительно безглючно, ожидал худшего результата.
adviser (22.04.2013 в 17:04):
Добрый день. Пошел глянуть ссылочку на панораму Гизы и сразу обратил внимание на голову девушки славянской внешности с темно-рыжими волосами. Голова попала в кадр явно случайно, но привлекла своей формой: явные проблемы с затылком :) А ведь не блондинка :)) Итак, одно из трёх: терминатор или глюк склейки? :)
Роман (22.04.2013 в 15:10):
Жаль, что вы так отзываетесь о маках, видимо вам не приходилось ими пользоваться (ну и конечно вы не желаете)
ManHunter (21.04.2013 в 18:53):
А не знаю и знать не хочу. Раз уж нашлось бабло на эти понторезные огрызки, то найдутся и на программу.
Роман (21.04.2013 в 17:07):
А для мака как?..
Maxim (08.04.2013 в 20:09):
Будем разбираться! Большое спасибо!
ManHunter (08.04.2013 в 07:53):
google -> "введение в крэкинг с нуля рикардо нарваха"
Maxim (07.04.2013 в 23:57):
Добрый вечер! Меня зовут Максим.

Мне очень понравилась Ваша статья! Я очень хочу пользоваться этой программой, но я так и не смог разобраться как Вы правили код. Помогите немного разобраться... Я скачал дизассемблер, но допустим не понял где Вы выполняли мнемонику mov для замены 93 на 94. Ассемблер преподавали только в институте, до этого не делал ни чего серьезного. Если есть возможность, подскажите с чего начать и есть ли шанс у веб программиста разобраться с машинными кодами?
Заранее благодарен.
С уважением, Максим /chekiley@mail.ru/
ManHunter (11.02.2013 в 00:54):
Сферы пока не осилил, ограничиваюсь круговыми панорамами. Если научишь как, то будет хорошо. Аська и мобила прежние.
NorTan (11.02.2013 в 00:12):
Искал обновление для себя и наткнулся на борде =)И от меня мерси!
Сам еще снимать сферы не начал?)
ErikPshat (11.01.2013 в 19:48):
Здравствуйте, случайно натолкнулся на статью - очень понравилось и есть чему поучиться.
У меня есть к этой Панораме небольшой вопросик...
Когда начал рассматривать код, то обнаружил в проге 2 публичных ключа и один похоже приватный, разделённый на несколько частей.
Ну по виду ключей сразу видно, что кодированы они в Base64.

Собственно первая часть, после слова "pro" расшифровалась, как "Your license is not valid! Pano2VR returns to trial mode" - эта надпись отображается при попытке вставить ложный ключ(Файл=>Настройки).
Вторая часть, после слова "the key: " - содержит начальную часть ключа, до 4-ёх нулей.
Далее идёт ещё кусок, но при его использовании прога сразу переходит в Триал.
И в заключении идёт часть ключа, после декриптовки которого получаем читабельное окончание "license/key_v4".
Если соединить 2-ую и заключительную часть и вставить в поле регистрации(Файл=>Настройки), то прога становится зареганной. Но почему-то слова "Pro" я не вижу в зареганной версии, однако похоже прога работает в полнофункциональном режиме. Попробовал создать флеш, никаких копирайтов или надписей не увидел.
Почему-то прога автоматом зарегалась на сами смотрите: http://img7.imageshack.us/img7/5711/1101b.png
CheshireCat (07.01.2013 в 00:44):
Ураааа!!! Получилось! Спасибо тебе огромное!
ManHunter (04.01.2013 в 00:39):
Готовых патчей и ломаных файлов тут никогда не будет.
Bredl (04.01.2013 в 00:36):
Я вот не программист и не смогу повторить процесс описанный в статье, можно ли скачать патч для себя
ManHunter (12.12.2012 в 17:10):
В статье про отпуск есть ссылки на четыре панорамы.
http://www.manhunter.ru/panorama/giza.swf
SAY (12.12.2012 в 17:09):
А можно какую-нить собраную понараму показать здесь?
ManHunter (12.12.2012 в 01:55):
Да уж, приятный такой ребус на пол-дня с перерывами на кофе. Мне самому понравилось. А программа реально полезная, я египетские панорамы именно ей собирал.
Musika (12.12.2012 в 00:59):
Приветствую,

Спасибо. В который раз, удивляюсь, Вашей настойчивости.
noldor (11.12.2012 в 17:01):
Спасибо за разбор, довольно увлекательно!

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

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

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