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

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


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

Создание кейгена для EmFTP 2.01

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

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

Автор: ProTeuS <proteus@antichat.ru>

Создание кейгена для EmFTP 2.01

Отбросив всякого рода помпезные вступления о предназначенности статьи новичкам и просьбах не пинать ногами автора, сразу перейду к делу...
Исследуемая программа - FTP-клиент EmFTP 2.01, имеет 30 day trial и позволяет вводить к окне регистрации полученый от разработчиков регкод. PEID выдал после проверки файла EmFTP.exe такой результат: Microsoft Visual C++ 7.0 [Debug]. Это не может не радовать и дает пищу для дальнейших непродолжительных экспериментов.

Сразу переходим к исследованию. Жмем Help->About EmFTP...(попутно замечаем надпись Unregistered)->How To Purchase->Enter Registration Key и видим 4 поля по 4 символа для ввода регистрационной информации. Сюда можно запихнуть лишь цифры (запомним...). Вводим набум 1111-2222-3333-4444 и
получаем в ответ месаджбокс "Wrong registration key". Для отлова вызова этого сообщения грузим выполняемый файл в ольку и ставим "bp MessageBoxA" в плагине Command Bar. После повторного ввода "1111-2222-3333-4444" и нажатия на ОК прерываемся. Чтобы выяснить место, откуда функция вызывается, просмотрим стек вызовов (Alt+K). Он имеет такой вид:


Address Stack   Procedure                          Called from                Frame
0012F3EC 00416F11 USER32.MessageBoxA               EmFTP.00416F0B             0012F60C
0012F400 00416F47 EmFTP.00416ED8                   EmFTP.00416F42             0012F60C
0012F610 00418BCC EmFTP.00416F14                   EmFTP.00418BC7             0012F60C
0012F668 00401220 EmFTP.00418A61                   EmFTP.0040121B             0012F664
0012F670 004094A8 EmFTP.004011F7                   EmFTP.004094A3             0012F6C8
0012F6CC 0040A02D EmFTP.00409281                   EmFTP.0040A028             0012F6C8
0012FD64 77D38734 Maybe EmFTP.00409F64             USER32.77D38731            0012FD60
0012FD90 77D38816 ? USER32.77D3870C                USER32.77D38811            0012FD8C
0012FDF8 77D389CD ? USER32.77D3875F                USER32.77D389C8            0012FDF4
0012FE58 77D396C7 ? USER32.77D388F1                USER32.77D396C2            0012FE54   


Последовательно проверяем функции столбца "Called from" пока не дойдем до 00418BC7. Именно тут произошел вызов MessageBox с сообщением о неправильно введенном регистрационном коде


.text:00418B84                 call    __RegOpenKey
.text:00418B89                 mov     esi, eax
.text:00418B8B                 cmp     esi, ebx
.text:00418B8D                 jz      short end
.text:00418B8F                 push    esi             ; hKey
.text:00418B90                 call    ReadRegKey_FromRegistry_And_Check
.text:00418B95                 cmp     eax, ebx
.text:00418B97                 jle     short loc_418BB0 ; no JMP for registration!
.text:00418B99                 xor     ecx, ecx
.text:00418B9B                 cmp     eax, 2
.text:00418B9E                 setz    cl
.text:00418BA1                 mov     dword_466984, eax
.text:00418BA6                 push    40h
.text:00418BA8                 add     ecx, 455h       ; registered!
.text:00418BAE                 jmp     short loc_418BC6
.text:00418BB0 ; ---------------------------------------------------------------------------
.text:00418BB0
.text:00418BB0 loc_418BB0:                             ; CODE XREF: sub_418A61+136j
.text:00418BB0                 jz      short loc_418BCC
.text:00418BB2                 xor     ecx, ecx
.text:00418BB4                 cmp     eax, 0FFFFFFFEh
.text:00418BB7                 setnz   cl
.text:00418BBA                 push    30h             ; uType
.text:00418BBC                 dec     ecx
.text:00418BBD                 and     ecx, 3
.text:00418BC0                 add     ecx, 454h       ; not registered!
.text:00418BC6
.text:00418BC6 loc_418BC6:                             ; CODE XREF: sub_418A61+14Dj
.text:00418BC6                 push    ecx             ; uID
.text:00418BC7                 call    _LoadString     ;!!!! here loads "Wrong regcode" and calls MessageBox
.text:00418BCC
.text:00418BCC loc_418BCC:                             ; CODE XREF: sub_418A61:loc_418BB0j
.text:00418BCC                 push    esi             ; hKey
.text:00418BCD                 call    ds:RegCloseKey
.text:00418BD3
.text:00418BD3 end:                                    ; CODE XREF: sub_418A61+FCj
.text:00418BD3                                         ; sub_418A61+101j ...
.text:00418BD3                 xor     eax, eax
.text:00418BD5                 inc     eax
.text:00418BD6
.text:00418BD6 loc_418BD6:                             ; CODE XREF: sub_418A61+196j
.text:00418BD6                 pop     esi
.text:00418BD7                 pop     ebx
.text:00418BD8                 leave
.text:00418BD9                 retn    4


