Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
От патча до кейгена - Sanchs Marine Aquarium v0.99L Beta

Автор: Fess

Target: Sanchs Marine Aquarium v0.99L Beta

Tools:

  • Some brains
  • Soft-Ice 3.24
  • Win32Dasm 8.93
  • Любой hex+asm-редактор (я использую QView)

Пролог

Вступление:

Как-то около месяцев трех-четырех назад увидал я на softodrom'e хороший хранитель экрана в стиле "Эмуляция аквариума" и решил его себе закачать. Сказано сделано, скачал, поставил. Но по каким-то причинам он оказался шароварным. Дурацкий наг и возможность пользоваться одной рыбкой меня вдохновила на взлом. Наскоком взять не получилось, а со временем то- гда была напряженка сбацал патч и забыл. Но все возвращается, вот так и я от нечего делать решил вернуться и продолжить работу, как в следствии ок- азалось защита была плохой. Для начинающих крэкеров это в самый раз, и я предлагаю вашему вниманию 4 способа взлома этой программы.

Что за прога:

Один из самых лучших из видимых мной хранителей экрана, такой красоты и маленького размера (архив 1,1 Мб).

Примечание:

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

Вступление

Как я уже писал в прологе взлом будет производится четырьмя разными способами, это

  • Патч
  • Подсмотр кода
  • Написание кейгена на основе самой программы
  • Написание кейгена на Delphi

Патч

Патч это самый легкий способ взлома поэтому профессионалы и мастера в крэке считают его чем-то низким, я тоже стараюсь избегать использовать патч, но раз статья предназначена для начинающих, то не рассмотреть его это преступление. Но у легкости и быстроты патча есть и свои недостатки, по сравнению с серийным номером. Во-первых, это то, что он врядли будет работать с последующими версиями программы, во-вторых, сложно переносить патч, о... вот тут мне подсказывают, что для этого используют crk-файлы, согласен, но если программа запакована exe-паковщиком, то к этому файлу придется добавлять и распаковщик, а они подчас занимают достаточно много места.

Ну что ж приступим.

Программа ничем не запакована и написана на Visual C++. Поэтому сме- щение в файле равно смещению в памяти минус 400000h.

Первое, что нужно сделать это установить программу. Логично скажите Вы и будете правы. Установили? Теперь идем в Настройки Экрана, выбираем наш Screen Saver. И жмем кнопку Настройка. Там видим большое поле, где надо вводить наш код. Введем любой код и нажмем кнопку Enter. Код пропал, а ничего не произошло. Хм, странно. Почитаем текст вокруг. Написано, что можно написать TESTFISH, пишем, вводим и видим надпись: TEMP REGISTRATION OK. Работает. Скорее всего здесь и высветиться информация о правиль- ном номере. Что еще можно прочитать... Так написано, что нужно заплатить им 19,95 американских портретов за Deluxe регистрацию. Ладно, наплевать лучше сразу дизассемблировать, а там посмотрим. Копируем файл fish.scr из каталога Windows в свой каталог, у меня это MUSOR. Дизассемблируем. И ле- зем в директорию найденных в программе строк: StrRef и ищем там, какие- нибудь интересные строки, таковыми оказались:

"BASIC registration OK"
"DELUXE registration OK"
"TEMP registration OK"

Последнюю мы уже видели, а две другие нет. Судя по названиям Deluxe это продвинутая регистрация, а Basic основная. На Basic наплюем, хотя мы еще с ней встретимся в 2 и 3 пункте, а сделаем себя люксами. Два раза тыкаем на строку с Deluxe и оказываемя здесь Прим: все основные строки я выделю таким цветом.


:00411263 8B4D10                  mov ecx, dword ptr [ebp+10]
:00411266 81E1FFFF0000            and ecx, 0000FFFF
:0041126C 81F95A020000            cmp ecx, 0000025A
:00411272 0F85E1010000            jne 00411459
:00411278 833D7493420003          cmp dword ptr [00429374], 00000003
:0041127F 751B                    jne 0041129C

* Possible StringData Ref from Data Obj ->"DELUXE registration OK"
                                  |
:00411281 687C564200              push 0042567C
:00411286 6892000000              push 00000092
:0041128B 8B5508                  mov edx, dword ptr [ebp+08]
:0041128E 52                      push edx

* Reference To: USER32.SetDlgItemTextA, Ord:022Ch
                                  |
:0041128F FF154C024200            Call dword ptr [0042024C]

