Blog. Just Blog

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

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

Tag&Rename - мощный редактор тегов для аудиофайлов со множеством полезных функций. Когда-то я им активно пользовался, подготавливая музыкальные релизы для заливки, но уже несколько лет я этим не занимаюсь и, соответственно, обновлениями редактора не интересовался. Раньше на программу был навешан ASProtect, защита обходилась inline-патчем. Пришло время посмотреть, что там сейчас.

Скачиваем дистрибутив, устанавливаем, смотрим. На первый взгляд файл ничем не упакован, но это только на первый взгляд. Если посмотреть внимательнее, то в списке стандартных названий секций внезапно обнаруживается секция с названием vmp0.

Секция VMProtect
Секция VMProtect

Наличие такой секции в файле может говорить о том, что теперь исполняемый файл защищен VMProtect. Это серьезный инструмент защиты, при грамотном использовании его взлом потребует очень больших затрат сил и времени, да и уровень атакующего должен быть соответствующий. Но пока не будем опускать руки, сперва посмотрим что и как. В этом нам поможет один из главных инструментов - дизассемблер. Параллельно поищем в исполняемом файле строку "UNREGISTERED" из заголовка программы.

Строка в файле
Строка в файле

Юникодная строка найдена. Теперь вернемся в дизассемблер и посмотрим, при каких условиях она появляется.
  1. .text:00C49CBA                 call    sub_406C98
  2. .text:00C49CBF                 mov     eax, off_C82BB0
  3. .text:00C49CC4                 mov     eax, [eax]
  4. .text:00C49CC6                 mov     edx, offset aTagRename3_9_5
  5. ; "Tag&Rename 3.9.5"
  6. .text:00C49CCB                 call    sub_608CE8
  7. .text:00C49CD0                 mov     eax, off_C82BB0
  8. .text:00C49CD5                 mov     eax, [eax]
  9. .text:00C49CD7                 add     eax, 5Ch
  10. .text:00C49CDA                 mov     edx, off_C83050
  11. .text:00C49CE0                 mov     edx, [edx]
  12. .text:00C49CE2                 call    sub_40A210
  13. .text:00C49CE7                 lea     eax, [ebp+var_24]
  14. .text:00C49CEA                 call    sub_C4903C
  15. .text:00C49CEF                 mov     eax, [ebp+var_24]
  16. ; Вызвать функцию проверки
  17. .text:00C49CF2                 call    sub_C48E84
  18. ; Сохранить ее результат из EAX в EBX
  19. .text:00C49CF7                 mov     ebx, eax
  20. .text:00C49CF9                 mov     eax, off_C82D3C
  21. .text:00C49CFE                 mov     eax, [eax]
  22. ; Сохранить в переменную статус регистрации
  23. .text:00C49D00                 mov     [eax], bl
  24. .text:00C49D02                 cmp     bl, 1
  25. ; Если BL=1, то перепрыгнуть замену заголовка
  26. .text:00C49D05                 jz      loc_C49F7F
  27. .text:00C49D0B                 call    sub_C48850
  28. .text:00C49D10                 mov     eax, off_C81E94
  29. .text:00C49D15                 mov     eax, [eax]
  30. .text:00C49D17                 cmp     dword ptr [eax], 0
  31. .text:00C49D1A                 jle     loc_C49F62
  32. .text:00C49D20                 mov     ecx, off_C82BB0
  33. .text:00C49D26                 mov     ecx, [ecx]
  34. .text:00C49D28                 mov     dl, 1
  35. ; Заменить заголовок на UNREGISTERED и показать триальное окно
  36. .text:00C49D2A                 mov     eax, ds:off_90A220
  37. .text:00C49D2F                 call    sub_5FE328
  38. .text:00C49D34                 mov     edx, off_C82690
  39. .text:00C49D3A                 mov     [edx], eax
  40. .text:00C49D3C                 xor     ecx, ecx
  41. .text:00C49D3E                 push    ebp
  42. .text:00C49D3F                 push    offset loc_C49F3B
  43. .text:00C49D44                 push    dword ptr fs:[ecx]
  44. .text:00C49D47                 mov     fs:[ecx], esp
  45. ...
  46. .text:00C49DA8                 call    dword ptr [edx+0ACh]
  47. .text:00C49DAE                 mov     eax, off_C81D08
  48. .text:00C49DB3                 mov     eax, [eax]
  49. .text:00C49DB5                 mov     edx, offset aTagRename3_9_0
  50. ; "Tag&Rename 3.9.5 UNREGISTERED"
  51. .text:00C49DBA                 call    sub_54BA40
  52. .text:00C49DBF                 call    sub_6435A4
  53. .text:00C49DC4                 test    al, al
  54. .text:00C49DC6                 jz      short loc_C49DF3
  55. .text:00C49DC8                 lea     edx, [ebp+var_28]
  56. .text:00C49DCB                 mov     eax, off_C81D08