Как видно с листинга, по адресу 00418BC7 просиходит загрузка из файла ресурса с ID 454h (или 1108, "Wrong registration key", как показывает любой редактор ресурсов). Пробежавшись немного вверх по коду, замечаем, что по адресу 00418BA8 точно такая же загрузка ресурса с ID 455h (или 1109, "Thank for registering!"). Стало быть, этот код исполняется в случае удачно введенного регкода (и мы на верном пути, движемся выше...).


.text:00418B90                 call    ReadRegKey_FromRegistry_And_Check
.text:00418B95                 cmp     eax, ebx
.text:00418B97                 jle     short loc_418BB0 ; no JMP for registration!


Поскольку после вызова функции 00418B90 (ReadRegKey_FromRegistry_And_Check) выполняется проверка регистров (программа будет выводить сообщение о зарегистрированности если eax > ebx), то
можно сделать вывод, что именно в этой функции и сосредоточен модуль проверки введенного регкода на валидность.


.text:004189FE ; int __stdcall ReadRegKey_FromRegistry_And_Check(HKEY hKey)
.text:004189FE ReadRegKey_FromRegistry_And_Check proc near ; CODE XREF: sub_418A61+2Cp
.text:004189FE                                         ; sub_418A61+12Fp
.text:004189FE
.text:004189FE Data            = byte ptr -10h
.text:004189FE Type            = dword ptr -8
.text:004189FE cbData          = dword ptr -4
.text:004189FE hKey            = dword ptr  8
.text:004189FE
.text:004189FE                 push    ebp
.text:004189FF                 mov     ebp, esp
.text:00418A01                 sub     esp, 10h
.text:00418A04                 and     [ebp+cbData], 0
.text:00418A08                 push    esi
.text:00418A09                 mov     esi, ds:RegQueryValueExA
.text:00418A0F                 push    edi
.text:00418A10                 lea     eax, [ebp+cbData]
.text:00418A13                 push    eax             ; lpcbData
.text:00418A14                 push    0               ; lpData
.text:00418A16                 lea     eax, [ebp+Type]
.text:00418A19                 push    eax             ; lpType
.text:00418A1A                 push    0               ; lpReserved
.text:00418A1C                 mov     edi, offset ValueName ; "EmFTP-Pro"
.text:00418A21                 push    edi             ; lpValueName
.text:00418A22                 push    [ebp+hKey]      ; hKey
.text:00418A25                 call    esi ; RegQueryValueExA
.text:00418A27                 test    eax, eax
.text:00418A29                 jnz     short loc_418A59
.text:00418A2B                 cmp     [ebp+Type], 3
.text:00418A2F                 jnz     short loc_418A59
.text:00418A31                 cmp     [ebp+cbData], 8
.text:00418A35                 jnz     short loc_418A59
.text:00418A37                 lea     eax, [ebp+cbData]
.text:00418A3A                 push    eax             ; lpcbData
.text:00418A3B                 lea     eax, [ebp+Data]
.text:00418A3E                 push    eax             ; lpData
.text:00418A3F                 lea     eax, [ebp+Type]
.text:00418A42                 push    eax             ; lpType
.text:00418A43                 push    0               ; lpReserved
.text:00418A45                 push    edi             ; lpValueName
.text:00418A46                 push    [ebp+hKey]      ; hKey
.text:00418A49                 call    esi ; RegQueryValueExA
.text:00418A4B                 test    eax, eax
.text:00418A4D                 jnz     short loc_418A59
.text:00418A4F                 lea     eax, [ebp+Data]
.text:00418A52                 call    main_reg_routine
.text:00418A57                 jmp     short loc_418A5B
.text:00418A59 ; ---------------------------------------------------------------------------
.text:00418A59
.text:00418A59 loc_418A59:                             ; CODE XREF: ReadRegKey_FromRegistry_And_Check+2Bj
.text:00418A59                                         ; ReadRegKey_FromRegistry_And_Check+31j ...
.text:00418A59                 xor     eax, eax
.text:00418A5B
.text:00418A5B loc_418A5B:                             ; CODE XREF: ReadRegKey_FromRegistry_And_Check+59j
.text:00418A5B                 pop     edi
.text:00418A5C                 pop     esi
.text:00418A5D                 leave
.text:00418A5E                 retn    4
.text:00418A5E ReadRegKey_FromRegistry_And_Check endp


