Blog. Just Blog

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

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

Программа Fine Metronome представляет собой компьютерный вариант метронома. Обычным пользователям она вряд ли пригодится, а вот музыкантам может оказаться полезной. Программа триальная, имеет пробный период в 7 дней без ограничений функционала. А чтобы не отвлекать творческих людей от создания музыки, мы сейчас поможем программе стать бесплатной.

Скачиваем дистрибутив, устанавливаем, запускам. Внешне никаких признаков и ограничений действительно не видно, только в окне "О программе" тикает счетчик оставшихся бесплатных дней ("Осталось семь днее-ее-ее-й!"). Исполняемый файл ничем не упакован, отправим пока его в дизассемблер, а сами поищем где и как оно вообще регистрируется. Окно регистрации обнаружилось за кнопкой "Menu" под пунктом "Register..."

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

А вот на ввод всяких левых данных программа никак не реагирует, только молча закрывает окно ввода серийника. Грамотный ход со стороны разработчиков, ничего не скажешь. Придется искать что-нибудь, похожее на строку "registered", "unregistered", "licensed", "trial" и т.п. Долго искать не пришлось, со второй попытки в файле обнаружилась юникодная строка сообщения с благодарностью за регистрацию:

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

Смотрим в дизассемблере откуда чего берется. Код чистенький, без сюрпризов, все понятно с первого взгляда:
  1. ...
  2. .text:005AF17B                 call    sub_407530
  3. .text:005AF180                 mov     eax, [ebp+var_C]
  4. .text:005AF183                 pop     edx
  5. ; Вызвать функцию проверки
  6. .text:005AF184                 call    sub_567F0C
  7. .text:005AF189                 test    al, al
  8. ; Если в регистре AL вернулся 0, то серийный номер неправильный
  9. .text:005AF18B                 jz      loc_5AF2A5
  10. .text:005AF191                 xor     edx, edx
  11. .text:005AF193                 mov     eax, [ebx+3A4h]
  12. .text:005AF199                 mov     ecx, [eax]
  13. ...
  14. ; Часть кода пропущена. В нем регистрационные данные сохраняются в реестр и т.п.
  15. ...
  16. .text:005AF282                 call    sub_488E20
  17. .text:005AF287                 mov     eax, off_5CB6B0
  18. .text:005AF28C                 mov     eax, [eax]
  19. .text:005AF28E                 mov     eax, [eax+43Ch]
  20. .text:005AF294                 xor     edx, edx
  21. .text:005AF296                 call    sub_4CE480
  22. ; Вывести сообщение об успешной регистрации
  23. .text:005AF29B                 mov     eax, offset aSuccessfullyRe
  24. ; "Successfully registered! Thank you."
  25. .text:005AF2A0                 call    sub_4C6D80
  26. .text:005AF2A5 loc_5AF2A5:
  27. ; Закрыть окно регистрации
  28. .text:005AF2A5                 xor     eax, eax
  29. .text:005AF2A7                 pop     edx
  30. ...