Тут все понятно. Сперва главному окну программы устанавливается заголовок по умолчанию, если не пройдена проверка на предмет зарегистрированности, то заголовок меняется на триальный. Посмотрим функцию проверки:
  1. .text:00C48E84 ; FUNCTION CHUNK AT .vmp0:00C97383 SIZE 00000005 BYTES
  2. .text:00C48E84 ; FUNCTION CHUNK AT .vmp0:00C97D12 SIZE 00000011 BYTES
  3. .text:00C48E84 ; FUNCTION CHUNK AT .vmp0:00C981FE SIZE 0000001A BYTES
  4. .text:00C48E84
  5. .text:00C48E84                 push    ebp
  6. .text:00C48E85                 mov     ebp, esp
  7. .text:00C48E87                 add     esp, 0FFFFFFC8h
  8. .text:00C48E8A                 push    ebx
  9. .text:00C48E8B                 push    esi
  10. .text:00C48E8C                 xor     edx, edx
  11. .text:00C48E8E                 mov     [ebp+var_4], edx
  12. .text:00C48E91                 mov     ebx, eax
  13. .text:00C48E93                 xor     eax, eax
  14. .text:00C48E95                 push    ebp
  15. .text:00C48E96                 push    offset loc_C4901C
  16. .text:00C48E9B                 push    dword ptr fs:[eax]
  17. .text:00C48E9E                 mov     fs:[eax], esp
А вот и место, где используется VMProtect. Виртуализирована функция проверки корректности серийного номера и состояния регистрации, дизассемблер нам подсказывает об этом ссылками на куски функции в секции vmp0. Точнее виртуализирована не вся функция целиком, начало осталось нетронутым. Вот его мы и будем патчить, даже не заглядывая в защищенный участок кода. Вписываем в начало функции проверки любимую пару команд MOV AL,1 и RET, теперь при любом раскладе серийник будет считаться правильным, а программа - зарегистрированной. Алгоритм проверки серийника узнать не получится, он находится под VMProtect, но эту печаль я как-нибудь переживу. Сохраняем изменения, запускаем, смотрим. Триальное окно при запуске пропало, нехорошая надпись в заголовке тоже.

Скриншот программы Tag&Rename
Скриншот программы Tag&Rename

Но это только половина дела. В окне "О программе" осталась надпись, что программа не зарегистрирована, а также в меню "Помощь" остались пункты меню, отвечающие за покупку и активацию. Можно попробовать зарегистрировать программу какими-нибудь левыми данными:

Сообщение об успешной регистрации
Сообщение об успешной регистрации

Программа их примет, даже поблагодарит за регистрацию, но после этого намертво зависнет с ошибкой обращения к памяти. Надо действовать другим путем. Поиск строки из окна "О программе" выводит нас на ресурсы:

Строка в ресурсах
Строка в ресурсах

Переведем на калькуляторе десятичное значение 64946 в шестнадцатеричное 0FDB2h и поищем эту строку в листинге дизассемблера. Находится хорошо известная нам конструкция указателя на строку в ресурсах.
  1. ; DATA XREF: .data:off_C8219C
  2. .text:00838BEC off_838BEC      dd offset hInstance
  3. .text:00838BF0                 dd 0FDB2h
По единственной перекрестной ссылке переходим на указатель на этот указатель, а уже с него - на код, где эта строка используется.
  1. .text:0090D315                 mov     eax, [ebp+var_C]
  2. .text:0090D318                 mov     eax, [eax+3F4h]
  3. .text:0090D31E                 xor     edx, edx
  4. .text:0090D320                 call    sub_54B908
  5. ; Загрузить адрес указателя по адресу C81DE8
  6. .text:0090D325                 mov     eax, off_C81DE8
  7. .text:0090D32A                 mov     eax, [eax]
  8. ; Проверить байт по загруженному указателю
  9. .text:0090D32C                 cmp     byte ptr [eax], 1
  10. ; Если байт = 1, то не показывать надпись о незарегистрированной версии
  11. .text:0090D32F                 jz      short loc_90D375
  12. .text:0090D331                 lea     edx, [ebp+var_14]
  13. ; Загрузить стоку надписи из ресурсов
  14. .text:0090D334                 mov     eax, off_C8219C
  15. .text:0090D339                 call    sub_643018
  16. .text:0090D33E                 mov     edx, [ebp+var_14]
  17. .text:0090D341                 lea     eax, [ebp+var_10]
  18. .text:0090D344                 call    sub_40AF38
  19. .text:0090D349                 mov     edx, [ebp+var_10]
  20. .text:0090D34C                 mov     eax, [ebp+var_C]
  21. .text:0090D34F                 mov     eax, [eax+3C0h]
  22. .text:0090D355                 call    sub_54BA40
  23. .text:0090D35A                 mov     eax, [ebp+var_C]
  24. .text:0090D35D                 mov     eax, [eax+3C0h]
  25. .text:0090D363                 mov     eax, [eax+6Ch]
Код я прокомментировал, продублирую словами. Проверяется один байт по фиксированному указателю на адрес в памяти. Если он равняется 1, то надпись о том, что программа не зарегистрирована, не выводится. Значит надо найти место, где этот байт инициализируется. Перекрестные ссылки на указатель приводят нас на три участка кода, где выполняются похожие проверки. А вот ссылки на указатель, на который указывает этот указатель (звучит чудовищно, но я натурально не представляю, как еще ЭТО написать), более интересные.