В это модуле считывается записаный только что ключ в реесте "HKEY_LOCAL_MACHINE\SOFTWARE\Emurasoft\Regist" "EmFTP-Pro", который в нашем случае имеет тип
REG_BINARY и равен "57 04 AE 08 05 0D 5C 11".


lea     eax, [ebp+Data]
call    main_reg_routine


Указатель на введенный код будет доступен в функции в регистре EAX. Давайте теперь расберемся в алгоритме генерации сохраняемого в реестре значения параметра EmFTP-Pro:
если вводимый ключ состоит из 4 полей (вспоминаем, что доступны только цифры 0..9), а запись состоит из 8 байт, то логично предположить, что это 4 переменные размером в WORD, каждая отвечающая за соответственное поле ввода. Проверим: переведем "04 57" (не забываем про обратный порядок следования байт) из 16ричной системы в 10чную и получим "1111", "08 AE" - "2222", "0D 05" - "3333", "11 5C" - "4444" - точно те же данные, что мы и вводили при регистрации. Перейдем к изучению основной функции проверки введенных данных main_reg_routine.


.text:00425328 main_reg_routine proc near              ; CODE XREF: ReadRegKey_FromRegistry_And_Check+54p
.text:00425328                 push    esi  ; бэкапим старое значение регистра
.text:00425329                 mov     esi, eax ; заносим в esi указатель на считаные с реестра данные
.text:0042532B                 movzx   eax, word ptr [esi] ; первый ворд из 4
.text:0042532E                 push    0Ah   ; заносим в верхушку стека 0A 
.text:00425330                 cdq           
.text:00425331                 pop     ecx   ; ecx = 0A 
.text:00425332                 idiv    ecx              ; eax : = eax div 0Ah 
.text:00425334                 cmp     eax, 0BFh        ; если eax = 0BFh тогда можно продолжать
.text:00425339                 jz      short loc_425340 ; прыгаем если не равно 
.text:0042533B                 or      eax, 0FFFFFFFFh  ; записываем в EAX значение провала регистрации и выходим   
.text:0042533E                 pop     esi ; восстанавливаем старое значение регистра
.text:0042533F                 retn
.text:00425340 ; ---------------------------------------------------------------------------
.text:00425340
.text:00425340 loc_425340:                             ; CODE XREF: main_reg_routine+11j
.text:00425340                 push    edi
.text:00425341                 mov     di, [esi+6]     ; 4 ворд
.text:00425345                 call    zamut
.text:0042534A                 cmp     eax, 1
.text:0042534D                 jnz     short loc_42535C
.text:0042534F                 xor     eax, eax
.text:00425351                 cmp     di, [esi+6]     ; сравниваем 4 ворд с результатом функции
.text:00425355                 setz    al
.text:00425358                 lea     eax, [eax+eax-1]
.text:0042535C
.text:0042535C loc_42535C:                             ; CODE XREF: main_reg_routine+25j
.text:0042535C                 pop     edi
.text:0042535D                 pop     esi
.text:0042535E                 retn
.text:0042535E main_reg_routine endp