Так в выделенной строке число по адресу 429374 сравнимается с 3 и если не равно, то идет куда-то дальше, а если равно, то выдает эту строку. Зна- чит надо, чтобы в этой ячейке памяти всегда было 3. Вы можете не согла- ситься со мной, сказав: "Может просто заменить переход после этого сравне- ния и все." Это самая главная ошибка начинающих борьба не с причиной, а со следствием, такой способ может сработать, но редко. Хотя никто Вас не дер- жит попробуйте, может и получится.

Попробуем поискать фрагмент, где в эту ячейку записываются данные, это можно сделать с помощью Soft-Ice. Но зачем крэкеру геморой. Просто поищем строку mov dword ptr [00429374], 00000003. Глядишь, что и всплывет. Найде- но три адреса, вот текст около первого


:00404026 6A03                    push 00000003
:00404028 E8C3F0FFFF              call 004030F0
:0040402D 83C404                  add esp, 00000004
:00404030 85C0                    test eax, eax
:00404032 7434                    je 00404068
:00404034 C7057493420003000000    mov dword ptr [00429374], 00000003

Каждые три раза вызывается эта процедура и если в eax она возвратит не 0, то все хорошо и идет присвоение, если 0, то плохо. Можно, конечно, поменять все jump'ы после этих процедур. И это скорее всего поможет, но я предпочи- таю действовать более тонко, сделать, чтобы процедура всегда возвращала не 0. Можно, конечно, прямо после входа в процедуру поставить ret, ведь скорее всего eax<>0. Процентов 91,2%. Но лучше присвоить eax единицу и выйти. Да- вайте так и сделаем.

Открываем файл qview или hiew. Включаем 32 битный-hex&asm режим. Как это делается я в предыдущих тьюториалах писал. Переходим по адресу 30F0. И вписываем такие строки (после ";" приведена расшифровка строк)


xor eax,eax ;обнулить eax
inc eax     ;увеличить eax на 1
ret         ;выйти из процедуры

Или прямо в hex-режиме начиная с адреса 30F0 пишем 33С040С3 это и будут эти команды.

Теперь можете зайти в настройки и увидеть их совсем другими, а сверху долгожданную надпись Deluxe Version. И пользуйтесь ей до скончанья веков. Жалко, что это только бета, а в нормальной этот патч будет не дейтвителен. Хотя я думаю сломать ее будет так же легко, да и адреса врядли сильно по- меняются. Но уж лучше код, читайте дальше....

Подсмотр кода

Подсмотреть, подслушать это давнее изобретение человека из века в век на этом делали деньги. И мы сегодня заработаем ни много, ни мало 19.95$. Только, к сожалению, Вам их никто не отдаст, но зато программа за эту це- ну станет Вашей. Поехали.

Самая главная задача это найти, где введенный нами код сравнивается с настоящим, сгенереным по каким-то законам с какими-то условиями. В этой главе нам на них превать. Тут вы можете меня осудить, мол сволочь, "тут, наверное, будет вычисляться контрольная сумма, ведь имя-то не вводим.". Я себе позволю сразу Вам заметить это тот редкий случай, когда это не так. Не забудьте включить SOFT-ICE, он нам понадобится подсмотреть код.

Помните мы писали TESTFISH и получали ответ. Да. Тогда давайте посмо- трим откудова вызывается эта строка. Ведь она сравнивается с нашим вве- денным нами кодом. Жмем два раза на TESTFISH и оказываемся здесь. Я чтобы было по понятней понаставлю своих комментариев.


:00411315 6A20             push 00000020 <- считать 20h символов
:00411317 68A48E4200       push 00428EA4 <- сюда
:0041131C 6892000000       push 00000092 <- из нашего поля(т.е. пароль)
:00411321 8B5508           mov edx, dword ptr [ebp+08]
:00411324 52               push edx <- идентификатор окна

* Reference To: USER32.GetDlgItemTextA, Ord:0104h
                             |
:00411325 FF15E0014200     Call dword ptr [004201E0]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00411313(C)
|
* Possible StringData Ref from Data Obj ->"TESTFISH"
                                  |
:0041132B 6870564200              push 00425670   <- Адрес строки TESTFISH
:00411330 68A48E4200              push 00428EA4   <- Адрес нашего пароля

* Reference To: KERNEL32.lstrcmpiA, Ord:02FFh <- сравниваем строки
                                  |
