Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Hasp защита в Базис Конструктор Мебельщик Demo
Два уровня защиты: High и... и нехай...

Это хоть и демо но в ней остался блок для работы с HASP. Естественно даже если мы тут сэмулируем Hasp - фичи не активируются, потому что их тут нет :) Но зато можно потренироваться в эмуляции HASP.

Взять это дело можно вот тут

Инструменты: Softice, Windasm, Hiew.

Сначала откроем BazMebel50.exe в windasm. Вызовы ключа тут отключены т.к. это демо, но нам для обучения нужно чтобы ключ таки вызывался. Как это сделать? Сначала найдем процедуру вызова HASP ключа. Искать ее очень просто, либо по вызову FreeEnvironmentStringsA либо по команде cmp bh, 32 (этой командой проверяется номер функции перед вызовом HASP ключа). Итак сделаем поиск строки "cmp bh, 32" и окажемся вот в таком месте:


:004C68D0 55 push ebp
:004C68D1 8BEC mov ebp, esp
:004C68D3 50 push eax
:004C68D4 53 push ebx
:004C68D5 51 push ecx
:004C68D6 52 push edx
:004C68D7 57 push edi
:004C68D8 56 push esi
:004C68D9 8B7514 mov esi, dword ptr [ebp+14]
:004C68DC 8B3E mov edi, dword ptr [esi]
:004C68DE BB00000000 mov ebx, 00000000
:004C68E3 8BD8 mov ebx, eax
:004C68E5 8AFB mov bh, bl
:004C68E7 B300 mov bl, 00
:004C68E9 03D9 add ebx, ecx
:004C68EB 8BC2 mov eax, edx
:004C68ED 8B4D1C mov ecx, dword ptr [ebp+1C]
:004C68F0 8B5518 mov edx, dword ptr [ebp+18]
:004C68F3 80FF32 cmp bh, 32 - проверяем чтобы номер функции был < 50
:004C68F6 7205 jb 004C68FD
:004C68F8 8B7508 mov esi, dword ptr [ebp+08]
:004C68FB 8B06 mov eax, dword ptr [esi]
:004C68FD 8B7510 mov esi, dword ptr [ebp+10]
:004C6900 8B36 mov esi, dword ptr [esi]
:004C6902 55 push ebp
:004C6903 E82E090000 call 004C7236 - Тут вызов HASP
:004C6908 5D pop ebp
:004C6909 8B7D14 mov edi, dword ptr [ebp+14]
:004C690C 8907 mov dword ptr [edi], eax - первое возвращаемое значение
:004C690E 8B7D10 mov edi, dword ptr [ebp+10]
:004C6911 891F mov dword ptr [edi], ebx - второе возвращаемое значение
:004C6913 8B7D0C mov edi, dword ptr [ebp+0C]
:004C6916 890F mov dword ptr [edi], ecx - третье возвращаемое значение
:004C6918 8B7D08 mov edi, dword ptr [ebp+08]
:004C691B 8917 mov dword ptr [edi], edx - четвертое возвращаемое значение
:004C691D 5E pop esi
:004C691E 5F pop edi
:004C691F 5A pop edx
:004C6920 59 pop ecx
:004C6921 5B pop ebx
:004C6922 58 pop eax
:004C6923 5D pop ebp
:004C6924 C21800 ret 0018

Это стандартная процедура вызова HASP ключа. Теперь надо сделать чтобы она таки вызывалась. Смотрим откуда вызывается эта процедура:


* Referenced by a CALL at Address:
:004B2C40
А там:
* Referenced by a CALL at Addresses:
|:004B2D48 , :004BF452 , :004BF4D9 , :004BF568 , :004BF5E2
|:004BF643 , :005846C8 , :00584703 , :00584781

ну глянем чо там к примеру по адресу 4B2D48:


:004B2D07 803D3D90650000 cmp byte ptr [0065903D], 00
:004B2D0E 753D jne 004B2D4D - тут перепрыгивает вызов HASP
.........

:004B2D43 B802000000 mov eax, 00000002
:004B2D48 E8C3FEFFFF call 004B2C10 - отсюда мы вышли

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B2D0E(C)

Вот, это уже хорошо. Теперь делаем запускаем прогу через symbol loader и bpm 0065903D. Оно сработает вот тут:


:004BE99B C6053C90650000 mov byte ptr [0065903C], 00
:004BE9A2 C6053D90650001 mov byte ptr [0065903D], 01 - Вот оно!
:004BE9A9 C605F468650001 mov byte ptr [006568F4], 01
:004BE9B0 C6054D7E650001 mov byte ptr [00657E4D], 01
:004BE9B7 C6054E7E650000 mov byte ptr [00657E4E], 00