С первой части функции видно, что в первом поле должно быть такое число, что chislo div $0A = $BF.
Если это условие правдиво, то мы движемся дальше и по адресу 00425345 происходит вызов основной функции просчета валидного серийника и окончательной его проверки с нами введенным.


.text:0042522E zamut           proc near               ; CODE XREF: main_reg_routine+1Dp
.text:0042522E
.text:0042522E var             = dword ptr -8
.text:0042522E first_word      = dword ptr -4
.text:0042522E
.text:0042522E                 push    ecx
.text:0042522F                 push    ecx
.text:00425230                 mov     dx, [esi+2]     ; 2 ворд
.text:00425234                 and     word ptr [esi+6], 0 ; 4 ворд
.text:00425239                 cmp     dx, 270Fh
.text:0042523E                 ja      ending
.text:00425244                 mov     ax, [esi+4]
.text:00425248                 cmp     ax, 270Fh
.text:0042524C                 ja      ending
.text:00425252                 xor     ecx, ecx
.text:00425254                 mov     cx, [esi]       ; 1 ворд
.text:00425257                 cmp     cx, 715h
.text:0042525C                 mov     [esp+8+first_word], ecx
.text:00425260                 jnz     short loc_425276
.text:00425262                 cmp     dx, 1C1Eh
.text:00425267                 jnz     short loc_425276
.text:00425269                 cmp     ax, 159Dh
.text:0042526D                 jnz     short loc_425276
.text:0042526F
.text:0042526F fail:                                   ; CODE XREF: zamut+5Aj
.text:0042526F                                         ; zamut+6Ej
.text:0042526F                 push    0FFFFFFFEh
.text:00425271                 jmp     ending2
.text:00425276 ; ---------------------------------------------------------------------------
.text:00425276
.text:00425276 loc_425276:                             ; CODE XREF: zamut+32j
.text:00425276                                         ; zamut+39j ...
.text:00425276                 cmp     cx, 71Ah
.text:0042527B                 jnz     short loc_42528A
.text:0042527D                 cmp     dx, 1009h
.text:00425282                 jnz     short loc_42528A
.text:00425284                 cmp     ax, 15h
.text:00425288                 jz      short fail
.text:0042528A
.text:0042528A loc_42528A:                             ; CODE XREF: zamut+4Dj
.text:0042528A                                         ; zamut+54j
.text:0042528A                 cmp     cx, 714h
.text:0042528F                 jnz     short loc_42529E
.text:00425291                 cmp     dx, 1321h
.text:00425296                 jnz     short loc_42529E
.text:00425298                 cmp     ax, 0B6Ch
.text:0042529C                 jz      short fail
.text:0042529E
.text:0042529E loc_42529E:                             ; CODE XREF: zamut+61j
.text:0042529E                                         ; zamut+68j
.text:0042529E                 push    ebx
.text:0042529F                 push    ebp
.text:004252A0                 push    edi
.text:004252A1                 movzx   edi, ax
.text:004252A4                 movzx   eax, dx
.text:004252A7                 mov     [esp+14h+var], eax
.text:004252AB                 push    64h
.text:004252AD                 pop     ebx
.text:004252AE                 mov     eax, edi
.text:004252B0                 cdq
.text:004252B1                 idiv    ebx             ; 3 word div 64h
.text:004252B3                 push    0Ah
.text:004252B5                 pop     ebp
.text:004252B6                 movzx   ecx, cx
.text:004252B9                 push    64h
.text:004252BB                 mov     ebx, eax
.text:004252BD                 mov     eax, ecx
.text:004252BF                 cdq
.text:004252C0                 idiv    ebp             ; 1 word div Ah
.text:004252C2                 add     ebx, [esp+18h+var] ; добавляем 3 word к остатку от "3 word div 64h"
.text:004252C6                 add     eax, ebx        ; + eax
.text:004252C8                 add     eax, edi        ; + 3 word
.text:004252CA                 cdq
.text:004252CB                 pop     edi
.text:004252CC                 idiv    edi             ; eax div 64h
.text:004252CE                 mov     eax, [esp+14h+var] ; eax = 2 word
.text:004252D2                 push    64h
.text:004252D4                 pop     ebx
.text:004252D5                 push    64h
.text:004252D7                 pop     ebp
.text:004252D8                 push    ebp
.text:004252D9                 mov     di, word ptr byte_463E20[edx*4]
.text:004252E1                 cdq
.text:004252E2                 imul    di, 64h
.text:004252E6                 idiv    ebx             ; div 64h
.text:004252E8                 mov     ebx, eax
.text:004252EA                 mov     eax, ecx
.text:004252EC                 cdq
.text:004252ED                 idiv    ebp             ; div 64h
.text:004252EF                 add     ebx, ecx
.text:004252F1                 pop     ecx
.text:004252F2                 add     eax, ebx
.text:004252F4                 cdq
.text:004252F5                 idiv    ecx             ; div 64h
.text:004252F7                 add     di, word ptr byte_463E20[edx*4]
.text:004252FF                 cmp     word ptr [esp+14h+first_word], 77Bh
.text:00425306                 mov     [esi+6], di     ; result?
.text:0042530A                 pop     edi
.text:0042530B                 pop     ebp
.text:0042530C                 pop     ebx
.text:0042530D                 jz      short fail2     ; no JMP!
.text:0042530F                 cmp     word ptr [esp+8+first_word], 77Ah
.text:00425316                 jz      short fail2     ; no JMP!
.text:00425318                 xor     eax, eax
.text:0042531A                 inc     eax
.text:0042531B                 jmp     short end
.text:0042531D ; ---------------------------------------------------------------------------
.text:0042531D
.text:0042531D fail2:                                  ; CODE XREF: zamut+DFj
.text:0042531D                                         ; zamut+E8j
.text:0042531D                 push    2
.text:0042531F
.text:0042531F ending2:                                ; CODE XREF: zamut+43j
.text:0042531F                 pop     eax
.text:00425320                 jmp     short end
.text:00425322 ; ---------------------------------------------------------------------------
.text:00425322
.text:00425322 ending:                                 ; CODE XREF: zamut+10j
.text:00425322                                         ; zamut+1Ej
.text:00425322                 or      eax, 0FFFFFFFFh
.text:00425325
.text:00425325 end:                                    ; CODE XREF: zamut+EDj
.text:00425325                                         ; zamut+F2j
.text:00425325                 pop     ecx
.text:00425326                 pop     ecx
.text:00425327                 retn
.text:00425327 zamut           endp


Вся "красота" функции заключается в математических операциях над первыми тремя введенными числами и записи просчитанного валидного для них четвертого (.text:00425306 mov [esi+6], di).
Как мы помним, по адресу 00425351 (cmp di, [esi+6] ; сравниваем 4 ворд с результатом функции) происходит окончательная их проверка. Так что для создания кейгена достаточно "понять" алгоритм проверок и преобразовать его на любой любимый язык. Но можно сделать проще, просто рипнув эту функцию и использовав ее для своих нужд (я употребил плагин для ольки AsmToClipboard -> Copy Fixed Asm To Clipboard).

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


004252D9  |. 66:8B3C95 203E>MOV DI,WORD PTR DS:[EDX*4+463E20] ; ТУТ
004252E1  |. 99             CDQ
004252E2  |. 66:6BFF 64     IMUL DI,DI,64
004252E6  |. F7FB           IDIV EBX
004252E8  |. 8BD8           MOV EBX,EAX
004252EA  |. 8BC1           MOV EAX,ECX
004252EC  |. 99             CDQ
004252ED  |. F7FD           IDIV EBP
004252EF  |. 03D9           ADD EBX,ECX
004252F1  |. 59             POP ECX
004252F2  |. 03C3           ADD EAX,EBX
004252F4  |. 99             CDQ
004252F5  |. F7F9           IDIV ECX
004252F7  |. 66:033C95 203E>ADD DI,WORD PTR DS:[EDX*4+463E20] ; И ТУТ