Простой путь - пропатчить начало функции проверки серийного номера по адресу 00567F0C, чтобы она всегда возвращала AL=1. Более сложный путь - разобрать алгоритм проверки серийного номера. На этот раз загружаем программу в отладчик, введем какой-нибудь левый серийник и перед вводом последнего символа поставим точку останова на начало функции проверки регистрационных данных. Почему нельзя ставить точку останова сразу? Программа вызывает эту функцию проверки после ввода каждого символа в поле имени и серийного номера, соответственно, каждый раз будет срабатывать наш breakpoint. Оно вам надо? :)
  1. .text:00567F0C                 push    ebp
  2. .text:00567F0D                 mov     ebp, esp
  3. .text:00567F0F                 mov     ecx, 4
  4. .text:00567F14 loc_567F14:
  5. .text:00567F14                 push    0
  6. .text:00567F16                 push    0
  7. .text:00567F18                 dec     ecx
  8. .text:00567F19                 jnz     short loc_567F14
  9. .text:00567F1B                 push    ecx
  10. .text:00567F1C                 push    esi
  11. .text:00567F1D                 mov     [ebp+var_8], edx
  12. .text:00567F20                 mov     [ebp+var_4], eax
  13. .text:00567F23                 lea     eax, [ebp+var_4]
  14. .text:00567F26                 call    sub_40727C
  15. .text:00567F2B                 lea     eax, [ebp+var_8]
  16. .text:00567F2E                 call    sub_40727C
  17. .text:00567F33                 xor     eax, eax
  18. .text:00567F35                 push    ebp
  19. .text:00567F36                 push    offset loc_56801A
  20. .text:00567F3B                 push    dword ptr fs:[eax]
  21. .text:00567F3E                 mov     fs:[eax], esp
  22. .text:00567F41                 mov     [ebp+var_9], 0
  23. .text:00567F45                 lea     eax, [ebp+var_18]
  24. .text:00567F48                 mov     edx, [ebp+var_4]
  25. .text:00567F4B                 call    sub_40751C
  26. .text:00567F50                 mov     eax, [ebp+var_18]
  27. .text:00567F53                 lea     edx, [ebp+var_14]
  28. .text:00567F56                 call    sub_413A68
  29. .text:00567F5B                 mov     edx, [ebp+var_14]
  30. .text:00567F5E                 lea     eax, [ebp+var_4]
  31. .text:00567F61                 call    sub_407530
  32. .text:00567F66                 lea     eax, [ebp+var_20]
  33. .text:00567F69                 mov     edx, [ebp+var_8]
  34. .text:00567F6C                 call    sub_40751C
  35. .text:00567F71                 mov     eax, [ebp+var_20]
  36. .text:00567F74                 lea     edx, [ebp+var_1C]
  37. .text:00567F77                 call    sub_413A68
  38. .text:00567F7C                 mov     edx, [ebp+var_1C]
  39. .text:00567F7F                 lea     eax, [ebp+var_8]
  40. .text:00567F82                 call    sub_407530
  41. .text:00567F87                 mov     eax, [ebp+var_4]
  42. .text:00567F8A                 xor     edx, edx
  43. .text:00567F8C                 call    sub_407110
  44. .text:00567F91                 jz      short loc_567FF2
  45. .text:00567F93                 mov     eax, [ebp+var_8]
  46. .text:00567F96                 xor     edx, edx
  47. .text:00567F98                 call    sub_407110
  48. .text:00567F9D                 jz      short loc_567FF2
  49. .text:00567F9F                 lea     eax, [ebp+var_24]
  50. .text:00567FA2                 mov     edx, [ebp+var_8]
  51. .text:00567FA5                 call    sub_40751C
  52. ; Перевести серийный номер из строки в число
  53. .text:00567FAA                 mov     eax, [ebp+var_24]
  54. .text:00567FAD                 lea     edx, [ebp+var_10]
  55. .text:00567FB0                 call    sub_4144B8
  56. ; Серийный номер был числовой?
  57. .text:00567FB5                 test    al, al
  58. .text:00567FB7                 jz      short loc_567FF2
  59. ; Начинается функция подсчета правильного серийника для введенного имени
  60. .text:00567FB9                 xor     esi, esi
  61. .text:00567FBB                 mov     eax, [ebp+var_4]
  62. .text:00567FBE                 test    eax, eax
  63. .text:00567FC0                 jz      short loc_567FC9
  64. ; Получить длину строки регистрационного имени с учетом юникода
  65. .text:00567FC2                 sub     eax, 4
  66. .text:00567FC5                 mov     eax, [eax]
  67. .text:00567FC7                 shr     eax, 1
  68. .text:00567FC9 loc_567FC9:
  69. .text:00567FC9                 test    eax, eax
  70. .text:00567FCB                 jle     short loc_567FE3
  71. ; Счетчик символов - с первой позиции
  72. .text:00567FCD                 mov     ecx, 1
  73. .text:00567FD2 loc_567FD2:
  74. ; Указатель на строку регистрационного имени
  75. .text:00567FD2                 mov     edx, [ebp+var_4]
  76. ; Получить следующий байт
  77. .text:00567FD5                 movzx   edx, byte ptr [edx+ecx*2-2]
  78. ; Умножить его на 0Bh (11 десятичное)
  79. .text:00567FDA                 imul    edx, 0Bh
  80. ; Добавить к счетчику
  81. .text:00567FDD                 add     esi, edx
  82. ; Передвинуть указатель на следующий символ строки
  83. .text:00567FDF                 inc     ecx
  84. .text:00567FE0                 dec     eax
  85. ; Все символы обработали?
  86. .text:00567FE1                 jnz     short loc_567FD2
  87. .text:00567FE3 loc_567FE3:
  88. ; Умножить счетчик на 409h
  89. .text:00567FE3                 imul    eax, esi, 409h
  90. ; Результат равен введенному серийнику?
  91. .text:00567FE9                 cmp     eax, [ebp+var_10]
  92. .text:00567FEC                 jnz     short loc_567FF2
  93. ; Да, записать в переменную флажок "зарегистрировано"
  94. .text:00567FEE                 mov     [ebp+var_9], 1
  95. .text:00567FF2 loc_567FF2:
  96. .text:00567FF2                 xor     eax, eax
  97. .text:00567FF4                 pop     edx
  98. .text:00567FF5                 pop     ecx
  99. .text:00567FF6                 pop     ecx
  100. .text:00567FF7                 mov     fs:[eax], edx
  101. .text:00567FFA                 push    offset loc_568021
  102. .text:00567FFF loc_567FFF:
  103. .text:00567FFF                 lea     eax, [ebp+var_24]
  104. .text:00568002                 mov     edx, 5
  105. .text:00568007                 call    sub_4072AC
  106. .text:0056800C                 lea     eax, [ebp+var_8]
  107. .text:0056800F                 mov     edx, 2
  108. .text:00568014                 call    sub_406E08
  109. .text:00568019                 retn