:00411335 FF15A0004200            Call dword ptr [004200A0]
:0041133B 85C0                    test eax, eax
:0041133D 750A                    jne 00411349 <- если не равны то переход
:0041133F C7057493420001000000    mov dword ptr [00429374], 00000001

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041133D(C)
|
:00411349 6A02                    push 00000002
:0041134B E8A01DFFFF              call 004030F0 <-сравнение на Basic регистрацию
:00411350 83C404                  add esp, 00000004
:00411353 85C0                    test eax, eax
:00411355 7414                    je 0041136B <- если не равно, то переход
:00411357 C7057493420002000000    mov dword ptr [00429374], 00000002
:00411361 6A01                    push 00000001
:00411363 E8D825FFFF              call 00403940
:00411368 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00411355(C)
|
:0041136B 6A03                    push 00000003
:0041136D E87E1DFFFF              call 004030F0 <- сравнение на Deluxe
:00411372 83C404                  add esp, 00000004
:00411375 8945F8                  mov dword ptr [ebp-08], eax
:00411378 837DF800                cmp dword ptr [ebp-08], 00000000
:0041137C 7414                    je 00411392 <- если не равно, то переход
:0041137E C7057493420003000000    mov dword ptr [00429374], 00000003

Будем надеятся с коментариями все понятно. Как я угадал, где Basic, где Deluxe. Посмотрите на выделенные строки. Если не переходит адресу 429374 записывается значение. А о нем мы говорили, когда делали патч. Так же мы увидели, что наша введеная строка заносится в память по адресу 00428EA4. Кстати, Вы заметили, что процедура у Basic регистрации и Deluxe одна, и различаются только по значению кладущимуся в стэк 2 или 3. Заходим в эту процедуру и ищем, где наш введенный код сравнивается с истинным. "Истина, где-то рядом","как говорил один мой друг, ныне покой- ник". Сразу скажу программа написана на C++ и использует MFC, если, ко- нечно, это вам что-нибудь говорит. Ищем пока не доходим до такого места.


:0040327A 8D4DC8                  lea ecx, dword ptr [ebp-38]
:0040327D 51                      push ecx
:0040327E 68A48E4200              push 00428EA4

* Reference To: KERNEL32.lstrcmpiA, Ord:02FFh
                                  |
:00403283 FF15A0004200            Call dword ptr [004200A0]
:00403289 85C0                    test eax, eax
:0040328B 0F851A010000            jne 004033AB

Видно, что наш код сравнивается с чем-то. Теперь пора взятся за Soft- Ice. Заходим ставим бряк на GetDlgItemTextA строкой bpx GetDlgItemTextA. Из предыдущего фрагмента кода было видно, что именно эта функция исполь- зуется для чтения. Лезем в настройки и вводим такой код: 110022334455. Нажимаем Enter и вываливаемся в Soft-Ice нажимаем F11, чтобы вернуться в тело программы. Удаляем все бряки командой bc * и устанавливаем бряк на адрес 40327E команда bpx 40327E. Нажимаем F5. Но ничего не происходит программа до этого места не дошла. Тогда попробуем символьный код, такой FESSCOOL. Опять вводим и на сей раз вываливаемся, в Soft-Ice на нашем бряке. Даем команду d ecx, чтобы посмотреть, что будет по адресу ecx и видим следующее FESSCO760776. Жмем F5 и опять вываливаемся, опять d ecx и видим FESSCO966395. Рассуждаем логически, первое, программа использует первые 6 символов, введенного кода для генерации остальной части. Второе, эти первые 6 символов обязательно буквы, третье, первый код это скорее всего для Basic регистрации, а второй для Deluxe, поскольку процедура генерации одна.

Попробуем ввести - подходит. Это круто теперь Вы можете получить код для своего имени или его части. И это круто. Можете теперь рассказать всем как вы купили эту программу и получили код, заплатив 20$.

Но хорошего понемножку, и подсмотреть код просто, но что делать, ес- ли, кто-то не знает Soft-Ice можно дать ему свой код, но лучше другой. Каждый раз включать для этого Soft-Ice, ставить бряки и прочее. Неудобно лучше сделать кейген для начала на самой программе. Читайте дальше.

Написание кейгена на основесамой программы

Если в программе можно подсмотреть правильный номер, то написание кей- гена на основе самой программы элементарно просто. Уже в нескольких ма- нуалах я писал, как это сделать.

Мы уже нашли место, где правильный номер сравнивается с нашим. Оста- лось только вывести правильный номер на экран, для этого я обычно ис- пользую функцию MessageBoxA. Ищем любой код с этой функцией. Идем в секцию функций и два раза жмем на USER32.MessageBoxA. И попадаем в такое место.