Перекрестные ссылки на указатель
Перекрестные ссылки на указатель

Нам надо найти код, где выполняется какая-нибудь инициализация. Он обнаруживается по второй и третьей перекрестной ссылке.
  1. .itext:00C6FADD                 mov     eax, 1
  2. .itext:00C6FAE2                 call    sub_4067A8
  3. ; Инициализировать указатель
  4. .itext:00C6FAE7                 mov     ds:dword_C8A384, eax
  5. .itext:00C6FAEC                 mov     eax, 1
  6. .itext:00C6FAF1                 call    sub_4067A8
  7. .itext:00C6FAF6                 mov     ds:dword_C8A388, eax
  8. .itext:00C6FAFB                 mov     eax, 4
  9. .itext:00C6FB00                 call    sub_4067A8
  10. .itext:00C6FB05                 mov     ds:dword_C8A38C, eax
  11. .itext:00C6FB0A                 mov     eax, 4
  12. .itext:00C6FB0F                 call    sub_4067A8
  13. .itext:00C6FB14                 mov     ds:dword_C8A390, eax
  14. .itext:00C6FB19                 mov     eax, ds:dword_C8A384
  15. ; Записать начальное значение
  16. .itext:00C6FB1E                 mov     byte ptr [eax], 0
  17. .itext:00C6FB21                 mov     eax, ds:dword_C8A38C
  18. .itext:00C6FB26                 mov     dword ptr [eax], 0FFFFFFFFh
  19. .itext:00C6FB2C                 mov     eax, ds:dword_C8A390
  20. .itext:00C6FB31                 mov     dword ptr [eax], 0FFFFFFFFh
Как мы помним, значение должно быть равно 1. Заменим один байт в команде mov byte ptr [eax], 0, чтобы она превратилась в mov byte ptr [eax], 1. Таким образом программа должна с самого начала считать себя зарегистрированной. Сохраняем изменения и проверяем, так ли это.

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

Надпись в окне "О программе" и пункты меню пропали. Регистрационное имя, к сожалению, тоже не показывается, но это не проблема. Если все-таки хотите видеть ваше имя, то воспользуйтесь следующим трюком. Tag&Rename неоднократно кардили и выкладывали на варезные сайты с валидными серийниками, которые, конечно, сразу попадали в "черный список" и в следующих версиях уже не работали. Так вот, сперва надо скачать любой из таких релизов, установить и зарегистрировать на свое имя. Затем надо накатить поверх обновление до самой последней версии и пропатчить ее, как описано в статье. Регистрационное имя сохранится, несмотря на невалидный серийник.

Цель достигнута. Использование такого серьезного протектора как VMProtect в данном случае ничем не оправдано, навешан он абсолютно неграмотно. Вся защита напоминает пословицу "калитку поставили, а забор забыли".

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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (19.12.2018 в 10:42):
Почитай правила. А пока бан.
Вячеслав (19.12.2018 в 10:37):
Взломайте, пожалуйста, TMPGEnc Video Mastering Works 6
уж сколько лет прошло, никто не взломал..
X-Wing Top Ace (30.05.2016 в 11:49):
Цитатаесли грамотно виртуализировать участки

Именно что если грамотно, а не так, как навешивал VMProtect детектнутый ламер - обо что и речь и у меня, и у автора блога. ;)
ManHunter (25.04.2016 в 17:10):
Цитатаесли грамотно виртуализировать участки

Дык, он именно для этого и предназначен :) Но речь тут идет конкретно про эту софтину, где говнопрот навешан абсолютно неграмотно.
DimitarSerg (25.04.2016 в 16:57):
ЦитатаЛамер детектед. Это я, разумеется, про того, кто VMProtect навешивал.

Да ладно, если грамотно виртуализировать участки, то %90 крякеров сразу обломаются :)
X-Wing Top Ace (19.04.2016 в 19:04):
ЦитатаНа первый взгляд файл ничем не упакован, но это только на первый взгляд.

Ламер детектед. Это я, разумеется, про того, кто VMProtect навешивал. Действительно, забор он забыл, как вы про него и написАли...

ЦитатаЗаменим один байт в команде mov byte ptr [eax], 0, чтобы она превратилась в mov byte ptr [eax], 1.

В порядке мелочных придирок можно написАть о еще одном варианте - заменить на mov код команды cmp по адресу .90В32С и обойти NAGлый код безусловным переходом на loc_90D375 (как я обычно и делаю) - но именно в порядке мелочных придирок. Оба варианта одинаково хороши.
Madness (17.04.2016 в 00:46):
Немедленно вспоминается traffic insector, на котором стоял старфорс. Так вот там генерился серийник в виртуализированной процедуре, но вот сравнение с введенным было сразу после этой процедуры :)
Почему тут не используется упаковка средствами vmprotect, он же вроде это позволяет, не понятно, так бы просто уже не было.

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

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

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