чтобы сделать полностью рабочий кейген нужно рипнуть и эту таблицу. Для этого щелкаем в ольке на строке
"004252D9 |. 66:8B3C95 203E>MOV DI,WORD PTR DS:[EDX*4+463E20] ; ТУТ" и жмем Follow in dump -> Address Constant
и получаем в окне дампов начало искомой таблицы (00463E20).


00463E20  26 00 00 00 5B 00 00 00 62 00 00 00 36 00 00 00  &...[...b...6...
00463E30  34 00 00 00 60 00 00 00 13 00 00 00 35 00 00 00  4...`......5...
00463E40  19 00 00 00 54 00 00 00 3F 00 00 00 44 00 00 00  ...T...?...D...
00463E50  4C 00 00 00 38 00 00 00 5D 00 00 00 33 00 00 00  L...8...]...3...
00463E60  56 00 00 00 61 00 00 00 42 00 00 00 21 00 00 00  V...a...B...!...
00463E70  3E 00 00 00 2D 00 00 00 23 00 00 00 0E 00 00 00  >...-...#......
00463E80  1E 00 00 00 5F 00 00 00 57 00 00 00 12 00 00 00  ..._...W......
00463E90  1B 00 00 00 17 00 00 00 22 00 00 00 58 00 00 00  ......"...X...
00463EA0  2C 00 00 00 63 00 00 00 5C 00 00 00 18 00 00 00  ,...c...\......
00463EB0  37 00 00 00 41 00 00 00 59 00 00 00 4D 00 00 00  7...A...Y...M...
00463EC0  15 00 00 00 5A 00 00 00 53 00 00 00 0B 00 00 00  ...Z...S......
00463ED0  05 00 00 00 1C 00 00 00 10 00 00 00 2E 00 00 00  .............
00463EE0  49 00 00 00 40 00 00 00 0D 00 00 00 07 00 00 00  I...@..........
00463EF0  50 00 00 00 3D 00 00 00 32 00 00 00 46 00 00 00  P...=...2...F...
00463F00  0A 00 00 00 43 00 00 00 2B 00 00 00 00 00 00 00  ....C...+.......
00463F10  3B 00 00 00 48 00 00 00 5E 00 00 00 4E 00 00 00  ;...H...^...N...
00463F20  51 00 00 00 1F 00 00 00 20 00 00 00 3A 00 00 00  Q...... ...:...
00463F30  01 00 00 00 2A 00 00 00 45 00 00 00 55 00 00 00  ...*...E...U...
00463F40  4A 00 00 00 02 00 00 00 52 00 00 00 27 00 00 00  J......R...'...
00463F50  03 00 00 00 4B 00 00 00 08 00 00 00 3C 00 00 00  ...K......<...
00463F60  0F 00 00 00 14 00 00 00 24 00 00 00 25 00 00 00  ......$...%...
00463F70  28 00 00 00 29 00 00 00 16 00 00 00 1D 00 00 00  (...).........
00463F80  1A 00 00 00 11 00 00 00 2F 00 00 00 39 00 00 00  ....../...9...
00463F90  09 00 00 00 47 00 00 00 06 00 00 00 4F 00 00 00  ....G......O...
00463FA0  04 00 00 00 31 00 00 00 0C 00 00 00 30 00 00 00  ...1.......0...


копируем дамп по адрес 463FB0 (ровно 400 байт, которые имеют визуально схожую структуру).

Забив в своем кейгене дамп в отдельную таблицу, получаем примерно такое:


unit main; //на форме баттон и 4 спинедита

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Spin;

type
  TForm1 = class(TForm)
    Button1: TButton;
    SpinEdit1: TSpinEdit;
    SpinEdit2: TSpinEdit;
    SpinEdit3: TSpinEdit;
    SpinEdit4: TSpinEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
Data: array [1..400] of byte =(
 $26, 00, 00, 00, $5B, 00, 00, 00, $62, 00, 00, 00, $36, 00, 00, 00,  //&...[...b...6...
 $34, 00, 00, 00, $60, 00, 00, 00, $13, 00, 00, 00, $35, 00, 00, 00,  //4...`......5...
 $19, 00, 00, 00, $54, 00, 00, 00, $3F, 00, 00, 00, $44, 00, 00, 00,  //...T...?...D...
 $4C, 00, 00, 00, $38, 00, 00, 00, $5D, 00, 00, 00, $33, 00, 00, 00,  //L...8...]...3...
 $56, 00, 00, 00, $61, 00, 00, 00, $42, 00, 00, 00, $21, 00, 00, 00,  //V...a...B...!...
 $3E, 00, 00, 00, $2D, 00, 00, 00, $23, 00, 00, 00, $0E, 00, 00, 00,  //>...-...#......
 $1E, 00, 00, 00, $5F, 00, 00, 00, $57, 00, 00, 00, $12, 00, 00, 00,  //..._...W......
 $1B, 00, 00, 00, $17, 00, 00, 00, $22, 00, 00, 00, $58, 00, 00, 00,  //......"...X...
 $2C, 00, 00, 00, $63, 00, 00, 00, $5C, 00, 00, 00, $18, 00, 00, 00,  //,...c...\......
 $37, 00, 00, 00, $41, 00, 00, 00, $59, 00, 00, 00, $4D, 00, 00, 00,  //7...A...Y...M...
 $15, 00, 00, 00, $5A, 00, 00, 00, $53, 00, 00, 00, $0B, 00, 00, 00,  //...Z...S......
 $05, 00, 00, 00, $1C, 00, 00, 00, $10, 00, 00, 00, $2E, 00, 00, 00,  //.............
 $49, 00, 00, 00, $40, 00, 00, 00, $0D, 00, 00, 00, $07, 00, 00, 00,  //I...@..........
 $50, 00, 00, 00, $3D, 00, 00, 00, $32, 00, 00, 00, $46, 00, 00, 00,  //P...=...2...F...
 $0A, 00, 00, 00, $43, 00, 00, 00, $2B, 00, 00, 00, $00, 00, 00, 00,  //....C...+.......
 $3B, 00, 00, 00, $48, 00, 00, 00, $5E, 00, 00, 00, $4E, 00, 00, 00,  //;...H...^...N...
 $51, 00, 00, 00, $1F, 00, 00, 00, $20, 00, 00, 00, $3A, 00, 00, 00,  //Q...... ...:...
 $01, 00, 00, 00, $2A, 00, 00, 00, $45, 00, 00, 00, $55, 00, 00, 00,  //...*...E...U...
 $4A, 00, 00, 00, $02, 00, 00, 00, $52, 00, 00, 00, $27, 00, 00, 00,  //J......R...'...
 $03, 00, 00, 00, $4B, 00, 00, 00, $08, 00, 00, 00, $3C, 00, 00, 00,  //...K......<...
 $0F, 00, 00, 00, $14, 00, 00, 00, $24, 00, 00, 00, $25, 00, 00, 00,  //......$...%...
 $28, 00, 00, 00, $29, 00, 00, 00, $16, 00, 00, 00, $1D, 00, 00, 00,  //(...).........
 $1A, 00, 00, 00, $11, 00, 00, 00, $2F, 00, 00, 00, $39, 00, 00, 00,  //....../...9...
 $09, 00, 00, 00, $47, 00, 00, 00, $06, 00, 00, 00, $4F, 00, 00, 00,  //....G......O...
 $04, 00, 00, 00, $31, 00, 00, 00, $0C, 00, 00, 00, $30, 00, 00, 00); //...1.......0...