Теперь вы можете пройти функцию в пошаговом режиме под отладчиком, чтобы уяснить для себя все ключевые моменты. Я сразу прокомментировал код для удобства восприятия.

Что у нас в итоге получается? Введенный регистрационный код переводится в численное представление, затем на основании регистрационного имени рассчитывается правильный серийник, после чего эти два значения сравниваются. Алгоритм расчета следующий: ASCII-код каждого символа регистрационного имени умножается на 0Bh, значения суммируются. Результат сложения умножается на число 409h, а полученное значение в десятичной системе счисления и будет искомым серийный номером. Так, например, рабочей парой будет регистрационное имя "ManHunter / PCL" и код 14181024. Кнопку "Ok" даже не пришлось нажимать, сообщение об успешной регистрации появляется сразу же после ввода правильных данных.

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

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

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

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

Комментарии

Отзывы посетителей сайта о статье
Isaev (28.09.2011 в 21:06):
Dimas, на счёт времени согласен
я её кейгенил, когда времени было навалом
Dimas (27.09.2011 в 18:05):
Isaev, я написал не про то что, надо патчить (сам стараюсь обходится в самых крайних случаях), а про то что, я как человек с хроническим дефицитом времени очень сильно его ценю - и если прожка дает мне серийник - то мое ИМХО лучше за пару минут сбацать сниферок, ну или как вариант, заставить прогу саму записать рег. данные в реестр например? Кстати чем не тема ManHunter? (вроде такого не было)
Повторяюсь ИМХО )
Isaev (26.09.2011 в 03:06):
Прыжки патчить не интересно... Там привязка к железу
Dimas (24.09.2011 в 16:21):
Какая-то она странная эта Billion Chords, поменял прыжок один - сама себя зарегистрировала) - все желание ковырять генерацию серийника пропало...
ManHunter (22.09.2011 в 18:36):
Пусть эти (ч)удаки сперва ссылку на закачку починят, тогда и буду кейгенить.
Isaev (22.09.2011 в 18:35):
Гитара это хорошо... Вот разбери, если хочешь
http://www.chordeditor.com/
там интересно кейгенить и полезно для гитариста )
ManHunter (22.09.2011 в 14:59):
Изучить Ассемблер, без этого в реверсе делать нечего. Почитать статьи на exelab.ru, wasm.ru, tuts4you.org, там тоже разобраны примеры защит, некоторые гораздо подробнее чем у меня. На wasm переведены замечательные статьи Рикардо Нарвахи по работе с отладчиком, как раз для новичков.

Если желание еще не пропадет, то порешать всякие простенькие крякмисы (в любом гуглояндексе по запросу "crackmes"). Ну а потом и за реальный софт можно браться.
Musika (22.09.2011 в 14:51):
Приветствую,

допустим мне стало интересно и я решил
научиться делать подобное.
Не ради конечного результата, но ради самого процесса.
С чего начать Вы бы посоветовали ?
Спасибо.
ManHunter (22.09.2011 в 14:47):
Ну так, на гитаре немного играю :) Когда-то и трекерной музыкой баловался, но отсутствие музыкального образования усложнило этот процесс.
Isaev (22.09.2011 в 14:46):
А ты музыкант ещё?

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

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

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