Если сделать чтоб по адресу 0065903D записалось 0, то все вызовы HASP ключа оживут. Оживляем :)

Ставим bpx 4C6903(процедура вызова HASP) Теперь берем бумажку и записываем все вызовы и ихние параметры. Перед тем как записывать параметры, не плохо бы почитать вот тут описалово функций Hasp.

Будут вызваны 1, 5 и 3. Функции 1 и 5 и идут без параметров, а вот третьей передается di=0e. Больше вызовов естественно нету т.к. вызов хаспа не дал правильных результатов. Давайте ка глянем а чо ж ему надо чтоб он поверил что ключ присутствует. Вопервых функция 1 должна вернуть 1 в ax, потом после 5-й функции у нас тут проверяется только чтоб в ax не было 0. А вот с третьей функцией сложнее. Поставим bpm на все четыре возвращаемые значения. Bpm сработает тут:


:004BF576 8B55F4 mov edx, dword ptr [ebp-0C]
:004BF579 89500C mov dword ptr [eax+0C], edx
:004BF57C 817DF44D350000 cmp dword ptr [ebp-0C], 0000354D
:004BF583 7407 je 004BF58C

Хе-хе, третий возвращаемый параметр должен быть равен 354D. Т.е. в [ebp-0C] должно быть 4D 35 00 00 (354D). Правим память и смотрим дальше. Теперь, когда мы сэмулировали правильный ответ, прога будет пробовать снова обращаться к HASP.

Опять функция 3 с параметром di=10 Проверка возвращаемого значения тут:


:004BF5E7 817DF452350000 cmp dword ptr [ebp-0C], 00003552
:004BF5EE 750A jne 004BF5FA

И еще раз функция 3 с параметром di=11 Проверка возвращаемого значения тут:


:004BF648 817DF449350000 cmp dword ptr [ebp-0C], 00003549
:004BF64F 750A jne 004BF65B

Дальше идет вызов функции 2 с параметром ax=1B

Но тут чуть извратнее. Параметры копируются:


:004B2D4D A194846500 mov eax, dword ptr [00658494]
:004B2D52 8B80C4070000 mov eax, dword ptr [eax+000007C4]
:004B2D58 8B55F0 mov edx, dword ptr [ebp-10]
:004B2D5B 89500C mov dword ptr [eax+0C], edx - первый
:004B2D5E A194846500 mov eax, dword ptr [00658494]
:004B2D63 8B80C8070000 mov eax, dword ptr [eax+000007C8]
:004B2D69 8B55EC mov edx, dword ptr [ebp-14]
:004B2D6C 89500C mov dword ptr [eax+0C], edx - второй
:004B2D6F A194846500 mov eax, dword ptr [00658494]
:004B2D74 8B80CC070000 mov eax, dword ptr [eax+000007CC]
:004B2D7A 8B55E8 mov edx, dword ptr [ebp-18]
:004B2D7D 89500C mov dword ptr [eax+0C], edx - третий
:004B2D80 A194846500 mov eax, dword ptr [00658494]
:004B2D85 8B80D0070000 mov eax, dword ptr [eax+000007D0]
:004B2D8B 8B55E4 mov edx, dword ptr [ebp-1C]
:004B2D8E 89500C mov dword ptr [eax+0C], edx - четвертый

Ну естественно нужно ставить bpm на dword ptr [eax+0C]. Только вот один облом, они почему то не срабатывают :( А глюк такой вылазит вот тут:


:004B4552 803DF468650000 cmp byte ptr [006568F4], 00 - тут у нас 1
:004B4559 7416 je 004B4571 - тут нет прыжка
:004B455B C6053D90650001 mov byte ptr [0065903D], 01 - единица означает что hasp нету.

А как жеж в [006568F4] появляется единица? А очень просто! Поставив bpm 006568F4 мы увидим:


:004BE99B C6053C90650000 mov byte ptr [0065903C], 00
:004BE9A2 C6053D90650000 mov byte ptr [0065903D], 00 - это мы Hasp включили
:004BE9A9 C605F468650001 mov byte ptr [006568F4], 01 - Вот оно!
:004BE9B0 C6054D7E650001 mov byte ptr [00657E4D], 01
:004BE9B7 C6054E7E650000 mov byte ptr [00657E4E], 00

Упс :) Оказывается для активации ключа надо еще 1 байт поправить. Поправив вот это место возвращаемся к нашим брейкпоинтам, которые мы ставили чтобы понять куда уходят значения после функции 2 с параметром ax=1B. Теперь они таки сработают. Вот тут:


:004B459B A194846500 mov eax, dword ptr [00658494]
:004B45A0 8B80C4070000 mov eax, dword ptr [eax+000007C4]
:004B45A6 81780C76F00000 cmp dword ptr [eax+0C], 0000F076 - правильное значение 1
:004B45AD 753C jne 004B45EB
:004B45AF A194846500 mov eax, dword ptr [00658494]
:004B45B4 8B80C8070000 mov eax, dword ptr [eax+000007C8]
:004B45BA 81780C77DF0000 cmp dword ptr [eax+0C], 0000DF77 - правильное значение 2
:004B45C1 7528 jne 004B45EB
:004B45C3 A194846500 mov eax, dword ptr [00658494]
:004B45C8 8B80CC070000 mov eax, dword ptr [eax+000007CC]
:004B45CE 81780CFFC50000 cmp dword ptr [eax+0C], 0000C5FF - правильное значение 3
:004B45D5 7514 jne 004B45EB
:004B45D7 A194846500 mov eax, dword ptr [00658494]
:004B45DC 8B80D0070000 mov eax, dword ptr [eax+000007D0]
:004B45E2 81780CADEA0000 cmp dword ptr [eax+0C], 0000EAAD - правильное значение 4
:004B45E9 7404 je 004B45EF

Вот они все 4 параметра которые нужно вернуть. Правим их в памяти. Вооот ... и прога запускается без надписей "Demo". Активируется кнопка сохранить на панели инструментов и в About уже горит что полная. Но если зайти в меню "файл" или пощелкать по вкладкам выбора примитвовов то происходит еще 1 вызов функции 2 на этот раз с параметром ax=25. Опять ставим брейкпоинты и видим что проверка происходит тут:


:004B4654 A194846500 mov eax, dword ptr [00658494]
:004B4659 8B80C4070000 mov eax, dword ptr [eax+000007C4]
:004B465F 81780C1ACC0000 cmp dword ptr [eax+0C], 0000CC1A
:004B4666 753C jne 004B46A4
:004B4668 A194846500 mov eax, dword ptr [00658494]
:004B466D 8B80C8070000 mov eax, dword ptr [eax+000007C8]
:004B4673 81780C8EF10000 cmp dword ptr [eax+0C], 0000F18E
:004B467A 7528 jne 004B46A4
:004B467C A194846500 mov eax, dword ptr [00658494]
:004B4681 8B80CC070000 mov eax, dword ptr [eax+000007CC]
:004B4687 81780C6AA30000 cmp dword ptr [eax+0C], 0000A36A
:004B468E 7514 jne 004B46A4
:004B4690 A194846500 mov eax, dword ptr [00658494]
:004B4695 8B80D0070000 mov eax, dword ptr [eax+000007D0]
:004B469B 81780CFBD30000 cmp dword ptr [eax+0C], 0000D3FB
:004B46A2 7404 je 004B46A8

Ну вроде все. Можно писать эмулятор. Данные есть. Т.е. надо написать программу которая обрабатывает 3 регистра и возвращает правильные цифры в регистры ax, bx, cx и dx

Т.е. будет чо-то типа


cmp bh,1 - вызвали функцию 1?
jnz дальше
mov ax,1
jmp выход

дальше:
cmp bh,2 - вызвали функцию 2?
jnz еще_дальше
cmp ax, 1b
jnz не1b
mov ax,F076
mov bx,DF77
mov cx,C5FF
mov dx,EAAD
jmp выход

не1b:
cmp ax, 25
jnz выход
mov ax,CC1A
mov bx,F18E
mov cx,A36A
mov dx,D3FB
jmp выход

еще_дальше:
cmp bh,3 - вызвали функцию 3?
jnz даль_голубая
cmp di, 0e
jnz не_0е
mov cx,354d
jmp выход

не_0е:
cmp di, 10
jnz не_10
mov cx,3552
jmp выход

не_10:
cmp di, 11
jnz выход
mov cx,3549
jmp выход

даль_голубая:
cmp bh,5 - вызвали функцию 5?
jnz выход
mov ax,1

выход:
ret

И вот такую процедурку мы подсовываем вместо вызова HASP ключа. Это называется громким словом "Эмулятор" :)

Эх, жалко что демка :( Но я не думаю что в полноценной версии защита сильно отличается :)

P.S. Напоминаю! Это тока демка т.е. в ней нет кусков кода для сохранения и т.д. поэтому после эмуляции будет тока свтетится что она полноценная. Я эту прогу брал чисто для примера, чтоб показать процесс эмуляции.

Проект Delphi World © Выпуск 2002 - 2024
Автор проекта: USU Software
Вы можете выкупить этот проект.