Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Кейген для AxySnake v1.15.

Обсудить статью на форуме

Очень удобно, когда все крэкерские инструменты, книги и статьи в одном месте. Используйте сборник от EXELAB - вот тут.

Автор: Fess Дата: 07.10.2002 Тьютор: 23


-+-+-+-+-+-+-+-+-+-+ For education uses only +-+-+-+-+-+-+-+-+-+-
 Target: AxySnake v1.15
 
 Tools:    Some brains
           Soft-Ice/TRW2000
           Win32Dasm 8.93
           RegMon 4.13
           Masm32 (Masm 7.0)
 
           Все, кроме мозгов, можно найти на www.exetools.com
 

Вступление

Как это начиналось:

Принесли мне тут гамилу AxySnake v1.15 с кейгеном группы Desperate. Эта игрушка мне напомнила известную мне игрушку AirXonix. Как позже оказалось это было верным - игрушки одной фирмы. Я припомнил давешний взлом со множеством подлянок. И мне захотелось проверить надежность кейгена, как оказалось я правильно сомневался. Работать, он работает, но после нескольких этапов пишет, что код не особенно верный. И я решился поломать сию прогу.

Что за прога:

Очень даже неплохая игрушка 3D ремейк классической игры Червяк или Питон. Долго в нее не заиграешься, а вот расслабиться может помочь. В архиве примерно 7 Мбайт. Системные требования:

  • 3D Graphics card 
  • DirectX 7.0 or higher 
  • Windows 95/98/ME/2000/XP 
  • Processor 200 MHz or higher (>300 MHz - recommended) 
  • 32 MB RAM 
  • 15 MB free disk space
  • Sound card - optional

Начало

Чтобы было хоть какое-то разнообразие, я решил сегодня писать кейген на асме. Сразу хочется выразить особую благодарность Dr.Golova за предоставленный отличный пример. На основе которого я и написал свой кейген.

Предудущая игра не была запакована и была написана на MS Visual C++ 6.0. Не стала исключением и эта. Хочется только поблагодарить авторов за такой простор для работы.

Заглянув в каталог программы, я обнаружил пару dll-лок и 3 exe-шника. Немного поднапряг соображалку, воспользовался просмотрщиком ресурсов и я понял, что

  • AxySnake.exe - Настоящий запускаемый файл программы
  • Rekl.exe - Это фигня выдающая рекламу после выхода из игры (в незарегеной версии)
  • AxySnake.exe - Непонятный файл запускающий основную программу, покопавшись в листинге Win32Dasm'а я догнал, что он проверяет версию DirextX, командную строку и т.п.
  • proskin.dll - Из названия становится ясно, что это Prosto Skin в ресурсах содержатся картинки, и по размеру файла становится ясно, что это почти все, что там есть.
  • proton.dll - И наконец оно, в ресурсах находятся регистрационные диалоги, а где диалоги, почти всегда находятся функции отвечающие за их выполнение. Короче, беремся за него.

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

 ?bRegistered@@3HA
 ?DeleteRegistration@@YAXXZ
 ?GetRegCode@@YAPADXZ
 ?GetRegName@@YAPADXZ
 

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

Жмем два раза на Deluxe и попадаем сюда.

 Name:  REG_FAULT, # of Controls=004, Caption:"AxySnake Registration", ClassName:""
      001 - ControlID:0001, Control Class:"BUTTON" Control Text:"Try again"
      002 - ControlID:0002, Control Class:"BUTTON" Control Text:"Cancel"
      003 - ControlID:FFFF, Control Class:"STATIC" Control Text:"E R R O R !"
      004 - ControlID:FFFF, Control Class:"STATIC" Control Text:"Registration name or registration code is incorrect."
 Name:     REG_OK, # of Controls=003, Caption:"AxySnake Registration", ClassName:""
      001 - ControlID:0001, Control Class:"BUTTON" Control Text:"OK"
      002 - ControlID:FFFF, Control Class:"STATIC" Control Text:"REGISTRATION IS SUCCESSFULLY COMPLETED! "
      003 - ControlID:FFFF, Control Class:"STATIC" Control Text:"Thank you for registering !"
 

Два эти диалога показались мне переспективными. Идем в "Поиск" вписываем строку REG_OK. Нажимаем Enter и, о боже, она нашлась!!!!!!

 :1000FA54 E8570E0000 call 100108B0 <- Процедура проверки кода
 :1000FA59 85C0       test eax, eax
 :1000FA5B 7541       jne 1000FA9E
 :1000FA5D 50         push eax
 
 * Reference To: USER32.MessageBeep, Ord:01BDh
                                   |
 :1000FA5E FF15D4610210 Call dword ptr [100261D4]
 (удалено лишнее)
 :1000FA71 56           push esi
 
 * Possible StringData Ref from Data Obj ->"REG_FAULT" <- Вроде неправильный код
                                   |
 :1000FA72 6840CB0210   push 1002CB40
 (лишнее вырезано)
 :1000FA8E 56           push esi
 
 * Possible StringData Ref from Data Obj ->"REG_DIALOG"
                                   |
 :1000FA8F 684CCB0210   push 1002CB4C
 (мусор убран)
 :1000FA9C EB4D         jmp 1000FAEB
 
 * Referenced by a (U)nconditional or (C)onditional Jump at Address:
 |:1000FA5B(C)
 |
 :1000FA9E E86D6BFFFF   call 10006610
 (мусор выкинут)
 :1000FAC1 6860DF0010   push 1000DF60
 :1000FAC6 56           push esi
 
 * Possible StringData Ref from Data Obj ->"REG_OK"  <- Вроде правильный код
                                   |
 :1000FAC7 6838CB0210   push 1002CB38
 

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

Заходим в процедуру и пытаемся разобраться в хитросплетениях магических команд называемых языком ассемблера. Благо здесь нет ничего особо сложного, я в смысле, что здесь не применяется никаких команд сопроцессора и т.п. гадости. На этом этапе Вам без сомнения придется пользоваться отладчиком. Надеюсь, Вы знаете как. Если нет, то попробуйте сначала почитать тьюториал полегче. Короче ставим бряк на точку входа в процедуру, т.е. на 100108B0 (bpx 100108B0). Для наглядности я буду пояснять, что тут и куда (Запомните все числа даны в 16 системе счисления)

 :100108B0 A198A40310     mov eax, dword ptr [1003A498] <- Проверка длинны имени на 0
 :100108B5 85C0           test eax, eax
 :100108B7 0F84E1000000   je 1001099E
 :100108BD 8B0D9CA40310   mov ecx, dword ptr [1003A49C] <- Проверка длинны кода на 0
 :100108C3 85C9           test ecx, ecx
 :100108C5 0F84D3000000   je 1001099E
 :100108CB 6818F91210     push 1012F918  <- Передает в процедуру адрес буфера
 :100108D0 6838A40310     push 1003A438  <- Передаем в процедуру адрес имени
 :100108D5 C68038A4031000 mov byte ptr [eax+1003A438], 00 <- В конце имени пишем байт 0
 :100108DC E84FFFFFFF     call 10010830
 {Здесь вставлена вышеназванная процедура (чтобы не лазить)}
   :10010830 55       push ebp   <- Сохраняем ebp
   :10010831 8B6C2408 mov ebp, dword ptr [esp+08] <- Берем в ebp адрес имени
   :10010835 8BCD     mov ecx, ebp  <- ecx = ebp
   :10010837 8A4500   mov al, byte ptr [ebp+00] <- Берем 1 символ
   :1001083A 84C0     test al, al    <- Проверяем на 0
   :1001083C 7410     je 1001084E    <- Если да, то переход
   :1001083E 3C20     cmp al, 20     <- Сравниваем его с пробелом
   :10010840 7404     je 10010846    <- Если да, то переход
   :10010842 A880     test al, 80    <- Проверяем 8 бит
   :10010844 740C     je 10010852    <- Если установлен, то переход
   :10010846 8A4101   mov al, byte ptr [ecx+01]  <- Берем ecx+1 символ имени
   :10010849 41       inc ecx        <- Увеличиваем адрес имени
   :1001084A 84C0     test al, al    <- Сравниваем код символа с кодом 0
   :1001084C 75F0     jne 1001083E   <- Если нет, то повторяем
   :1001084E 33C0     xor eax, eax   <- Очищаем eax
   :10010850 5D       pop ebp        <- Возвращаем ebp
   :10010851 C3       ret            <- Выходим из процедуры
 
   :10010852 53       push ebx       < \
   :10010853 56       push esi       <- Сохраняем регистры
   :10010854 57       push edi       < /
   :10010855 8B7C2418 mov edi, dword ptr [esp+18] <- Берем
   :10010859 8BCF     mov ecx, edi <- ecx=edi
   :1001085B 33C0     xor eax, eax <- eax=0
   :1001085D 33F6     xor esi, esi <- esi=0
   :1001085F 8BD5     mov edx, ebp <- edx=ebp
   :10010861 8901     mov dword ptr [ecx], eax <- Заносим 0
   :10010863 33DB     xor ebx, ebx <- ebx=0
   :10010865 894104   mov dword ptr [ecx+04], eax < \
   :10010868 894108   mov dword ptr [ecx+08], eax <- Обнуляем
   :1001086B 89410C   mov dword ptr [ecx+0C], eax < /
   :1001086E 8BC7     mov eax, edi    <- eax=edi (Адрес буфера суммы)
   :10010870 803A00   cmp byte ptr [edx], 00 <- Сравниваем символ имени по
                                                адресу edx с 0
   :10010873 7503     jne 10010878           <- Если не равно, то
   :10010875 40       inc eax                <- Увеличиваем адрес eax
   :10010876 8BD5     mov edx, ebp           <- edx=ebp (Устанавливаем на начало имени)
   :10010878 8A0A     mov cl, byte ptr [edx] <- Берем символ имени по адресу edx
   :1001087A 80F920   cmp cl, 20             <- Сравниваем его с пробелом
   :1001087D 7414     je 10010893            <- Если да, то переход
   :1001087F F6C180   test cl, 80            <- Сравниваем 8 бит
   :10010882 750F     jne 10010893           <- Если он 1, то переход
   :10010884 0008     add byte ptr [eax], cl <- Прибавляем к байту по адресу eax
                                                символ из cl
   :10010886 40       inc eax                <- Увеличиваем адрес eax
   :10010887 46       inc esi                <- Увеличиваем счетчик
   :10010888 83FE10   cmp esi, 00000010      <- Сравниваем счетчик с 10h
   :1001088B 7507     jne 10010894           <- Если не равен, то переход
   :1001088D 33F6     xor esi, esi           <- Обнуляем счетчик
   :1001088F 8BC7     mov eax, edi           <- eax=edi (Устан. на начало буфера)
   :10010891 EB01     jmp 10010894           <- Переход
   :10010893 4B       dec ebx                <- Уменьшаем ebx на 1
   :10010894 42       inc edx                <- Увеличиваем указатель имени на 1
   :10010895 43       inc ebx                <- Увеличиваем счетчик ebpx на 1
   :10010896 83FB6F   cmp ebx, 0000006F      <- Продолжаем все это, пока ebx<6Fh
   :10010899 7CD5     jl 10010870            <- Если меньше, то повторить
   :1001089B 5F       pop edi                < \
   :1001089C 5E       pop esi                <- Возвращаем значения
   :1001089D 5B       pop ebx                < /
   :1001089E B801000000 mov eax, 00000001      <- eax=1
   :100108A3 5D       pop ebp                <- Возвращаем ebp
   :100108A4 C3       ret                    <- Выходим из процедуры
 { Общий смысл: В буфер по адресу 1012F918 генерируется суммарное представление имени}
 {Для краткости, я буду называть ее суммой имени }
 {Заканчивается вставленная процедура}
 :100108E1 83C408         add esp, 00000008  <- Выравниваем стек
 :100108E4 85C0           test eax, eax      <- Проверяем eax
 :100108E6 0F84B2000000   je 1001099E        <- Если он 0, то переход
 :100108EC 6878A40310     push 1003A478      <- Ложим в стек адрес введенного кода
 :100108F1 E8EAFEFFFF     call 100107E0
 {Здесь вставлена вышеназванная процедура (чтобы не лазить)}
   :100107E0 8B4C2404 mov ecx, dword ptr [esp+04]
   :100107E4 56       push esi
   :100107E5 33F6     xor esi, esi
   :100107E7 803900   cmp byte ptr [ecx], 00 <- Если код символа пароля равен 0,
   :100107EA 742A     je 10010816            <- то переход
   :100107EC 53       push ebx               <- Сохраняем ebx
   :100107ED 33C0     xor eax, eax           <- Обнуление счетчика
   :100107EF 8A90B0CB0210 mov dl, byte ptr [eax+1002CBB0] <- Строка "23456..."
   :100107F5 8A19     mov bl, byte ptr [ecx] <- Берем символ пароля
   :100107F7 3AD3     cmp dl, bl             <- Сравниваем
   :100107F9 7507     jne 10010802           <- Если не равно переход
   :100107FB 8886F8F81210 mov byte ptr [esi+1012F8F8], al <- Записываем состояние счетчика
   :10010801 46       inc esi                <- esi = esi+1 (тоже счетчик)
   :10010802 40       inc eax                <- Увелич. счетчик
   :10010803 83F820   cmp eax, 00000020      <- Если вся строка закончилась, то
   :10010806 7CE7     jl 100107EF
   :10010808 8A4101   mov al, byte ptr [ecx+01] <- Берем код символа пароля +1
   :1001080B 41       inc ecx             <- Увелич. адрес введенного пароля
   :1001080C 84C0     test al, al         <- Проверка на окончание
   :1001080E 75DD     jne 100107ED        <- Если нет, то повторяем
   :10010810 83FE14   cmp esi, 00000014   <- Если было 14h совпадений, то все путем
   :10010813 5B       pop ebx             <- Восстанавливаем ebx
   :10010814 7404     je 1001081A         <- Если все было путем, то переход
   :10010816 33C0     xor eax, eax        <- eax=0 (Типа очень плохо)
   :10010818 5E       pop esi
   :10010819 C3       ret                 <- Выход из процедуры
   :1001081A B801000000 mov eax, 00000001 <- eax=1 (Типа хорошо)
   :1001081F 5E       pop esi
   :10010820 C3       ret                 <- Выход из процедуры
 {Общий смысл процедуры: Переконвертировка пароля в строку байтов, заданную}
 {счетчиком элемента в строке символов 23456789ABCDEFGHJKLMNPQRSTUVWXYZ }
 {Для краткости созданную строку я буду называть индексами пароля}
 {Заканчивается вставленная процедура}
 :100108F6 83C404         add esp, 00000004
 :100108F9 85C0           test eax, eax     <- Проверка на правильность
 :100108FB 0F849D000000   je 1001099E       <- Если да, то переход
 {Далее идет проверка правильности кода}
 :10010901 B949000000     mov ecx, 00000049 <- ecx= 49
 :10010906 33C0           xor eax, eax      <- eax=0
 :10010908 0FBE9018F91210 movsx edx, byte ptr [eax+1012F918] <- Берем символ из суммы имени
 :1001090F 03CA           add ecx, edx      <- ecx = ecx+edx
 :10010911 40             inc eax           <- Увеличиваем счетчик на 1
 :10010912 83F810         cmp eax, 00000010 <- Сравниваем счетчик с 10h
 :10010915 7CF1           jl 10010908       <- Если меньше, то переход (повтор цикла)
 :10010917 33C0           xor eax, eax      <- eax = 0 (Обнуляем счетчик)
 :10010919 0FBE90F8F81210 movsx edx, byte ptr [eax+1012F8F8] <- Берем символ индекса пароля
 :10010920 0FBE92B0CB0210 movsx edx, byte ptr [edx+1002CBB0] <- По индексу берем символ из строки
 :10010927 03CA           add ecx, edx      <- ecx = ecx+edx
 :10010929 40             inc eax           <- Увеличиваем счетчик на 1
 :1001092A 83F811         cmp eax, 00000011 <- Сравниваем счетчик с 11h
 :1001092D 7CEA           jl 10010919       <- Пока меньше, повторяем цикл
 :1001092F A009F91210     mov al, byte ptr [1012F909] <- Берем 18 символ из индекса пароля
 :10010934 83E11F         and ecx, 0000001F <- ecx = ecx and 1Fh
 :10010937 3AC1           cmp al, cl        <- Сравниваем
 :10010939 7563           jne 1001099E      <- Если не равно, то очень плохо
   { Понятно дело, что эти числа должны быть равны, иначе ничего не выйдет   }
   { Дальше идут аналогичные циклы для 19 и 20 индекса пароля, разобраться в }
   { которых не составит труда                                               }
 :1001093B B932000000     mov ecx, 00000032
 :10010940 33C0           xor eax, eax
 :10010942 0FBE9018F91210 movsx edx, byte ptr [eax+1012F918]
 :10010949 2BCA           sub ecx, edx
 :1001094B 40             inc eax
 :1001094C 83F810         cmp eax, 00000010
 :1001094F 7CF1           jl 10010942
 :10010951 33C0           xor eax, eax
 :10010953 0FBE90F8F81210 movsx edx, byte ptr [eax+1012F8F8]
 :1001095A 0FBE92B0CB0210 movsx edx, byte ptr [edx+1002CBB0]
 :10010961 03CA           add ecx, edx
 :10010963 40             inc eax
 :10010964 83F812         cmp eax, 00000012
 :10010967 7CEA           jl 10010953
 :10010969 A00AF91210     mov al, byte ptr [1012F90A]
 :1001096E 83E11F         and ecx, 0000001F
 :10010971 3AC1           cmp al, cl  <- Сравнение 19 символа
 :10010973 7529           jne 1001099E
 
 :10010975 B979000000     mov ecx, 00000079
 :1001097A 33C0           xor eax, eax
 :1001097C 0FBE90F8F81210 movsx edx, byte ptr [eax+1012F8F8]
 :10010983 0FBE92B0CB0210 movsx edx, byte ptr [edx+1002CBB0]
 :1001098A 2BCA           sub ecx, edx
 :1001098C 40             inc eax
 :1001098D 83F813         cmp eax, 00000013
 :10010990 7CEA           jl 1001097C
 :10010992 A00BF91210     mov al, byte ptr [1012F90B]
 :10010997 83E11F         and ecx, 0000001F
 :1001099A 3AC1           cmp al, cl  <- Сравнение 20 символа
 :1001099C 7416           je 100109B4
 
 :1001099E 57             push edi          {Это выполняется, если неправильный код}
 :1001099F B91A000000     mov ecx, 0000001A
 :100109A4 33C0           xor eax, eax
 :100109A6 BF38A40310     mov edi, 1003A438
 :100109AB F3             repz
 :100109AC AB             stosd
 :100109AD A338F91210     mov dword ptr [1012F938], eax
 :100109B2 5F             pop edi
 :100109B3 C3             ret
 
 :100109B4 B801000000     mov eax, 00000001   <- Записываем 1, что все правильно
 :100109B9 A338F91210     mov dword ptr [1012F938], eax  <- Переменная правильности тоже 1
 :100109BE C3             ret    <- Выход из процедуры
 

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

Тут уже поднаторевший в этом деле читатель, может сказать, что это все элементарно. Надо просто посмотреть откедова вызывается нехорошая строка. Так и сделаем :) Запускаем Win32Dasm и дизассемблируем основной exe-файл. В секции строк мы видим искомую нами строку. Нажимаем два раза и мы тут.

 * Referenced by a CALL at Address:
 |:0041245E
 |
 :00416D60 83EC10                  sub esp, 00000010
 (Всякой мусор)
 :00416D7E 6A28                    push 00000028
 
 * Possible StringData Ref from Data Obj ->"      LICENSE AGREEMENT VIOLATION "
                                         ->"!     "
                                   |
 :00416D80 68847F4200              push 00427F84
 :00416D85 FFD6                    call esi
 :00416D87 6A03                    push 00000003
 

Как видно, ничего интересного нет, поэтому идем в вызывающую процедуру по адресу 41245E.

 :00412396 FF1500514200 Call dword ptr [00425100]
 
 * Reference To: proton.?bRegistered@@3HA, Ord:0064h
                                  |
 :0041239C 8B1524524200 mov edx, dword ptr [00425224]<- Проверяем правильность в proton.dll
 :004123A2 83C408       add esp, 00000008
 :004123A5 391A         cmp dword ptr [edx], ebx <- Сравниваем полученное значение с 0
 :004123A7 745D         je 00412406              <- Если не все путем, то переходим
 :004123A9 56           push esi
 :004123AA 57           push edi
 
 * Reference To: proton.?GetRegName@@YAPADXZ, Ord:0023h <- Получаем сумму имени
                              |
 :004123AB FF15FC504200 Call dword ptr [004250FC]
 :004123B1 B908000000   mov ecx, 00000008
 :004123B6 8BF0         mov esi, eax
 :004123B8 BF246D4700   mov edi, 00476D24   <- Сумма имени теперь по этому адресу
 :004123BD F3           repz
 :004123BE A5           movsd
 
 * Reference To: proton.?GetRegCode@@YAPADXZ, Ord:0022h  <- Получаем индексный пароль
                               |
 :004123BF FF15F8504200 Call dword ptr [004250F8]
 :004123C5 B908000000   mov ecx, 00000008
 :004123CA 8BF0         mov esi, eax
 :004123CC BF4C6D4700   mov edi, 00476D4C     <- Теперь он по адресу
 :004123D1 33C0         xor eax, eax
 :004123D3 F3           repz
 :004123D4 A5           movsd
 :004123D5 5F           pop edi
 :004123D6 891D486D4700 mov dword ptr [00476D48], ebx
 {Кстати, вот на этих стандарных адресах они и попались}
 {А вот и первый подлячек}
 :004123DC B94D000000   mov ecx, 0000004D  <- ecx = 4Dh
 :004123E1 5E           pop esi            <- Возвращаем esi
 :004123E2 0FBE90246D4700 movsx edx, byte ptr [eax+00476D24]  <- Берем символ суммы имени
 :004123E9 40          inc eax             <- Увеличиваем счетчик на 1
 :004123EA 83F810      cmp eax, 00000010   <- Сравниваем счетчик с 10
 :004123ED 8D0C51      lea ecx, dword ptr [ecx+2*edx] <- ecx = ecx+2*edx
 :004123F0 7CF0        jl 004123E2         <- Пока счетчик меньше 10, повторяем цикл
 :004123F2 A04C6D4700  mov al, byte ptr [00476D4C] <- Берем 1 символ индексного кода
 :004123F7 83E11F      and ecx, 0000001F           <- ecx = ecx and 1Fh
 :004123FA 3AC1        cmp al, cl                  <- Сравниваем полученное с 1 символом
 :004123FC 7408        je 00412406                 <- Если все рулез, то переход
 :004123FE 892D486D4700 mov dword ptr [00476D48], ebp
 :00412404 EB33        jmp 00412439
 
 (Выкинут мусор)
 :0041245E E8FD480000  call 00416D60 <- Вот откуда вызывается предыдущая процедура
 
 * Reference To: proton.?DeleteRegistration@@YAXXZ, Ord:001Bh
                                   |
 :00412463 FF15F0504200 Call dword ptr [004250F0] <- Нас хотят лишить регистрации
 

Вот уже и первый подлячек обнаружился. Как я уже говорил, попались они на стабильном адресе имени. Идем в Поиск набираем 476D24. И он находит ее на строках: 40BD29, 40D794, 40DF0C, 412711, 4152F5, 4123B8. Ого-го сколько подлянок. Не хочу захламлять статью, поэтому найдите и разберитесь с ними сами.

В итоге процедура генерации стала выглядеть так

 -----------------------------------------
 		{Файл kg.asm}
 -----------------------------------------
 ; Собственно сырец KeyGen'a.
 ; Следует обратить внимание на процедуру KeyGen в конце этого файла,
 ; да на inc файл с некоторыми переменными.
 ;
 ; #########################################################################
 
       .386
       .model flat, stdcall  ; 32 bit memory model
       option casemap :none  ; case sensitive
 
       include kg.inc        ; local includes for this file
 
 ; #########################################################################
 
 .data
 
    szDisplayName db "AxySnake v1.15 KeyGen by Fess [PTDS]",0
    szAboutCapt   db "About...", 0
    szAboutText   db "         Game: AxySnake v1.15 ", 13,10
 				 db "Made by AxySoft URL: www.axysoft.com", 13,10
                  db "      KeyGen by Fess [PTDS]",    13,10
                  db "   mailto: lomovskih@yandex.ru", 13,10
                  db "  Special Thanks by Dr.Golova ", 13,10
                  db " Visit site: vallkor.chat.ru  ", 0
 
 ; Для работы с реестром
    Software db 'Software',0
    AxySoft  db 'AxySoft',0
    AxySnake db 'AxySnake',0
    RegName  db 'RegName',0
    RegCode  db 'RegCode',0
    szREGSZ  db 'REG_SZ',0
    TitleM   db 'Apply..'
    TextM    db 'Apply current name and Password'
 
    ZZZ		db '23456789ABCDEFGHJKLMNPQRSTUVWXYZ',0
    CodeReg	db '23456789ABCDEFGHJSCB',0
    GenCode  db 32 DUP (?)
    AddRegName db 32 DUP (?) ;Буфер для суммирования кодов имени
    hKey             dd  ?
    lpcbData         dd  ?
 
 ; ################  Дальше идет стандартное masm32начало  #################
 
 .code
 
 start:
       invoke GetModuleHandle, NULL
       mov hInstance, eax
 
       invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
       invoke ExitProcess,eax
 
 ; #########################################################################
 
 WinMain proc hInst     :DWORD,
              hPrevInst :DWORD,
              CmdLine   :DWORD,
              CmdShow   :DWORD
 
       ;====================
       ; Put LOCALs on stack
       ;====================
 
       LOCAL wc   :WNDCLASSEX
       LOCAL msg  :MSG
       LOCAL Wwd  :DWORD
       LOCAL Wht  :DWORD
       LOCAL Wtx  :DWORD
       LOCAL Wty  :DWORD
 
       ;==================================================
       ; Fill WNDCLASSEX structure with required variables
       ;==================================================
 
       invoke LoadIcon, hInst, IDI_MAINICON    ; Грузим иконку из ресурсов.
       mov hIcon, eax
 
       szText szClassName, "KG_WINDOW"         ; Создаем новый класс окна.
 
       mov wc.cbSize,         sizeof WNDCLASSEX
       mov wc.style,          CS_HREDRAW or CS_VREDRAW  \
                              or CS_BYTEALIGNWINDOW
       mov wc.lpfnWndProc,    offset WndProc
       mov wc.cbClsExtra,     NULL
       mov wc.cbWndExtra,     NULL
       m2m wc.hInstance,      hInst
       mov wc.hbrBackground,  COLOR_BTNFACE+1
       mov wc.lpszMenuName,   NULL
       mov wc.lpszClassName,  offset szClassName
       m2m wc.hIcon,          hIcon
 
       invoke LoadCursor, NULL, IDC_ARROW   ; Грузим стандартный курсор.
 
       mov wc.hCursor,        eax
       m2m wc.hIconSm,        hIcon
 
       invoke RegisterClassEx, ADDR wc      ; Регистрируем наш класс окна.
 
       ;================================
       ; Centre window at following size
       ;================================
 
       mov Wwd, MainWndWidth
       mov Wht, MainWndHight
 
       invoke GetSystemMetrics, SM_CXSCREEN    ; Это чтоб вывести окно
       invoke TopXY,Wwd,eax                    ; В центре экрана.
       mov Wtx, eax
 
       invoke GetSystemMetrics, SM_CYSCREEN
       invoke TopXY,Wht,eax
       mov Wty, eax
 
 ; ##################  Создаем главную форму  ##############################
 
       invoke CreateWindowEx, WS_EX_WINDOWEDGE,
                              ADDR szClassName,
                              ADDR szDisplayName,
                              WS_VISIBLE or WS_CAPTION or WS_SYSMENU,
                              Wtx, Wty, Wwd, Wht,
                              NULL,NULL,
                              hInst,NULL
       mov   hWnd,eax
 
 ; ##################  Создаем все остальные контролы  #####################
 
       invoke CreateWindowEx, WS_EX_LEFT,
 			     ADDR szBtnClass,
 			     ADDR szBtn1Text,
                 	     WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,
                              Button1L, Button1T, Button1W, Button1H,
 			     hWnd, NULL, hInst, NULL
       mov   Button1, eax
 
       invoke CreateWindowEx, WS_EX_LEFT,
 			     ADDR szBtnClass,
 			     ADDR szBtn2Text,
                 	     WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,
                              Button2L, Button2T, Button2W, Button2H,
 			     hWnd, NULL, hInst, NULL
       mov   Button2, eax
 
       invoke CreateWindowEx, WS_EX_LEFT,
 			     ADDR szStaticClass, NULL,
 			     WS_VISIBLE or WS_CHILD or SS_LEFT,
                              Label1L, Label1T, Label1W, Label1H,
 			     hWnd, NULL, hInst, NULL
       mov    Label1, eax
 
       invoke CreateWindowEx, WS_EX_LEFT,
 			     ADDR szStaticClass, NULL,
 			     WS_VISIBLE or WS_CHILD or SS_LEFT,
                              Label2L, Label2T, Label2W, Label2H,
 			     hWnd, NULL, hInst, NULL
       mov    Label2, eax
 
       invoke CreateWindowEx, WS_EX_CLIENTEDGE,
 			     ADDR szEditClass, NULL,
 			     WS_CHILD or WS_VISIBLE or WS_BORDER or ES_AUTOHSCROLL,
                 	     Edit1L, Edit1T, Edit1W, Edit1H,
 			     hWnd, NULL, hInst, NULL
       mov    Edit1, eax
 
       invoke CreateWindowEx, WS_EX_CLIENTEDGE,
 			     ADDR szEditClass, NULL,
 			     WS_CHILD or WS_VISIBLE or WS_BORDER or ES_READONLY or ES_AUTOHSCROLL,
                 	     Edit2L, Edit2T, Edit2W, Edit2H,
 			     hWnd, NULL, hInst, NULL
       mov    Edit2, eax
 
       invoke  SetWindowText, Label1, ADDR szLabel1Text  ; Пишем текст на метки.
       invoke  SetWindowText, Label2, ADDR szLabel2Text
 
       invoke CreateFont, -11, 0, 0, 0, 400, 0, 0, 0, ; Грузим подходящий шрифт.
                          DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                          CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
                          DEFAULT_PITCH or FF_DONTCARE, ADDR szFontName
       mov    hFont, eax
 
       .if hFont != 0              ; Присваиваем этот шрифт всем элементам окна.
           invoke  SendMessage, Button1, WM_SETFONT, hFont, 0
           invoke  SendMessage, Button2, WM_SETFONT, hFont, 0
 	  invoke  SendMessage, Label1,  WM_SETFONT, hFont, 0
 	  invoke  SendMessage, Label2,  WM_SETFONT, hFont, 0
 	  invoke  SendMessage, Edit1,   WM_SETFONT, hFont, 0
 	  invoke  SendMessage, Edit2,   WM_SETFONT, hFont, 0
       .endif
 
       invoke  SetFocus, Edit1;
 
 ; #########################################################################
 
       invoke ShowWindow,hWnd, 1   ; Показать окно.
       invoke UpdateWindow,hWnd    ; Перерисовать окно. :)
 
       ;===================================
       ; Loop until PostQuitMessage is sent
       ;===================================
 
     StartLoop:
       invoke GetMessage,ADDR msg,NULL,0,0
       cmp eax, 0
       je ExitLoop
       invoke TranslateMessage, ADDR msg
       invoke DispatchMessage,  ADDR msg
       jmp StartLoop
     ExitLoop:
 
       return msg.wParam
 
 WinMain endp
 
 ; #########################################################################
 
 WndProc proc hWin   :DWORD,
              uMsg   :DWORD,
              wParam :DWORD,
              lParam :DWORD
 
     LOCAL var    :DWORD
     LOCAL caW    :DWORD
     LOCAL caH    :DWORD
     LOCAL Rct    :RECT
     LOCAL hDC    :DWORD
     LOCAL Ps     :PAINTSTRUCT
     LOCAL buffer1[128]:BYTE  ; Два буфера для текстовых
     LOCAL buffer2[128]:BYTE  ; манипуляций и т.п...
 
     .if uMsg == WM_COMMAND      ; Обрабатываем поступающие в окно сообщения.
         mov eax, lParam
 	.if eax == Button1      ; Нажата кнопка "About."
 	    invoke  MessageBox, hWnd, ADDR szAboutText, ADDR szAboutCapt, 0
 	.elseif eax == Button2  ; Нажата кнопка "Close."
 			call Reestr ; Записываем результаты в реестр
             invoke PostQuitMessage,NULL
             return 0
         .elseif eax == Edit1    ; Изменилось содержимое поля ввода имени (!!!)
  	    mov eax, wParam
 	    shr eax, 16
 	    .if ax == EN_CHANGE
     	        call KeyGen     ; Генерим рег. ключики показываем его.
     	    .endif
 	.endif
 
     .elseif uMsg == WM_DESTROY
         invoke PostQuitMessage,NULL
         return 0
     .endif
 
     invoke DefWindowProc,hWin,uMsg,wParam,lParam
 
     ret
 
 WndProc endp
 
 ; ########################################################################
 
 TopXY proc wDim:DWORD, sDim:DWORD
 
     shr sDim, 1      ; divide screen dimension by 2
     shr wDim, 1      ; divide window dimension by 2
     mov eax, wDim    ; copy window dimension into eax
     sub sDim, eax    ; sub half win dimension from half screen dimension
 
     return sDim
 
 TopXY endp
 
 ; #########################################################################
 ; #################  Вот это главная ф-ция расчета РН  ####################
 ; ####  Сама берет все нужное, обрабатывает ошибки и пишет результат  #####
 ; #########################################################################
 
 KeyGen  PROC
 
    pushad
 
    invoke  GetWindowText, Edit1, ADDR szRegName, 1024  ; Получить текст
                                                        ; из Edit1
    invoke  lstrlen, ADDR szRegName
    cmp eax, 3
    ja      @NameOk
    invoke  SetWindowText, Edit2, ADDR szNoName ; то уведомить пользователя
 
    popad
    ret                                         ; и выйти из функции
 
 @NameOk:
 
    mov  byte ptr [szRegCode], 0   ; Если есть - расчитать правильный
                                   ; Регистрационный номер.
 
     mov edx, offset CodeReg
 	mov word ptr [edx+17],0
     mov word ptr [edx+19],0
 	mov edx, offset GenCode
 	mov esi, offset AddRegName
     mov cl,32
 @NullS:
 
 	mov byte ptr [edx],0
     mov byte ptr [esi],0
     inc edx
     inc esi
     dec cl
     jnz @NullS
 
 
     xor eax, eax
 	xor ecx, ecx
 	xor ebx, ebx
     xor esi, esi
 @001:
 
 ; Сумма кодов имени
 ;
 	mov al, byte ptr [offset szRegName+ecx]
 	test al, al
 	je @1084E
 	cmp al, 20h
     je @10846
 	test al, 80h
 	je @10852
 @10846:
 	mov al, byte ptr [ecx+01]
 	inc ecx
 	test al, al
 	jne @001
 @1084E:
 	xor eax, eax
 @10852:
    	mov edx, offset szRegName
 	mov eax, offset AddRegName
 @10870:
 	cmp byte ptr [edx], 00
 	jne @10878
 	inc eax
     mov edx, offset szRegName
 @10878:
 	mov cl, byte ptr [edx]
 	cmp cl, 20h
 	je @10893
 	test cl, 80h
 	jne @10893
 	add byte ptr [eax], cl
 	inc eax
 	inc esi
 	cmp esi, 00000010h
 	jne @10894
 	xor esi, esi
 	mov eax, offset AddRegName
 	jmp @10894
 @10893:
 	dec ebx
 @10894:
 	inc edx
 	inc ebx
 	cmp ebx, 0000006Fh
 	jl @10870
  ;
  ;                          Приколы
  ;
     ; Первый прикол - не запускается меню
 	mov ecx, 4Dh
 	xor eax, eax
 @4123E2:
 	movsx edx, byte ptr [offset AddRegName+eax]
     inc eax
     cmp eax, 10h
 	lea ecx, [ecx+edx*2]
 	jl @4123E2
 	and ecx, 1Fh
     movsx edx, byte ptr [offset ZZZ+ecx]
     xor eax, eax
 	mov byte ptr [offset CodeReg+eax], dl
 
    ; Второй прикол - не запускается пункт меню Game
 	mov ecx, 86h
 	xor eax, eax
 @4152FC:
 	movsx edx, byte ptr [eax+offset AddRegName]
 	test al, 1
 	jz @41350B
 	add ecx, edx
 	jmp @415310
 @41350B:
 	neg edx
 	lea ecx, [ecx+edx*2]
 @415310:
 	inc eax
 	cmp eax ,10h
 	jl @4152FC
 	and ecx, 1Fh
 	movsx edx, byte ptr [offset ZZZ+ecx]
 	mov eax, 2
 	mov byte ptr [offset CodeReg+eax], dl
 
 
    ; Третий прикол -
 	mov ecx, 0000038Ch
 	xor eax, eax
 @40D79B:
 	movsx edx, byte ptr [eax+offset AddRegName]
 	cmp eax, 00000009
 	jge @40D7AF
 	lea edx, dword ptr [edx+2*edx]
 	lea ecx, dword ptr [ecx+2*edx]
 	jmp @40D7BC
 @40D7AF:
 	lea esi, dword ptr [4*edx+00000000]
 	sub esi, edx
 	neg esi
 	add ecx, esi
 @40D7BC:
 	inc eax
 	cmp eax, 00000010h
 	jl @40D79B
 	and ecx, 0000001Fh
 	movsx edx, byte ptr [offset ZZZ+ecx]
 	mov eax, 4
 	mov byte ptr [offset CodeReg+eax], dl
 
 
    ; Четвертый прикол -
 @40DF0C:
 	mov edx, 00000007
 	xor eax, eax
 @40DF13:
 	movsx ecx, byte ptr [eax+offset AddRegName]
 	cmp eax, 00000008
 	jge @40DF23
 	mov esi, ecx
 	jmp @40DF2A
 @40DF23:
 	mov esi, 00000001
 	sub esi, ecx
 @40DF2A:
 	imul esi, ecx
 	add edx, esi
 	inc eax
 	cmp eax, 00000010h
 	jl @40DF13
 	and edx, 0000001Fh
 	mov ecx, edx
 	movsx edx, byte ptr [offset ZZZ+ecx]
 	mov eax, 3
 	mov byte ptr [offset CodeReg+eax], dl
 
    ; Пятый прикол -
 @412711:
 	mov ecx, 00000307h
 	xor eax, eax
 @412716:
 	movsx edx, byte ptr [eax+offset AddRegName]
 	sub ecx, edx
 	inc eax
 	cmp eax, 00000010h
 	jl @412716
 	and ecx, 0000001Fh
 	movsx edx, byte ptr [offset ZZZ+ecx]
     mov eax,1
 	mov byte ptr [offset CodeReg+eax], dl
 
    ; Шестой прикол - При выходе с этапа, но не всегда
     xor ecx, ecx
 	xor eax, eax
     xor edx, edx
 	mov esi, offset AddRegName ;476D24
 	mov al, byte ptr [esi+13]
 	mov cl, byte ptr [esi+12]
 	mov dl, byte ptr [esi+04]
 	imul eax, ecx
 	mov cl, byte ptr [esi+03]
 	imul edx, ecx
 	mov cl, byte ptr [esi+01]
 	sub eax, edx
 	mov dl, byte ptr [esi+02]
 	imul edx, ecx
 	mov cl, byte ptr [esi+05]
 	sub eax, edx
 	mov dl, byte ptr [esi+06]
 	imul edx, ecx
 	add eax, edx
 	mov dl, byte ptr [esi]
 	sub eax, edx
 	sub eax, 0000000Dh
 	and eax, 0000001Fh
 	movsx edx, byte ptr [offset ZZZ+eax]
     mov eax, 0Ch
 	mov byte ptr [offset CodeReg+eax], dl
 
 
 ; Генерация кодового представления
 
     xor esi, esi
     mov ecx, Offset CodeReg
 @107ED:
 	xor eax, eax
 @107EF:
 	mov dl, byte ptr [eax+offset ZZZ]
 	mov bl, byte ptr [ecx]
 	cmp dl, bl
 	jne @10802
 	mov byte ptr [esi+offset GenCode], al
 	inc esi
 @10802:
 	inc eax
 	cmp eax, 00000020h
 	jl @107EF
 	mov al, byte ptr [ecx+01]
 	inc ecx
 	test al, al
 	jne @107ED
 
 ;{18 символ}
 	mov ecx, 00000049h
 	xor eax, eax
 @10908:
 	movsx edx, byte ptr [eax+offset AddRegName]
 	add ecx, edx
 	inc eax
 	cmp eax, 00000010h
 	jl @10908
 	xor eax, eax
 @10919:
 	movsx edx, byte ptr [eax+offset GenCode]
 	movsx edx, byte ptr [edx+offset ZZZ]
 	add ecx, edx
 	inc eax
 	cmp eax, 00000011h
 	jl @10919
 	and ecx, 0000001Fh
     mov byte ptr [offset GenCode+eax], cl
     mov dl, byte ptr [offset ZZZ+ecx]
     mov  byte ptr [offset CodeReg+eax], dl
 
 ;{19 символ}
 	mov ecx, 00000032h
 	xor eax, eax
 @010942:
 	movsx edx, byte ptr [eax+offset AddRegName]
 	sub ecx, edx
 	inc eax
 	cmp eax, 00000010h
 	jl @010942
 	xor eax, eax
 @10953:
 	movsx edx, byte ptr [eax+offset GenCode]
 	movsx edx, byte ptr [edx+offset ZZZ]
 	add ecx, edx
 	inc eax
 	cmp eax, 00000012h
 	jl @10953
 	and ecx, 0000001Fh
     mov byte ptr [offset GenCode+eax], cl
     mov dl, byte ptr [offset ZZZ+ecx]
     mov  byte ptr [offset CodeReg+eax], dl
 
 ;{20 символ}
 	mov ecx, 00000079h
 	xor eax, eax
 @1097C:
 	movsx edx, byte ptr [eax+offset GenCode]
 	movsx edx, byte ptr [edx+offset ZZZ]
 	sub ecx, edx
 	inc eax
 	cmp eax, 00000013h
 	jl @1097C
   	and ecx, 0000001Fh
     mov dl, byte ptr [offset ZZZ+ecx]
     mov  byte ptr [offset CodeReg+eax], dl
 
    invoke  SetWindowText, Edit2, offset CodeReg   ; Поместить полученный РН
                                                   ; в Edit2
    popad
    ret                                            ; И выйти из функции.
 
 KeyGen  ENDP
 
 Reestr  PROC
    ; При выходе последнее имя и пароль автоматически заносится в реестр
    pushad
 
    INVOKE RegCreateKeyA, HKEY_LOCAL_MACHINE, addr Software, addr hKey
    INVOKE RegCreateKeyA, hKey, addr AxySoft, addr hKey
    INVOKE RegCreateKeyA, hKey, addr AxySnake, addr hKey
 
    INVOKE lstrlen, addr szRegName
    INVOKE RegSetValueEx, hKey, addr RegName, 0, REG_SZ, addr szRegName, lpcbData
    INVOKE RegSetValueEx, hKey, addr RegCode, 0, REG_SZ, addr CodeReg, lpcbData
    INVOKE RegCloseKey, hKey
 @NoR:
    popad
    ret                                         ; и выйти из функции
 Reestr  ENDP
 ; ####################  Типа конец и все такое.  ############################
 
 end start
 -----------------------------------------
 		{Файл kg.inc}
 -----------------------------------------
 ;     include files
 ;     ~~~~~~~~~~~~~
       include \MASM32\INCLUDE\windows.inc
       include \MASM32\INCLUDE\gdi32.inc
       include \MASM32\INCLUDE\user32.inc
       include \MASM32\INCLUDE\kernel32.inc
       include \MASM32\INCLUDE\Comctl32.inc
       include \MASM32\INCLUDE\comdlg32.inc
       include \MASM32\INCLUDE\shell32.inc
       include  \MASM32\include\advapi32.inc
 
 ;     libraries
 ;     ~~~~~~~~~
 
       includelib \MASM32\LIB\gdi32.lib
       includelib \MASM32\LIB\user32.lib
       includelib \MASM32\LIB\kernel32.lib
       includelib \MASM32\LIB\Comctl32.lib
       includelib \MASM32\LIB\comdlg32.lib
       includelib \MASM32\LIB\shell32.lib
       includelib  \MASM32\lib\advapi32.lib
 
 ; #########################################################################
 
         ;=================
         ; Local prototypes
         ;=================
         WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
         WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
         TopXY PROTO   :DWORD,:DWORD
         FillBuffer   PROTO :DWORD,:DWORD,:BYTE
 
       ;=============
       ; Local macros
       ;=============
 
       szText MACRO Name, Text:VARARG
         LOCAL lbl
           jmp lbl
             Name db Text,0
           lbl:
         ENDM
 
       m2m MACRO M1, M2
         push M2
         pop  M1
       ENDM
 
       return MACRO arg
         mov eax, arg
         ret
       ENDM
 
 .data?
         szRegName     db    1024 DUP (?)  ; Буфферы для введенного имени
         szRegCode     db    1024 DUP (?)  ; и расчитанного ключика.
 
 .data
 	Button1	      dd 0  ; Хэндлы контролов.
 	Button2       dd 0
 	Edit1	      dd 0
 	Edit2	      dd 0
 	Label1	      dd 0
 	Label2        dd 0
 
         CommandLine   dd 0
         hWnd          dd 0
         hInstance     dd 0
         hIcon         dd 0
 	hFont	      dd 0
 
 	szBtn1Text    db    "About.", 0   ; Используемые текстовые строки :)
 	szBtn2Text    db    "Close.", 0
 
 	szLabel1Text  db    "Enter Name:", 0
 	szLabel2Text  db    "Get RegNum:", 0
 	szNoName      db    "Enter Name, Dude !!!", 0
 
         szBtnClass    db    "Button", 0
         szEditClass   db    "Edit"  , 0
         szStaticClass db    "Static", 0
 
         szFontName    db    "MS Sans Serif", 0
 
 ; ########################### Inserted modules ############################
 
    IDI_MAINICON   EQU   500  ; Номер иконки в ресурсах.
 
    MainWndHight   EQU   083  ; Размеры и положения всех элементов.
    MainWndWidth   EQU   355
 
    Button1W	  EQU   065
    Button1H       EQU   019
    Button1T       EQU   009
    Button1L       EQU   277
 
    Button2W	  EQU   066
    Button2H       EQU   019
    Button2T       EQU   031
    Button2L       EQU   277
 
    Label1W	  EQU   176
    Label1H  	  EQU   013
    Label1T        EQU   012
    Label1L        EQU   008
 
    Label2W	  EQU   176
    Label2H  	  EQU   013
    Label2T        EQU   034
    Label2L        EQU   008
 
    Edit1W	  EQU   190
    Edit1H  	  EQU   021
    Edit1T         EQU   008
    Edit1L         EQU   080
 
    Edit2W	  EQU   190
    Edit2H  	  EQU   021
    Edit2T         EQU   030
    Edit2L         EQU   080
 
 ; #########################################################################
 

Процедура генерации опробована и проверена. Сделана на Masm 7.0.

Для имени Fess код должен быть 5WKJ9789ABCD7FGHJQUK.

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

Послесловие

Спасибо автору за предоставленный для исследования продукт. Было очень интересно.

Господа Авторы: Спасибо за интересный продукт, если бы еще чуточку улучшили защиту, то возможно пришлось бы изрядно попотеть, а пока только 3+.

Братья Крэкеры: Что ни говори, а игра хорошая. И еще ПРОВЕРЯЙТЕ ВСЕГДА СВОИ КРЭКИ!!! А то видите как с Desperate вышло.

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


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


With best wishes Fess Member of the group PTDS

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



Обсуждение статьи: Кейген для AxySnake v1.15. >>>


Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS