Blog. Just Blog

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

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

Maze Creator - программа для генерации лабиринтов. Отличное решение извечной детской проблемы "Папа, мне скучно!!!". Если кому-то обычные лабиринты покажутся слишком простыми, то Maze Creator умеет делать гексагональные, круглые, треугольные, октагональные и смешанные лабиринты. Причем генерить их можно в любых количествах, каждый раз они будут создаваться заново. Готовый лабиринт можно украсить картинками и текстовыми элементами. Для отчаявшихся можно сохранить файл с прохождением лабиринта. Но есть одно "НО". Точнее не одно, а 70 "НО" за стандартную версию и 400 - за профессиональную.

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

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

Главный исполняемый файл ничем не упакован, отправляем его на разбор в дизассемблер. Когда тот закончит работу, поищем строки, связанные с отсутствием регистрации. Найдется следующий код:
  1. .text:00453BF6                 mov     eax, [ebp-9Ch]
  2. .text:00453BFC                 mov     ecx, [eax+0A8h]
  3. .text:00453C02                 push    ecx
  4. .text:00453C03                 push    offset aUnregisteredYo
  5. ; "UNREGISTERED - You have %d days left ou"...
  6. .text:00453C08                 mov     edx, [ebp-9Ch]
  7. .text:00453C0E                 add     edx, 6FCh
  8. .text:00453C14                 push    edx
  9. .text:00453C15                 call    sub_407CF0
  10. .text:00453C1A                 add     esp, 10h
  11. .text:00453C1D                 push    0
  12. .text:00453C1F                 mov     ecx, [ebp-9Ch]
  13. .text:00453C25                 add     ecx, 5A0h
  14. .text:00453C2B                 call    ?EnableWindow@CWnd@@QAEHH@Z
  15. ; CWnd::EnableWindow(int)
  16. .text:00453C30                 mov     eax, [ebp-9Ch]
  17. .text:00453C36                 cmp     dword ptr [eax+0A8h], 0
  18. .text:00453C3D                 jg      short loc_453C7A
  19. .text:00453C3F                 mov     ecx, [ebp-9Ch]
  20. .text:00453C45                 mov     dword ptr [ecx+9Ch], 1
  21. .text:00453C4F                 push    offset aYourTrialPerio
  22. ; "Your Trial Period is over.  Please purc"...
  23. .text:00453C54                 mov     ecx, [ebp-9Ch]
  24. .text:00453C5A                 add     ecx, 69Ch
  25. .text:00453C60                 call    ?SetWindowTextA@CWnd@@QAEXPBD@Z
  26. ; CWnd::SetWindowTextA(char const *)
  27. .text:00453C65                 push    0
  28. .text:00453C67                 mov     ecx, [ebp-9Ch]
а прямо над ним условные переходы и код, который вызывается в зарегистрированной версии.
  1. .text:00453B57                 push    offset aInstall_31 ; "install"
  2. .text:00453B5C                 call    sub_404F90
  3. .text:00453B61                 mov     ecx, eax
  4. .text:00453B63                 call    ?WriteProfileStringA@CWinApp@@QAEHPBD00@Z
  5. ; Проверить значение переменной, оно должно быть в диапазоне [0..100h]
  6. .text:00453B68                 cmp     dword ptr [ebp-94h], 0
  7. .text:00453B6F                 jl      short loc_453BE9
  8. .text:00453B71                 cmp     dword ptr [ebp-94h], 100h
  9. .text:00453B7B                 jg      short loc_453BE9
  10. ; Если условие выполнено, то программа считается зарегистрированной
  11. .text:00453B7D                 push    offset aFullyRegistere
  12. ; "FULLY REGISTERED"
  13. .text:00453B82                 mov     eax, [ebp-9Ch]
  14. .text:00453B88                 add     eax, 6FCh
  15. .text:00453B8D                 push    eax
  16. .text:00453B8E                 call    sub_407CF0
  17. .text:00453B93                 add     esp, 8
  18. .text:00453B96                 push    1
  19. .text:00453B98                 mov     ecx, [ebp-9Ch]
  20. .text:00453B9E                 add     ecx, 5A0h
  21. .text:00453BA4                 call    ?EnableWindow@CWnd@@QAEHH@Z
  22. ; CWnd::EnableWindow(int)
  23. .text:00453BA9                 mov     ecx, [ebp-9Ch]
  24. .text:00453BAF                 mov     edx, [ecx+74h]
  25. .text:00453BB2                 push    edx
  26. .text:00453BB3                 push    offset aThankYouForYou
  27. ; "Thank you for your purchase of Maze Cre"...
  28. .text:00453BB8                 lea     eax, [ebp-90h]
  29. .text:00453BBE                 push    eax
  30. .text:00453BBF                 call    sub_407CF0
  31. .text:00453BC4                 add     esp, 0Ch
  32. .text:00453BC7                 lea     ecx, [ebp-90h]
  33. .text:00453BCD                 call    unknown_libname_4
  34. .text:00453BD2                 push    eax
  35. .text:00453BD3                 mov     ecx, [ebp-9Ch]
  36. .text:00453BD9                 add     ecx, 69Ch
  37. .text:00453BDF                 call    ?SetWindowTextA@CWnd@@QAEXPBD@Z
  38. ; CWnd::SetWindowTextA(char const *)
