Blog. Just Blog

Исследование защиты скринсейвера Incredible Mars 3D

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

Под сегодняшнюю принудительную раздачу халявы у нас попадает скринсейвер Incredible Mars 3D. На экране крутится планета Марс, причем как в ее нынешнем высушенном состоянии, так и ее гипотетическая версия, когда планета была покрыта водой и всякой зеленью. Не самый великий шедевр скринсейверостроения, конечно, но в качестве подопытного вполне сгодится.

Скачиваем дистрибутив, устанавливаем. Основной файл скринсейвера Incredible Mars 3D.scr устанавливается в папку с Windows, поэтому искать его надо именно там. Файл ничем не упакован, поэтому сразу отправляем его в дизассемблер. Дальше открываем системные настройки скринсейверов, выбираем Incredible Mars 3D и открываем его свойства.

Настройки скринсейвера и окно регистрации
Настройки скринсейвера и окно регистрации

На ввод неправильного серийного номера программа реагирует сообщением "The key is incorrect", значит надо поискать его в файле:

Нехорошая строка найдена
Нехорошая строка найдена

Строчка найдена, и там же рядом, по всей видимости, строка сообщения об успешной регистрации. Теперь поищем в дизассемблере ссылки на эти строчки и условия, при которых они появляются.
  1. ...
  2. .text:00422E48                 mov     eax, ds:dword_44788C
  3. .text:00422E4D                 mov     [esp+1ECh+var_1DC], 0
  4. .text:00422E55                 mov     [esp+1ECh+var_1E0], offset sub_422110
  5. .text:00422E5D                 mov     [esp+1ECh+var_1E4], ebp
  6. .text:00422E61                 mov     [esp+1ECh+var_1E8], 68h
  7. .text:00422E69                 mov     [esp+1ECh+var_1EC], eax
  8. .text:00422E6C                 mov     ebx, 1
  9. .text:00422E71                 call    DialogBoxParamA
  10. .text:00422E76                 sub     esp, 14h
  11. .text:00422E79                 test    eax, eax
  12. .text:00422E7B                 jz      loc_422248
  13. ; Если байт по адресу 430158 равен нулю, то введенный серийник правильный
  14. .text:00422E81                 cmp     byte_430158, 0
  15. .text:00422E88                 jz      loc_422FE2
  16. ; Иначе вывести сообщение о неправильном серийном номере
  17. .text:00422E8E                 mov     [esp+1ECh+var_1E0], 10h
  18. .text:00422E96                 mov     [esp+1ECh+var_1E4], offset aError
  19. ; "Error"
  20. .text:00422E9E                 mov     [esp+1ECh+var_1E8], offset aTheKeyIsIncorr
  21. ; "The key is incorrect."
  22. .text:00422EA6                 mov     [esp+1ECh+var_1EC], ebp
  23. .text:00422EA9                 call    MessageBoxA
  24. ; ---------------
  25. ; часть кода пропущена
  26. ; ---------------
  27. .text:00422FE2 loc_422FE2:
  28. ; Сообщение об успешной регистрации
  29. .text:00422FE2                 call    sub_401B40
  30. .text:00422FE7                 lea     esi, [esp+1ECh+hWnd]
  31. .text:00422FEB                 mov     eax, ds:dword_44788C
  32. .text:00422FF0                 mov     [esp+1ECh+var_1E4], esi
  33. .text:00422FF4                 mov     [esp+1ECh+var_1E0], 104h
  34. .text:00422FFC                 mov     [esp+1ECh+var_1E8], 9C41h
  35. .text:00423004                 mov     [esp+1ECh+var_1EC], eax
  36. .text:00423007                 call    LoadStringA
  37. .text:0042300C                 sub     esp, 10h
  38. .text:0042300F                 mov     [esp+1ECh+var_1EC], ebp
  39. .text:00423012                 mov     [esp+1ECh+var_1E0], 40h
  40. .text:0042301A                 mov     [esp+1ECh+var_1E4], offset aSuccess
  41. ; "Success"
  42. .text:00423022                 mov     [esp+1ECh+var_1E8], offset aRegistrationCo
  43. ; "Registration completed."
  44. .text:0042302A                 call    MessageBoxA
  45. ...
Значит флажок условия триальности хранится в байте по адресу 0430158h. Если он равен нулю, то программа зарегистрирована, и если равен 1, то программа работает в триальном режиме. Все не как у людей, все нормальные разработчики взводят флажок зарегистрированности, а тут сбрасывают флажок триальности. Ладно, космические фантазии аффтаров нам не очень интересны, нас больше интересует где же этот флажок инициализируется и изменяется. Посмотрим в сегменте данных:
  1. .data:00430158 byte_430158     db 1
Еще более странно. Значение флажка триальности вбито прямо в данные и по умолчанию сразу же равно "незарегистрировано". Смоторим перекрестные ссылки на этот несчастный байт:

Перекрестные ссылки на байт
Перекрестные ссылки на байт

Все очевидно. Первые две ссылки - инициализация флажка в режим триальности и в режим зарегистрированной программы, а дальше только куча проверок. Нас интересует вторая ссылка, там флажок сбрасывается и программа переходит в зарегистрированный режим. Надо посмотреть, где и как это делается. Вся инициализация и проверка оформлены в виде отдельной процедуры. Для наглядности лучше ее пройти под отладчиком.
  1. .text:00401920                 push    ebp
  2. .text:00401921                 push    edi
  3. .text:00401922                 push    esi
  4. .text:00401923                 push    ebx
  5. .text:00401924                 sub     esp, 8Ch
  6. ; Начальная инициализация - программа по умолчанию не зарегистрирована
  7. .text:0040192A                 mov     byte_430158, 1
  8. ; Если вообще никакого серийного номера нет, то сразу на выход
  9. .text:00401931                 cmp     ds:byte_4476E0, 0
  10. .text:00401938                 jz      loc_401B2E
  11. ; Перевести серийник в верхний регистр
  12. .text:0040193E                 lea     edi, [esp+9Ch+var_3C]
  13. .text:00401942                 mov     ecx, 8
  14. .text:00401947                 xor     eax, eax
  15. .text:00401949                 xor     esi, esi
  16. .text:0040194B                 rep stosd
  17. .text:0040194D                 xor     ebx, ebx
  18. .text:0040194F                 mov     edi, ds:__mb_cur_max
  19. .text:00401955                 mov     ebp, ds:_pctype
  20. .text:0040195B                 jmp     short loc_401982
  21. .text:0040195B ; -----------------------------------
  22. .text:0040195D                 align 10h
  23. .text:00401960 loc_401960:
  24. .text:00401960                 mov     edx, [ebp+0]
  25. .text:00401963                 movzx   eax, word ptr [edx+eax*2]
  26. .text:00401967                 and     eax, 80h
  27. .text:0040196C loc_40196C:
  28. .text:0040196C                 test    eax, eax
  29. .text:0040196E                 jz      short loc_40197C
  30. .text:00401970                 movzx   eax, ds:byte_4476E0[ebx]
  31. .text:00401977                 mov     [esp+esi+9Ch+var_3C], al
  32. .text:0040197B                 inc     esi
  33. .text:0040197C loc_40197C:
  34. .text:0040197C                 inc     ebx
  35. .text:0040197D                 cmp     ebx, 20h
  36. .text:00401980                 jz      short loc_4019A0
  37. .text:00401982 loc_401982:
  38. .text:00401982                 movsx   eax, ds:byte_4476E0[ebx]
  39. .text:00401989                 cmp     dword ptr [edi], 1
  40. .text:0040198C                 jz      short loc_401960
  41. .text:0040198E                 mov     [esp+9Ch+var_98], 80h
  42. .text:00401996                 mov     [esp+9Ch+var_9C], eax
  43. .text:00401999                 call    _isctype
  44. .text:0040199E                 jmp     short loc_40196C
  45. .text:004019A0 ; --------------------------------------------
  46. .text:004019A0 loc_4019A0:
  47. ; А вот тут начинаются манипуляции с серийным номером
  48. .text:004019A0                 lea     esi, [esp+9Ch+var_7C]
  49. .text:004019A4                 xor     eax, eax
  50. .text:004019A6                 movzx   edx, [esp+9Ch+var_3C]
  51. .text:004019AB                 lea     edi, [esp+9Ch+var_5C]
  52. .text:004019AF                 mov     ecx, 8
  53. .text:004019B4                 rep stosd
  54. .text:004019B6                 mov     [esp+9Ch+var_54], dl
  55. .text:004019BA                 lea     edi, [esp+9Ch+var_7C]
  56. .text:004019BE                 movzx   edx, [esp+9Ch+var_3B]
  57. .text:004019C3                 mov     cl, 8
  58. .text:004019C5                 mov     [esp+9Ch+var_55], dl
  59. .text:004019C9                 movzx   edx, [esp+9Ch+var_3A]
  60. .text:004019CE                 mov     [esp+9Ch+var_53], dl
  61. .text:004019D2                 movzx   edx, [esp+9Ch+var_39]
  62. .text:004019D7                 mov     [esp+9Ch+var_56], dl
  63. .text:004019DB                 movzx   edx, [esp+9Ch+var_38]
  64. .text:004019E0                 mov     [esp+9Ch+var_52], dl
  65. .text:004019E4                 movzx   edx, [esp+9Ch+var_37]
  66. .text:004019E9                 mov     [esp+9Ch+var_57], dl
  67. .text:004019ED                 movzx   edx, [esp+9Ch+var_36]
  68. .text:004019F2                 mov     [esp+9Ch+var_51], dl
  69. .text:004019F6                 movzx   edx, [esp+9Ch+var_35]
  70. .text:004019FB                 mov     [esp+9Ch+var_58], dl
  71. .text:004019FF                 movzx   edx, [esp+9Ch+var_34]
  72. .text:00401A04                 mov     [esp+9Ch+var_50], dl
  73. .text:00401A08                 movzx   edx, [esp+9Ch+var_33]
  74. .text:00401A0D                 mov     [esp+9Ch+var_59], dl
  75. .text:00401A11                 movzx   edx, [esp+9Ch+var_32]
  76. .text:00401A16                 mov     [esp+9Ch+var_4F], dl
  77. .text:00401A1A                 movzx   edx, [esp+9Ch+var_31]
  78. .text:00401A1F                 mov     [esp+9Ch+var_5A], dl
  79. .text:00401A23                 movzx   edx, [esp+9Ch+var_30]
  80. .text:00401A28                 mov     [esp+9Ch+var_4E], dl
  81. .text:00401A2C                 movzx   edx, [esp+9Ch+var_2F]
  82. .text:00401A31                 mov     [esp+9Ch+var_5B], dl
  83. .text:00401A35                 movzx   edx, [esp+9Ch+var_2E]
  84. .text:00401A3A                 mov     [esp+9Ch+var_4D], dl
  85. .text:00401A3E                 movzx   edx, [esp+9Ch+var_2D]
  86. .text:00401A43                 mov     [esp+9Ch+var_5C], dl
  87. .text:00401A47                 rep stosd
  88. .text:00401A49                 lea     eax, [esp+9Ch+var_5C]
  89. .text:00401A4D                 mov     [esp+9Ch+var_9C], esi
  90. .text:00401A50                 mov     edi, 0A3F3h
  91. .text:00401A55                 mov     [esp+9Ch+var_94], 8
  92. .text:00401A5D                 mov     [esp+9Ch+var_98], eax
  93. .text:00401A61                 call    strncpy
  94. .text:00401A66                 mov     [esp+9Ch+var_9C], esi
  95. .text:00401A69                 mov     [esp+9Ch+var_94], 10h
  96. .text:00401A71                 mov     [esp+9Ch+var_98], 0
  97. .text:00401A79                 call    strtoul
  98. .text:00401A7E                 mov     [esp+9Ch+var_9C], esi
  99. .text:00401A81                 mov     ebx, eax
  100. .text:00401A83                 mov     [esp+9Ch+var_94], 8
  101. ; Собрать 8 нечетных символов серийника в обратном порядке, преобразовать
  102. ; их в HEX-число и поXORить результат с 05AEB7C3h
  103. .text:00401A8B                 xor     ebx, 5AEB7C3h
  104. .text:00401A91                 lea     eax, [esp+9Ch+var_54]
  105. .text:00401A95                 mov     [esp+9Ch+var_98], eax
  106. .text:00401A99                 call    strncpy
  107. .text:00401A9E                 mov     [esp+9Ch+var_9C], esi
  108. .text:00401AA1                 mov     [esp+9Ch+var_94], 10h
  109. .text:00401AA9                 mov     [esp+9Ch+var_98], 0
  110. .text:00401AB1                 call    strtoul
  111. .text:00401AB6                 mov     [esp+9Ch+var_94], 0A3F3h
  112. .text:00401ABE                 mov     esi, eax
  113. .text:00401AC0                 mov     [esp+9Ch+var_90], 0
  114. ; Собрать 8 четных символов серийника в HEX-число и поXORить полученный
  115. ; результат с 14AB7B4Ah
  116. .text:00401AC8                 xor     esi, 14AB7B4Ah
  117. ; Теперь в ESI проверочное значение
  118. .text:00401ACE                 mov     [esp+9Ch+var_9C], ebx
  119. .text:00401AD1                 mov     [esp+9Ch+var_98], 0
  120. .text:00401AD9                 call    sub_42EB10
  121. .text:00401ADE                 mov     [esp+9Ch+var_94], 0A3F3h
  122. .text:00401AE6                 imul    ecx, edx, 0A3F3h
  123. .text:00401AEC                 mov     [esp+9Ch+var_90], 0
  124. .text:00401AF4                 mul     edi
  125. .text:00401AF6                 mov     [esp+9Ch+var_9C], ebx
  126. .text:00401AF9                 add     edx, ecx
  127. .text:00401AFB                 mov     [esp+9Ch+var_84], eax
  128. .text:00401AFF                 mov     [esp+9Ch+var_80], edx
  129. .text:00401B03                 mov     [esp+9Ch+var_98], 0
  130. .text:00401B0B                 call    sub_42EC34
  131. .text:00401B10                 add     eax, [esp+9Ch+var_84]
  132. .text:00401B14                 mov     edi, eax
  133. .text:00401B16                 add     edi, 7B1h
  134. .text:00401B1C                 mul     edi
  135. .text:00401B1E                 add     eax, 7CBh
  136. ; Сравнить вычисленное значение EAX с сохраненным ESI
  137. .text:00401B23                 cmp     esi, eax
  138. .text:00401B25                 jnz     short loc_401B2E
  139. ; Регистрационный номер правильный
  140. .text:00401B27                 mov     byte_430158, 0
  141. .text:00401B2E loc_401B2E:
  142. ...
В коде я прокомментировал ключевые моменты, но повторю их словами. Из серийного номера выбираются нечетные символы в обратном порядке, начиная с 15-го. То есть длина серийника должна быть 16 символов. Затем из него же выбираются все четные символы по порядку, начиная с нулевого. Для наглядности из введенного серийника 192A3B4C5D6E7F80 получится две строки "0FEDCBA" и "12345678". Дальше эти строки переводятся в шестнадцатеричные числа, первое XORится с константой 05AEB7C3h, а второе с константой 14AB7B4Ah. Полученный из второго преобразования результат является проверочным значением для серийника. А на основании первого числа, путем различных преобразований, получается тестовое число. Если оно равно проверочному, то серийный номер правильный и в байт 0430158h заносится ноль.

Первый вариант решения проблемы регистрации - патч. Достаточно заменить команду инициализации mov byte_430158, 1 на mov byte_430158, 0, а затем поменять с 1 на 0 начальное значение байта в файле. После этого скринсейвер переходит в полноценный режим работы. Это быстро, эффективно, но неспортивно.

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

Второй вариант - серийный номер. Разбирать все алгоритмы преобразований мне лениво, а вот подобрать какой-нибудь правильный серийный номер вполне реально. Вспомним алгоритм проверки. На последнем этапе у нас есть тестовое число, которое должно быть равно проверочному.

Тестовое число = (четные символы) XOR 14AB7B4Ah
Уравнение младших классов. Тестовое число мы узнаем при проверке, команда XOR обратимая и при ее применении с тем же параметром 14AB7B4Ah мы получим некое число, которое является четными символами серийного номера. То есть подбор сводится к тому, чтобы на основании введенных нечетных символов в конце проверки узнать правильные четные символы. Берем серийник "192A3B4C5D6E7F80", под отладчиком пытаемся зарегистрировать им программу. Тестовое число в регистре EAX получается "8BDBD25D":

Сравнение тестового и контрольного чисел
Сравнение тестового и контрольного чисел

Осталась простейшая двоичная математика: 8BDBD25D xor 14AB7B4A = 9F70A917, это и есть искомые символы серийного номера, которые должны быть на четных позициях. Записываем их в серийный номер, получается строка "99FA7B0CAD9E1F70". Попробуем зарегистрировать скринсейвер с его помощью.

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

Вот теперь все красиво. Серийный номер принят, скринсейвер работает в полном режиме. Можете бесплатно приобщаться к красотам космоса.

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

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

Комментарии

Отзывы посетителей сайта о статье
Petya (03.11.2020 в 16:02):
Благодарствую.
Petya (03.11.2020 в 15:27):
Дистрибутива не сохранилось? Офсайт мёртв.
DimitarSerg (10.10.2012 в 00:08):
Насчет зашифрованных строк и нестандартных путей поиска:
Вот это интересно было когда-то (настоятельно рекоммендую), те, что без надписи FREE:
http://www.mcrenox.com.ar/downloads/

своеобразно, но не сложно, а если повезет, то ваяется скрипт и достаются валидные серийники, кейген я чёт так и не осилил в свое время (может обленился).
ManHunter (09.10.2012 в 19:15):
Только если вспомню или найду такую программу. На ум приходит только BWMeter, но я его тут уже разбирал.
Балбес (09.10.2012 в 19:14):
Не могли бы вы показать пример взлома программы, в котором бы демонстрировались нестандартные пути поиска регистрации, к примеру, когда строки зашифрованы?

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

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

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