:00403A46 685C534200              push 0042535C
:00403A4B 6A00                    push 00000000

* Reference To: USER32.MessageBoxA, Ord:01BEh
                                  |
:00403A4D FF1530024200            Call dword ptr [00420230]
:00403A53 33C0                    xor eax, eax

Посмотрите hex представление этой функции и перепишите на бумажку, оно нам понадобиться. Формат функции MessageBoxA такой


push тип текста (обычно 0)
push текст в заголовке
push текст в окне
push идентификатор окна (обычно 0)
call MessageBoxA

Еще раз внимательно посмотрите на предыдущий фрагмент кода, нам надо начиная с 40327D. Написать такие строки, через дефис я буду приводить их hex представление. Запомните адрес MessageBoxA уникален для каждой программы, поэтому я беру его hex представление из самой программы.


push 0          - 6A00
push ecx        - 51
push ecx        - 51
push 0          - 6A00
CallMessageBoxA - FF1530024200
jmp 4033AB      - E91D014000

Джамп после этого всего необходим, чтобы программа не посчитала себя зарегеной, а то как вводить код? Как вы понимаете вываливаться будет 2 раза. Первый Basic код, второй Deluxe-код.

Вот пожалуй и все. Перейдем теперь к написанию настоящего кейгена.

Написание кейгена на Delphi

Сегодня мы покажем класс. Soft-Ice можете отложить в сторонку. Будем писать кейген, ТОЛЬКО опираясь на код в Win32Dasm'e. У каждого внутри есть свой Soft-Ice надо только научиться им пользоваться. Заходим в про- цедуру генерации пароля 4030F0 и анализируем ее.


:004030F0 55             push ebp
:004030F1 8BEC           mov ebp, esp
:004030F3 83EC4C         sub esp, 0000004C
:004030F6 56             push esi
:004030F7 57             push edi
:004030F8 C745B800000000 mov [ebp-48], 00000000  }
:004030FF C745BC01000000 mov [ebp-44], 00000001  } Инициализация переменных
:00403106 C745D800000000 mov [ebp-28], 00000000  }
:0040310D C745C400000000 mov [ebp-3C], 00000000  }
       ;Помните push перед процедурой, так вот он в [ebp+8], а что он значил
       ;помните? Если 2, то это Basic, если 3 - Deluxe.
:00403114 837D0802       cmp dword ptr [ebp+08], 00000002 <-Basic
:00403118 7406           je 00403120
:0040311A 837D0801       cmp dword ptr [ebp+08], 00000001
:0040311E 7507           jne 00403127

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403118(C)
|
:00403120 C745D803000000 mov [ebp-28], 00000003

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040311E(C)
|
:00403127 837D0803       cmp dword ptr [ebp+08], 00000003 <-Наш Deluxe
:0040312B 7406           je 00403133  <-Переходим
:0040312D 837D0805       cmp dword ptr [ebp+08], 00000005
:00403131 7507           jne 0040313A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040312B(C)
|
:00403133 C745D807000000 mov [ebp-28], 00000007 <-Так значит в переменной
                                                  [ebp-28] теперь 7
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403131(C)
|
:0040313A 837D0804       cmp dword ptr [ebp+08], 00000004 <- Не равно
:0040313E 7507           jne 00403147         <- Переходим
:00403140 C745D804000000 mov [ebp-28], 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040313E(C)
|
:00403147 33C0           xor eax, eax                }
:00403149 8945C8         mov dword ptr [ebp-38], eax }
:0040314C 8945CC         mov dword ptr [ebp-34], eax } Обнуление переменных
:0040314F 8945D0         mov dword ptr [ebp-30], eax }
:00403152 668945D4       mov word ptr [ebp-2C], ax   }
:00403156 8B0DA48E4200   mov ecx, dword ptr [00428EA4] } Первые 6 введенных
:0040315C 894DC8         mov dword ptr [ebp-38], ecx   } символов переносят
:0040315F 668B15A88E4200 mov dx, word ptr [00428EA8]   } в память начиная с
:00403166 668955CC       mov word ptr [ebp-34], dx     } [ebp-38]
:0040316A C745C000000000 mov [ebp-40], 00000000
:00403171 EB09           jmp 0040317C

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004031A9(U), :004031C6(U)
|
:00403173 8B45C0         mov eax, dword ptr [ebp-40] } Добавление к счетчику
:00403176 83C001         add eax, 00000001           } цикла единицы
:00403179 8945C0         mov dword ptr [ebp-40], eax }

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403171(U)
|
:0040317C 837DC006       cmp dword ptr [ebp-40], 00000006 <- Проверка все ли
                                                           6 символов обработаны