Надо найти место, где инициализируется проверяемая переменная. Оно обнаруживается несколькими строчками выше.
  1. .text:00453A90                 push    1
  2. .text:00453A92                 mov     ecx, [ebp-9Ch]
  3. ; Вызвать функцию проверки
  4. .text:00453A98                 call    sub_452AB0
  5. ; Сохранить ее результат в переменную
  6. .text:00453A9D                 mov     [ebp-94h], eax
  7. .text:00453AA3                 mov     ecx, [ebp-9Ch]
  8. .text:00453AA9                 add     ecx, 6F8h
Мы помним, что значение должно получиться больше нуля и меньше-равно 100h. Быстренько заглянем в функцию проверки, убедимся, что там происходит всякая движуха с наборами символов, с ключами, кодами и прочими непонятками, прокрутим до конца и посмотрим, сколько байт надо восстановить на стеке при возврате. Затем впечатываем в начало функции по адресу 00452AB0 пару команд MOV EAX,20h и RET 4. Таким образом мы установим значение из нужного диапазона и восстановим стек при возврате. Сохраняем изменения, запускаем, убеждаемся в работоспособности программы.

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

Теперь в качестве регистрации Maze Creator принимает вообще любые данные, они все считаются правильными. Перевод часов на пару месяцев вперед-назад на работу программы также не влияет. Первая цель успешно достигнута. Надо ли напоминать, что выход в интернет для программы должен быть наглухо закрыт? Теперь переходим к косметическим исправлениям. Начнем с самого простого, это ссылка на сайт автора под каждым сгенерированным лабиринтом. По тексту строки выходим на следующую функцию:
  1. .text:00431FA0 sub_431FA0      proc near
  2. .text:00431FA0                 push    ebp
  3. .text:00431FA1                 mov     ebp, esp
  4. .text:00431FA3                 push    0FFFFFFFFh
  5. .text:00431FA5                 push    offset loc_53F364
  6. .text:00431FAA                 mov     eax, large fs:0
  7. .text:00431FB0                 push    eax
  8. .text:00431FB1                 sub     esp, 44h
  9. .text:00431FB4                 mov     eax, dword_5C2E60
  10. .text:00431FB9                 xor     eax, ebp
  11. .text:00431FBB                 push    eax
  12. .text:00431FBC                 lea     eax, [ebp+var_C]
  13. .text:00431FBF                 mov     large fs:0, eax
  14. .text:00431FC5                 mov     [ebp+var_50], ecx
  15. .text:00431FC8                 push    4
  16. .text:00431FCA                 mov     eax, [ebp+arg_0]
  17. .text:00431FCD                 push    eax
  18. .text:00431FCE                 mov     ecx, [ebp+var_50]
  19. .text:00431FD1                 call    sub_431C90
  20. .text:00431FD6                 mov     [ebp+var_10], eax
  21. .text:00431FD9                 lea     ecx, [ebp+var_3C]
  22. .text:00431FDC                 call    _LocaleUpdate::GetLocaleT(void)
  23. .text:00431FE1                 lea     ecx, [ebp+var_48]
  24. .text:00431FE4                 call    _LocaleUpdate::GetLocaleT(void)
  25. .text:00431FE9                 lea     ecx, [ebp+var_24]
  26. .text:00431FEC                 call    _LocaleUpdate::GetLocaleT(void)
  27. .text:00431FF1                 mov     ecx, [ebp+var_50]
  28. .text:00431FF4                 call    sub_43EB10
  29. .text:00431FF9                 mov     [ebp+var_1C], eax
  30. .text:00431FFC                 lea     ecx, [ebp+var_18]
  31. .text:00431FFF                 call    sub_407600
  32. .text:00432004                 mov     [ebp+var_4], 0
  33. .text:0043200B                 push    offset aCourier ; "Courier"
  34. .text:00432010                 push    30h             ; char
  35. .text:00432012                 push    0               ; char
  36. .text:00432014                 push    0               ; char
  37. .text:00432016                 push    0               ; char
  38. .text:00432018                 push    0               ; char
  39. .text:0043201A                 push    0               ; char
  40. .text:0043201C                 push    0               ; char
  41. .text:0043201E                 push    0               ; char
  42. .text:00432020                 push    190h            ; cWeight
  43. .text:00432025                 push    0               ; cOrientation
  44. .text:00432027                 push    0               ; cEscapement
  45. .text:00432029                 push    0               ; cWidth
  46. .text:0043202B                 mov     ecx, [ebp+var_50]
  47. .text:0043202E                 mov     eax, [ecx+15Ch]
  48. .text:00432034                 cdq
  49. .text:00432035                 sub     eax, edx
  50. .text:00432037                 sar     eax, 1
  51. .text:00432039                 push    eax             ; cHeight
  52. .text:0043203A                 lea     ecx, [ebp+var_18]
  53. .text:0043203D                 call    sub_43EB30
  54. .text:00432042                 lea     edx, [ebp+var_18]
  55. .text:00432045                 push    edx
  56. .text:00432046                 mov     eax, [ebp+arg_0]
  57. .text:00432049                 mov     edx, [eax]
  58. .text:0043204B                 mov     ecx, [ebp+arg_0]
  59. .text:0043204E                 mov     eax, [edx+28h]
  60. .text:00432051                 call    eax
  61. .text:00432053                 mov     [ebp+var_40], eax
  62. .text:00432056                 mov     ecx, [ebp+var_1C]
  63. .text:00432059                 mov     edx, [ecx+0C8h]
  64. .text:0043205F                 neg     edx
  65. .text:00432061                 mov     eax, [ebp+var_50]
  66. .text:00432064                 add     edx, [eax+15Ch]
  67. .text:0043206A                 mov     [ebp+var_30], edx
  68. .text:0043206D                 mov     ecx, [ebp+var_1C]
  69. .text:00432070                 mov     edx, [ecx+0C8h]
  70. .text:00432076                 neg     edx
  71. .text:00432078                 mov     [ebp+var_28], edx
  72. .text:0043207B                 mov     [ebp+var_34], 0
  73. .text:00432082                 mov     eax, [ebp+var_50]
  74. .text:00432085                 mov     ecx, [eax+180h]
  75. .text:0043208B                 mov     [ebp+var_2C], ecx
  76. .text:0043208E                 push    offset aWww_mazecreato
  77. ; "WWW.MAZECREATOR.COM"
  78. .text:00432093                 lea     ecx, [ebp+var_4C]
  79. .text:00432096                 call    sub_4051A0
  80. .text:0043209B                 mov     byte ptr [ebp+var_4], 1
  81. .text:0043209F                 push    101h
  82. .text:004320A4                 lea     edx, [ebp+var_34]
  83. .text:004320A7                 push    edx
  84. .text:004320A8                 lea     eax, [ebp+var_4C]
  85. .text:004320AB                 push    eax
  86. .text:004320AC                 mov     ecx, [ebp+arg_0]
  87. .text:004320AF                 call    sub_407C40
  88. .text:004320B4                 mov     byte ptr [ebp+var_4], 0
  89. .text:004320B8                 lea     ecx, [ebp+var_4C]
  90. .text:004320BB                 call    sub_401870
  91. .text:004320C0                 mov     ecx, [ebp+var_40]
  92. .text:004320C3                 push    ecx
  93. .text:004320C4                 mov     edx, [ebp+arg_0]
  94. .text:004320C7                 mov     eax, [edx]
  95. .text:004320C9                 mov     ecx, [ebp+arg_0]
  96. .text:004320CC                 mov     edx, [eax+28h]
  97. .text:004320CF                 call    edx
  98. .text:004320D1                 lea     ecx, [ebp+var_18]
  99. .text:004320D4                 call    ?DeleteObject@CGdiObject@@QAEHXZ
  100. ; CGdiObject::DeleteObject(void)
  101. .text:004320D9                 mov     [ebp+var_4], 0FFFFFFFFh
  102. .text:004320E0                 lea     ecx, [ebp+var_18]
  103. .text:004320E3                 call    sub_407850
  104. .text:004320E8                 mov     eax, [ebp+var_10]
  105. .text:004320EB                 mov     ecx, [ebp+var_C]
  106. .text:004320EE                 mov     large fs:0, ecx
  107. .text:004320F5                 pop     ecx
  108. .text:004320F6                 mov     esp, ebp
  109. .text:004320F8                 pop     ebp
  110. .text:004320F9                 retn    4
  111. .text:004320F9 sub_431FA0      endp
Все предельно ясно. Выбирается шрифт для надписи, затем надпись наносится на холст окна или сохраняемого изображения. Впечатываем в самое начало функции команду RET 4, чтобы никаких художеств больше не было. Сохраняем изменения, запускаем, проверяем. Подпись под картинкой пропала. Остается пустой отступ, но на него можно не обращать внимания. Как вариант, можно заменить надпись на свою собственную. На этом вторая часть задачи тоже успешно решена. Теперь надо избавиться от ублюдочного фона со ссылками на сайт разработчика, который также принудительно накладывается на каждый создаваемый лабиринт. Картинка обнаруживается в ресурсах:

Картинка в ресурсах
Картинка в ресурсах

Тут есть два варианта решения. Первый, самый простой, - это создать в любом графическом редакторе белый прямоугольник и заменить в редакторе ресурсов картинку с надписями на чистое изображение. Второй вариант связан с бинарной хирургией, ей и займемся. На скриншоте видно, что ресурс с картинкой имеет индекс 171 или 0ABh, если считать в шестнадцатеричной системе. Поищем это значение в листинге дизассемблера. Обнаружится вот такая приметная функция с очень характерными действиями:
  1. .text:00431A00 sub_431A00      proc near
  2. .text:00431A00                 push    ebp
  3. .text:00431A01                 mov     ebp, esp
  4. .text:00431A03                 push    0FFFFFFFFh
  5. .text:00431A05                 push    offset loc_53F32C
  6. .text:00431A0A                 mov     eax, large fs:0
  7. .text:00431A10                 push    eax
  8. .text:00431A11                 sub     esp, 25Ch
  9. .text:00431A17                 mov     eax, dword_5C2E60
  10. .text:00431A1C                 xor     eax, ebp
  11. .text:00431A1E                 mov     [ebp+var_40], eax
  12. .text:00431A21                 push    eax
  13. .text:00431A22                 lea     eax, [ebp+var_C]
  14. .text:00431A25                 mov     large fs:0, eax
  15. .text:00431A2B                 mov     [ebp+var_268], ecx
  16. .text:00431A31                 push    0
  17. .text:00431A33                 lea     ecx, [ebp+var_234]
  18. .text:00431A39                 call    sub_459BF0
  19. .text:00431A3E                 mov     [ebp+var_4], 0
  20. .text:00431A45                 lea     ecx, [ebp+var_24]
  21. .text:00431A48                 call    ??0CDC@@QAE@XZ  ; CDC::CDC(void)
  22. .text:00431A4D                 mov     byte ptr [ebp+var_4], 1
  23. .text:00431A51                 lea     ecx, [ebp+var_23C]
  24. .text:00431A57                 call    _LocaleUpdate::GetLocaleT(void)
  25. .text:00431A5C                 lea     ecx, [ebp+var_38]
  26. .text:00431A5F                 call    _LocaleUpdate::GetLocaleT(void)
  27. .text:00431A64                 lea     ecx, [ebp+var_14]
  28. .text:00431A67                 call    _LocaleUpdate::GetLocaleT(void)
  29. .text:00431A6C                 mov     ecx, [ebp+var_268]
  30. .text:00431A72                 call    sub_43EB10
  31. .text:00431A77                 mov     [ebp+var_28], eax
  32. .text:00431A7A                 push    2               ; lpType
  33. ; Найти и загрузить ресурс с фоновой картинкой
  34. .text:00431A7C                 push    0ABh            ; lpName
  35. .text:00431A81                 push    0               ; hModule
  36. .text:00431A83                 call    ds:FindResourceA
  37. .text:00431A89                 mov     [ebp+hResInfo], eax
  38. .text:00431A8F                 push    0               ; hModule
  39. .text:00431A91                 push    1               ; int
  40. .text:00431A93                 mov     eax, [ebp+hResInfo]
  41. .text:00431A99                 push    eax             ; hResInfo
  42. .text:00431A9A                 lea     ecx, [ebp+var_234]
  43. .text:00431AA0                 call    sub_459840
  44. .text:00431AA5                 lea     ecx, [ebp+var_234]
  45. .text:00431AAB                 call    ?IsOpen@CDatabase@@QBEHXZ
  46. ; CDatabase::IsOpen(void)
  47. .text:00431AB0                 movzx   ecx, al
  48. .text:00431AB3                 mov     [ebp+var_3C], ecx
  49. .text:00431AB6                 mov     edx, [ebp+var_268]
  50. ...
  51. ...
  52. .text:00431C79                 call    sub_51BF7A
  53. .text:00431C7E                 mov     esp, ebp
  54. .text:00431C80                 pop     ebp
  55. .text:00431C81                 retn    4
  56. .text:00431C81 sub_431A00      endp
Всю функцию я тут дублировать не буду, в середине содержится код плиточного заполнения фона рисунка лабиринта этими мерзкими картинками. Отлично, впечатываем в ее начало команду возврата RET 4. Сохраняем изменения, запускаем, проверяем. Теперь лабиринты генерируются на чистом белоснежном фоне. Все поставленные цели достигнуты, можно взять карандаш, распечатать пару листов с головоломками и приступить к тренировке мозга.

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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (23.06.2022 в 13:24):
Шайтанама :)
Grey (20.06.2022 в 11:56):
Мой лабиринт для калькулятора Электроника МК-52. Переписал на питоне спустя 30 лет.
Псевдослучайные числа генерируются с помощью синуса.
------
import math as m
import turtle as tt
sc=50 #scale
bd=2 #border
dd=(50-bd)/2
lavel=30062006
OldCell=4.5
CurCell=5.5
a=(0,-1,-0.1,1,0.1,0,0,0,0,0)
def DrawTWall(x, y):
gg=0
cc=x+y*0.1
if m.sin(lavel*cc*(cc+1))>0:
  tt.pu()
  tt.goto(x*sc+dd,y*sc-dd)
  tt.pd()
  tt.goto(x*sc+dd,y*sc+dd)
  gg=gg+1
if m.sin(lavel*cc*(cc-1))>0:
  tt.pu()
  tt.goto(x*sc-dd,y*sc-dd)
  tt.pd()
  tt.goto(x*sc-dd,y*sc+dd)
  gg=gg+2
if m.sin(lavel*cc*(cc+0.1))>0:
  tt.pu()
  tt.goto(x*sc-dd,y*sc+dd)
  tt.pd()
  tt.goto(x*sc+dd,y*sc+dd)
  gg=gg+4
if m.sin(lavel*cc*(cc-0.1))>0:
  tt.pu()
  tt.goto(x*sc-dd,y*sc-dd)
  tt.pd()
  tt.goto(x*sc+dd,y*sc-dd)
  gg=gg+8
if gg==15:
   tt.goto(x*sc-dd,y*sc+dd)
   tt.pu()
   tt.goto(x*sc-dd,y*sc-dd)
   tt.pd()
   tt.goto(x*sc+dd,y*sc+dd)

for i in range(-8,9):
for j in range(-8,9):
  DrawTWall(i,j)
tt.mainloop()

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

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

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