var
  Form1: TForm1;

implementation

{$R *.dfm}

function Generate(first, second, third, fourth :word): word;
begin
  asm
    PUSH ESI
    PUSH ECX
    PUSH ECX
    MOV DX, second
    AND fourth, 0
    CMP DX, 270Fh
    JA @ending
    MOV AX, third
    CMP AX, 270Fh
    JA @ending
    XOR ECX, ECX
    MOV CX, first
    CMP CX, 715h
    MOV esi, ECX //!!!
    JNZ @next
    CMP DX, 1C1Eh
    JNZ @next
    CMP AX, 159Dh
    JNZ @next
  @fail:
    PUSH -2
    JMP @ending2
  @next:
    CMP CX, 71Ah
    JNZ @next2
    CMP DX, 1009h
    JNZ @next2
    CMP AX, 15h
    JE @fail
  @next2:
    CMP CX, 714h
    JNZ @main
    CMP DX, 1321h
    JNZ @main
    CMP AX, 0B6Ch
    JE @fail
  @main:
    PUSH EBX
    PUSH EBP
    PUSH EDI
    MOVZX EDI,AX
    MOVZX EAX,DX
    MOV esi, EAX //!!!
    PUSH 64h
    POP EBX
    MOV EAX,EDI
    CDQ
    IDIV EBX
    PUSH 0Ah
    POP EBP
    MOVZX ECX, CX
    PUSH 64h
    MOV EBX, EAX
    MOV EAX, ECX
    CDQ
    IDIV EBP
    ADD EBX, esi
    ADD EAX, EBX
    ADD EAX, EDI
    CDQ
    POP EDI
    IDIV EDI
    MOV EAX, esi
    PUSH 64h
    POP EBX
    PUSH 64h
    POP EBP
    PUSH EBP
    MOV DI, WORD PTR DS:[EDX*4 + Data]
    CDQ
    IMUL DI,DI,64h
    IDIV EBX
    MOV EBX, EAX
    MOV EAX, ECX
    CDQ
    IDIV EBP
    ADD EBX, ECX
    POP ECX
    ADD EAX, EBX
    CDQ
    IDIV ECX
    ADD DI, WORD PTR DS:[EDX*4 + Data]
    MOV DX, DI
    POP EDI
    POP EBP
    POP EBX
    CMP first, 77Bh
    MOV fourth, DX //result
    JE @fail2
    CMP first, 77Ah
    JE @fail2
    XOR EAX, EAX
    INC EAX
    JMP @end
  @fail2:
    PUSH 2
  @ending2:
   POP EAX
    JMP @end
  @ending:
    OR EAX, -1h
  @end:
    MOV CX, fourth
    MOV RESULT, CX
    POP ECX
    POP ECX
    POP ESI
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
label
next_iteration;
var
first, second, third, fourth: word;
begin
    randomize;
  next_iteration:
    first := random(9999); //генерируем 4 случайных числа 
    second := random(9999);
    third := random(9999);
    fourth := random(9999);
    if first div $A <> $BF then goto next_iteration; //значение первого числа не подходит
    if first = $77B then goto next_iteration; //эти значения не следует брать, т.к. они используются только в
    if first = $77A then goto next_iteration; //education и academic version, а нам нужна FULL
    SpinEdit1.Value := first;
    SpinEdit2.Value := second;
    SpinEdit3.Value := third;
    SpinEdit4.Value := Generate(first, second, third, fourth);
end;

end.


gl hf!



Обсуждение статьи: Создание кейгена для EmFTP 2.01 >>>


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



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


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