:00403180 7D46           jge 004031C8
:00403182 8B4DC0         mov ecx, dword ptr [ebp-40]      <- В [ebp-40] счетчик цикла
:00403185 8A540DC8       mov dl, byte ptr [ebp+ecx-38]    <- Берем n-символ
:00403189 8855DC         mov byte ptr [ebp-24], dl        <- Записываем его сюда
:0040318C 0FBE45DC       movsx eax, byte ptr [ebp-24]     <- Опять его берем теперь в eax
:00403190 0345C0         add eax, dword ptr [ebp-40]      <- Добавляем к нему счетчик цикла
:00403193 0FAF45BC       imul eax, dword ptr [ebp-44]     <- Умножаем получившееся на общую сумму в [ebp-44]
:00403197 8945BC         mov dword ptr [ebp-44], eax      <- Записываем в общую сумму
:0040319A 837DC001       cmp dword ptr [ebp-40], 00000001 <- Если символ 1 или 2
:0040319E 7E0B           jle 004031AB                     <- то переходим
:004031A0 0FBE4DDC       movsx ecx, byte ptr [ebp-24]     <- Заносим символ в ecx
:004031A4 83F92D         cmp ecx, 0000002D                <- Сравниваем символ с символом '-'
:004031A7 7502           jne 004031AB                     <- если не равно
:004031A9 EBC8           jmp 00403173                     <- иначе

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040319E(C), :004031A7(C)
|
:004031AB 0FBE55DC       movsx edx, byte ptr [ebp-24]     <- Заносим символ в edx
:004031AF 83FA7A         cmp edx, 0000007A                <- Если код больше 'Z'
:004031B2 7F09           jg 004031BD                      <- переход на выход
:004031B4 0FBE45DC       movsx eax, byte ptr [ebp-24]     <- Заносим символ в eax
:004031B8 83F841         cmp eax, 00000041                <- Если код больше 'A'
:004031BB 7D09           jge 004031C6                     <- переход
                     ; Это и есть сравнение "только большие латинские буквы"

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004031B2(C)
|
:004031BD C745B801000000 mov [ebp-48], 00000001
:004031C4 EB02           jmp 004031C8                     <- Выход с позором

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004031BB(C)
|
:004031C6 EBAB           jmp 00403173    <- Новый виток цикла

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00403180(C), :004031C4(U)
|
:004031C8 837DB800       cmp dword ptr [ebp-48], 00000000
:004031CC 0F85D9010000   jne 004033AB    <- Не переходим
:004031D2 8B4DD8         mov ecx, dword ptr [ebp-28] <- Берем число зависящее
                                 ;от типа регистрации для Deluxe это 7, для
                                 ;Basic это 3
:004031D5 69C9C8000000   imul ecx, 000000C8 <- Умножаем его на C8
:004031DB 8B45BC         mov eax, dword ptr [ebp-44] <- Берем сумму из предыдущего цикла
:004031DE 33D2           xor edx, edx
:004031E0 F7F1           div ecx  <- Eax делим нацело на ecx результат в eax
:004031E2 8945BC         mov dword ptr [ebp-44], eax <- Записываем его в сумму

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004031F6(U)
|
:004031E5 817DBC301B0F00 cmp dword ptr [ebp-44], 000F1B30 <- Если сумма меньше F1B30
:004031EC 760A           jbe 004031F8                     <- переход
:004031EE 8B55BC         mov edx, dword ptr [ebp-44]      }
:004031F1 D1EA           shr edx, 1                       } Делим сумму на 2
:004031F3 8955BC         mov dword ptr [ebp-44], edx      }
:004031F6 EBED           jmp 004031E5                     <- Проверяем заново

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004031EC(C), :00403209(U)
|
:004031F8 817DBCA0860100 cmp dword ptr [ebp-44], 000186A0 <- если сумма больше 186A0
:004031FF 730A           jnb 0040320B                     <- переход
:00403201 8B45BC         mov eax, dword ptr [ebp-44]      }
:00403204 D1E0           shl eax, 1                       } Умножаем сумму на 2
:00403206 8945BC         mov dword ptr [ebp-44], eax      }
:00403209 EBED           jmp 004031F8                     <- Повторяем заново

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004031FF(C)
|
:0040320B 8B4DBC         mov ecx, dword ptr [ebp-44]   }
:0040320E 81C180000000   add ecx, 00000080             } Добавляем к сумме 80h
:00403214 894DBC         mov dword ptr [ebp-44], ecx   }
:00403217 8B55BC         mov edx, dword ptr [ebp-44]
:0040321A 52             push edx

