Исследование защиты программы Maze Creator
Скриншот программы Maze Creator
Maze Creator - программа для генерации лабиринтов. Отличное решение извечной детской проблемы "Папа, мне скучно!!!". Если кому-то обычные лабиринты покажутся слишком простыми, то Maze Creator умеет делать гексагональные, круглые, треугольные, октагональные и смешанные лабиринты. Причем генерить их можно в любых количествах, каждый раз они будут создаваться заново. Готовый лабиринт можно украсить картинками и текстовыми элементами. Для отчаявшихся можно сохранить файл с прохождением лабиринта. Но есть одно "НО". Точнее не одно, а 70 "НО" за стандартную версию и 400 - за профессиональную.
Профессиональная версия доступна для скачивания только после покупки. Максимум, что можно свободно скачать с сайта, это версия "стандарт". Ну ничего, мы не гордые, нам хватит и ее. Распаковываем, устанавливаем, смотрим. Из триальных проявлений есть ограниченное время работы, плюс всякие триальные окна с предложением регистрации, открывающиеся при запуске. Из косметических недоработок можно отметить копирайтную надпись на каждом сгенерированном лабиринте и принудительный фоновый рисунок, который также накладывается на любой создаваемый лабиринт. Брендирование вроде как можно отключить в профессиональной версии, в стандартной версии это не предусмотрено. В остальном я никаких ограничений не нашел.
Окно регистрации
Главный исполняемый файл ничем не упакован, отправляем его на разбор в дизассемблер. Когда тот закончит работу, поищем строки, связанные с отсутствием регистрации. Найдется следующий код:
Code (Assembler) : Убрать нумерацию
- .text:00453BF6 mov eax, [ebp-9Ch]
- .text:00453BFC mov ecx, [eax+0A8h]
- .text:00453C02 push ecx
- .text:00453C03 push offset aUnregisteredYo
- ; "UNREGISTERED - You have %d days left ou"...
- .text:00453C08 mov edx, [ebp-9Ch]
- .text:00453C0E add edx, 6FCh
- .text:00453C14 push edx
- .text:00453C15 call sub_407CF0
- .text:00453C1A add esp, 10h
- .text:00453C1D push 0
- .text:00453C1F mov ecx, [ebp-9Ch]
- .text:00453C25 add ecx, 5A0h
- .text:00453C2B call ?EnableWindow@CWnd@@QAEHH@Z
- ; CWnd::EnableWindow(int)
- .text:00453C30 mov eax, [ebp-9Ch]
- .text:00453C36 cmp dword ptr [eax+0A8h], 0
- .text:00453C3D jg short loc_453C7A
- .text:00453C3F mov ecx, [ebp-9Ch]
- .text:00453C45 mov dword ptr [ecx+9Ch], 1
- .text:00453C4F push offset aYourTrialPerio
- ; "Your Trial Period is over. Please purc"...
- .text:00453C54 mov ecx, [ebp-9Ch]
- .text:00453C5A add ecx, 69Ch
- .text:00453C60 call ?SetWindowTextA@CWnd@@QAEXPBD@Z
- ; CWnd::SetWindowTextA(char const *)
- .text:00453C65 push 0
- .text:00453C67 mov ecx, [ebp-9Ch]
Code (Assembler) : Убрать нумерацию
- .text:00453B57 push offset aInstall_31 ; "install"
- .text:00453B5C call sub_404F90
- .text:00453B61 mov ecx, eax
- .text:00453B63 call ?WriteProfileStringA@CWinApp@@QAEHPBD00@Z
- ; Проверить значение переменной, оно должно быть в диапазоне [0..100h]
- .text:00453B68 cmp dword ptr [ebp-94h], 0
- .text:00453B6F jl short loc_453BE9
- .text:00453B71 cmp dword ptr [ebp-94h], 100h
- .text:00453B7B jg short loc_453BE9
- ; Если условие выполнено, то программа считается зарегистрированной
- .text:00453B7D push offset aFullyRegistere
- ; "FULLY REGISTERED"
- .text:00453B82 mov eax, [ebp-9Ch]
- .text:00453B88 add eax, 6FCh
- .text:00453B8D push eax
- .text:00453B8E call sub_407CF0
- .text:00453B93 add esp, 8
- .text:00453B96 push 1
- .text:00453B98 mov ecx, [ebp-9Ch]
- .text:00453B9E add ecx, 5A0h
- .text:00453BA4 call ?EnableWindow@CWnd@@QAEHH@Z
- ; CWnd::EnableWindow(int)
- .text:00453BA9 mov ecx, [ebp-9Ch]
- .text:00453BAF mov edx, [ecx+74h]
- .text:00453BB2 push edx
- .text:00453BB3 push offset aThankYouForYou
- ; "Thank you for your purchase of Maze Cre"...
- .text:00453BB8 lea eax, [ebp-90h]
- .text:00453BBE push eax
- .text:00453BBF call sub_407CF0
- .text:00453BC4 add esp, 0Ch
- .text:00453BC7 lea ecx, [ebp-90h]
- .text:00453BCD call unknown_libname_4
- .text:00453BD2 push eax
- .text:00453BD3 mov ecx, [ebp-9Ch]
- .text:00453BD9 add ecx, 69Ch
- .text:00453BDF call ?SetWindowTextA@CWnd@@QAEXPBD@Z
- ; CWnd::SetWindowTextA(char const *)
Code (Assembler) : Убрать нумерацию
- .text:00453A90 push 1
- .text:00453A92 mov ecx, [ebp-9Ch]
- ; Вызвать функцию проверки
- .text:00453A98 call sub_452AB0
- ; Сохранить ее результат в переменную
- .text:00453A9D mov [ebp-94h], eax
- .text:00453AA3 mov ecx, [ebp-9Ch]
- .text:00453AA9 add ecx, 6F8h
Программа успешно "зарегистрирована"
Теперь в качестве регистрации Maze Creator принимает вообще любые данные, они все считаются правильными. Перевод часов на пару месяцев вперед-назад на работу программы также не влияет. Первая цель успешно достигнута. Надо ли напоминать, что выход в интернет для программы должен быть наглухо закрыт? Теперь переходим к косметическим исправлениям. Начнем с самого простого, это ссылка на сайт автора под каждым сгенерированным лабиринтом. По тексту строки выходим на следующую функцию:
Code (Assembler) : Убрать нумерацию
- .text:00431FA0 sub_431FA0 proc near
- .text:00431FA0 push ebp
- .text:00431FA1 mov ebp, esp
- .text:00431FA3 push 0FFFFFFFFh
- .text:00431FA5 push offset loc_53F364
- .text:00431FAA mov eax, large fs:0
- .text:00431FB0 push eax
- .text:00431FB1 sub esp, 44h
- .text:00431FB4 mov eax, dword_5C2E60
- .text:00431FB9 xor eax, ebp
- .text:00431FBB push eax
- .text:00431FBC lea eax, [ebp+var_C]
- .text:00431FBF mov large fs:0, eax
- .text:00431FC5 mov [ebp+var_50], ecx
- .text:00431FC8 push 4
- .text:00431FCA mov eax, [ebp+arg_0]
- .text:00431FCD push eax
- .text:00431FCE mov ecx, [ebp+var_50]
- .text:00431FD1 call sub_431C90
- .text:00431FD6 mov [ebp+var_10], eax
- .text:00431FD9 lea ecx, [ebp+var_3C]
- .text:00431FDC call _LocaleUpdate::GetLocaleT(void)
- .text:00431FE1 lea ecx, [ebp+var_48]
- .text:00431FE4 call _LocaleUpdate::GetLocaleT(void)
- .text:00431FE9 lea ecx, [ebp+var_24]
- .text:00431FEC call _LocaleUpdate::GetLocaleT(void)
- .text:00431FF1 mov ecx, [ebp+var_50]
- .text:00431FF4 call sub_43EB10
- .text:00431FF9 mov [ebp+var_1C], eax
- .text:00431FFC lea ecx, [ebp+var_18]
- .text:00431FFF call sub_407600
- .text:00432004 mov [ebp+var_4], 0
- .text:0043200B push offset aCourier ; "Courier"
- .text:00432010 push 30h ; char
- .text:00432012 push 0 ; char
- .text:00432014 push 0 ; char
- .text:00432016 push 0 ; char
- .text:00432018 push 0 ; char
- .text:0043201A push 0 ; char
- .text:0043201C push 0 ; char
- .text:0043201E push 0 ; char
- .text:00432020 push 190h ; cWeight
- .text:00432025 push 0 ; cOrientation
- .text:00432027 push 0 ; cEscapement
- .text:00432029 push 0 ; cWidth
- .text:0043202B mov ecx, [ebp+var_50]
- .text:0043202E mov eax, [ecx+15Ch]
- .text:00432034 cdq
- .text:00432035 sub eax, edx
- .text:00432037 sar eax, 1
- .text:00432039 push eax ; cHeight
- .text:0043203A lea ecx, [ebp+var_18]
- .text:0043203D call sub_43EB30
- .text:00432042 lea edx, [ebp+var_18]
- .text:00432045 push edx
- .text:00432046 mov eax, [ebp+arg_0]
- .text:00432049 mov edx, [eax]
- .text:0043204B mov ecx, [ebp+arg_0]
- .text:0043204E mov eax, [edx+28h]
- .text:00432051 call eax
- .text:00432053 mov [ebp+var_40], eax
- .text:00432056 mov ecx, [ebp+var_1C]
- .text:00432059 mov edx, [ecx+0C8h]
- .text:0043205F neg edx
- .text:00432061 mov eax, [ebp+var_50]
- .text:00432064 add edx, [eax+15Ch]
- .text:0043206A mov [ebp+var_30], edx
- .text:0043206D mov ecx, [ebp+var_1C]
- .text:00432070 mov edx, [ecx+0C8h]
- .text:00432076 neg edx
- .text:00432078 mov [ebp+var_28], edx
- .text:0043207B mov [ebp+var_34], 0
- .text:00432082 mov eax, [ebp+var_50]
- .text:00432085 mov ecx, [eax+180h]
- .text:0043208B mov [ebp+var_2C], ecx
- .text:0043208E push offset aWww_mazecreato
- ; "WWW.MAZECREATOR.COM"
- .text:00432093 lea ecx, [ebp+var_4C]
- .text:00432096 call sub_4051A0
- .text:0043209B mov byte ptr [ebp+var_4], 1
- .text:0043209F push 101h
- .text:004320A4 lea edx, [ebp+var_34]
- .text:004320A7 push edx
- .text:004320A8 lea eax, [ebp+var_4C]
- .text:004320AB push eax
- .text:004320AC mov ecx, [ebp+arg_0]
- .text:004320AF call sub_407C40
- .text:004320B4 mov byte ptr [ebp+var_4], 0
- .text:004320B8 lea ecx, [ebp+var_4C]
- .text:004320BB call sub_401870
- .text:004320C0 mov ecx, [ebp+var_40]
- .text:004320C3 push ecx
- .text:004320C4 mov edx, [ebp+arg_0]
- .text:004320C7 mov eax, [edx]
- .text:004320C9 mov ecx, [ebp+arg_0]
- .text:004320CC mov edx, [eax+28h]
- .text:004320CF call edx
- .text:004320D1 lea ecx, [ebp+var_18]
- .text:004320D4 call ?DeleteObject@CGdiObject@@QAEHXZ
- ; CGdiObject::DeleteObject(void)
- .text:004320D9 mov [ebp+var_4], 0FFFFFFFFh
- .text:004320E0 lea ecx, [ebp+var_18]
- .text:004320E3 call sub_407850
- .text:004320E8 mov eax, [ebp+var_10]
- .text:004320EB mov ecx, [ebp+var_C]
- .text:004320EE mov large fs:0, ecx
- .text:004320F5 pop ecx
- .text:004320F6 mov esp, ebp
- .text:004320F8 pop ebp
- .text:004320F9 retn 4
- .text:004320F9 sub_431FA0 endp
Картинка в ресурсах
Тут есть два варианта решения. Первый, самый простой, - это создать в любом графическом редакторе белый прямоугольник и заменить в редакторе ресурсов картинку с надписями на чистое изображение. Второй вариант связан с бинарной хирургией, ей и займемся. На скриншоте видно, что ресурс с картинкой имеет индекс 171 или 0ABh, если считать в шестнадцатеричной системе. Поищем это значение в листинге дизассемблера. Обнаружится вот такая приметная функция с очень характерными действиями:
Code (Assembler) : Убрать нумерацию
- .text:00431A00 sub_431A00 proc near
- .text:00431A00 push ebp
- .text:00431A01 mov ebp, esp
- .text:00431A03 push 0FFFFFFFFh
- .text:00431A05 push offset loc_53F32C
- .text:00431A0A mov eax, large fs:0
- .text:00431A10 push eax
- .text:00431A11 sub esp, 25Ch
- .text:00431A17 mov eax, dword_5C2E60
- .text:00431A1C xor eax, ebp
- .text:00431A1E mov [ebp+var_40], eax
- .text:00431A21 push eax
- .text:00431A22 lea eax, [ebp+var_C]
- .text:00431A25 mov large fs:0, eax
- .text:00431A2B mov [ebp+var_268], ecx
- .text:00431A31 push 0
- .text:00431A33 lea ecx, [ebp+var_234]
- .text:00431A39 call sub_459BF0
- .text:00431A3E mov [ebp+var_4], 0
- .text:00431A45 lea ecx, [ebp+var_24]
- .text:00431A48 call ??0CDC@@QAE@XZ ; CDC::CDC(void)
- .text:00431A4D mov byte ptr [ebp+var_4], 1
- .text:00431A51 lea ecx, [ebp+var_23C]
- .text:00431A57 call _LocaleUpdate::GetLocaleT(void)
- .text:00431A5C lea ecx, [ebp+var_38]
- .text:00431A5F call _LocaleUpdate::GetLocaleT(void)
- .text:00431A64 lea ecx, [ebp+var_14]
- .text:00431A67 call _LocaleUpdate::GetLocaleT(void)
- .text:00431A6C mov ecx, [ebp+var_268]
- .text:00431A72 call sub_43EB10
- .text:00431A77 mov [ebp+var_28], eax
- .text:00431A7A push 2 ; lpType
- ; Найти и загрузить ресурс с фоновой картинкой
- .text:00431A7C push 0ABh ; lpName
- .text:00431A81 push 0 ; hModule
- .text:00431A83 call ds:FindResourceA
- .text:00431A89 mov [ebp+hResInfo], eax
- .text:00431A8F push 0 ; hModule
- .text:00431A91 push 1 ; int
- .text:00431A93 mov eax, [ebp+hResInfo]
- .text:00431A99 push eax ; hResInfo
- .text:00431A9A lea ecx, [ebp+var_234]
- .text:00431AA0 call sub_459840
- .text:00431AA5 lea ecx, [ebp+var_234]
- .text:00431AAB call ?IsOpen@CDatabase@@QBEHXZ
- ; CDatabase::IsOpen(void)
- .text:00431AB0 movzx ecx, al
- .text:00431AB3 mov [ebp+var_3C], ecx
- .text:00431AB6 mov edx, [ebp+var_268]
- ...
- ...
- .text:00431C79 call sub_51BF7A
- .text:00431C7E mov esp, ebp
- .text:00431C80 pop ebp
- .text:00431C81 retn 4
- .text:00431C81 sub_431A00 endp
Просмотров: 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()
Псевдослучайные числа генерируются с помощью синуса.
------
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()
Добавить комментарий
Заполните форму для добавления комментария