* Possible StringData Ref from Data Obj ->"%d"
                          |
:0040321B 6808524200     push 00425208
:00403220 8D45CE         lea eax, dword ptr [ebp-32]
:00403223 50             push eax                  <- Адрес памяти куда будет записан перевод
:00403224 E8D31E0100     call 004150FC             <- Перевод числа в строку
:00403229 83C40C         add esp, 0000000C
:0040322C 8A4DCE         mov cl, byte ptr [ebp-32] <- Берем первое число
:0040322F 884DDC         mov byte ptr [ebp-24], cl <- Помещаем в [ebp-24]
:00403232 8A55D3         mov dl, byte ptr [ebp-2D] } Заменяем первое на
:00403235 8855CE         mov byte ptr [ebp-32], dl } последнее.
:00403238 8A45DC         mov al, byte ptr [ebp-24] } Заменяем последнее на число
:0040323B 8845D3         mov byte ptr [ebp-2D], al } из буфера, т.е. бывшее первое
:0040323E 0FBE4DCE       movsx ecx, byte ptr [ebp-32] <- Берем первое число в ecx
:00403242 83F930         cmp ecx, 00000030            <- Если число не равно '0'
:00403245 7504           jne 0040324B                 <- Переходим
:00403247 C645CE39       mov [ebp-32], 39             <- Иначе заменяем первое число на '9'

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403245(C)
|
:0040324B C645D400       mov [ebp-2C], 00 <- Закрываем строку
                Теперь по адресу [ebp-32] число прибавив которое к введенной
                строке получится истинный код.

Надеюсь все понятно из моих комментариев. Видите как просто, зачем здесь Soft-Ice. Я сляпал кейген на Delpi. Так как это быстро и просто. Да и Вас загружать не зачем. В нем я умышленно, чтобы не разрасталась статья не привожу проверку на заглавные буквы, т.к. программа воспринимает только заглавные. Если надо будет напишите сами это не сложно. Для создания кей- гена на основной форме нужно поместить два компонента Edit с именами Edit1 и Edit2 (они по умолчанию будут такими). И одну кнопку, имя любое. Затем жмете два раза на кнопку и вставляете этот фрагмент:


if Length(Edit1.Text) >= 6 then // Проверка на длинну
begin
  S := Edit1.Text;
  I := 1;
  Z := 7;
  // Тип регистрации Basic - 3 или Deluxe - 7
  for C := 1 to 6 do
    I := I * (Ord(S[C]) + C - 1);
  Z := Z * $C8;
  I := I div Z;
  while I > $F1B30 do
    I := I div 2;
  while I < $186A0 do
    I := I * 2;
  I := I + $80;
  S := IntToStr(I);
  C := Ord(S[Length(S)]);
  S[Length(S)] := S[1];
  if c = $30 then
    c := $39;
  S[1] := Chr(C);
  Edit2.Text := Edit1.Text + S;
end;

Разобраться с этими строками легко, я думаю вы справитесь, если что непонятно пишите. Адрес есть в начале и в конце.

Послесловие

Вот и закончена работа потирая руки вы регистрируете программу на себя. Винище льется рекой вы празднуете халявно заработанные 20$.

Хочу надеяться, что эта статья Вас чему-либо научила и помогла в осво- ении этой нелегкой науки.

Снять регистрацию можно, в разделе реестра: HKEY_CURRENT_USER\SOFTWARE\Serenescreen\SereneAquarium Удалив параметр Code.

Люди, если у Вас есть деньги и Вам понравилась эта программа ку- пите ее, поддержите разработчиков для выпуска новых версий. Тем более прога действительно хороша.

Крэкеры, крякеры и кракерята, сказать практически нечего разве, что только не ругайте сильно разработчиков за такую корявую защиту.

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

Все ругательства отправлять в null
Все остальное на lomovskih@yandex.ru

Спасибо за интерес к моему творчеству!

Удачи в Reversing Engeneering!

P.S. Запомните все материалы публикуются только в учебных целях и автор за их использование ответственности не несет!!

P.P.S. Возможно имеют место опечатки, заранее извините!

With best wishes Fess

И да пребудет с вами великий дух bad-сектора.

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay