IT-Блог о программировании и операционных системах

Простой шаблон кейгена

Автор: Goppit / ARTeam [www.accessroot.com]
Перевод: Rob [www.delphiday.blogspot.com]
Номер тьюториала: #6, Simple Keygen Template.

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



Как обычно запустите WinAsm, создайте новый проект - standart exe project. И добавьте новый скрипт ресурса и создайте новый диалог и иконку (как в предидущих уроках).

Добавьте 2 контрола "EditBox" чтобы вводить наше имя и показывать наш серийник. 2 статические надписи, чтобы подписать где какое поле находиться и 3 кнопки, как показанно на рисунке:


Измените стиль для DialogBox, добавив свойство DS_CENTER. К надписям примените свойство SS_CENTERIMAGE, а к полю где будет выводиться серийник примените свойство ES_READONLY. Скрипт вставлен в исходный код проекта как simplekeygen.rc

Теперь переключитесь в главный исходник программы ( simplekeygen.asm ) и вставьте код из нижепреведённого листинга. Вот главный код тела програмы:


.386 
.model flat,stdcall 
option casemap:none 

include  windows.inc 
include  kernel32.inc 
include  user32.inc 
includelib kernel32.lib
includelib user32.lib 

DlgProc  proto  :DWORD,:DWORD,:DWORD,:DWORD 

.data? 
hInstance HINSTANCE ?  
NameBuffer db  32 dup(?) 
SerialBuffer db  32 dup(?)

.const
IDD_KEYGEN equ  1001
IDC_NAME equ  1002
IDC_SERIAL equ  1003
IDC_GENERATE equ  1004
IDC_COPY equ  1005 
IDC_EXIT equ  1006
ARIcon  equ  2001

.code 
start: 
    invoke GetModuleHandle, NULL 
    mov    hInstance,eax 
    invoke DialogBoxParam, hInstance, IDD_KEYGEN, NULL, addr DlgProc, NULL 
    invoke ExitProcess,eax 
    
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 
.if uMsg == WM_INITDIALOG
 invoke LoadIcon,hInstance,ARIcon
 invoke SendMessage,hWnd,WM_SETICON,1,eax
 invoke GetDlgItem,hWnd,IDC_NAME
 invoke SetFocus,eax 
.elseif uMsg == WM_COMMAND
 mov eax,wParam
 .if eax==IDC_GENERATE
  invoke GetDlgItemText,hWnd,IDC_NAME,addr NameBuffer,32
  call Generate
  invoke SetDlgItemText,hWnd,IDC_SERIAL,addr SerialBuffer
 .elseif eax==IDC_COPY
  invoke SendDlgItemMessage,hWnd,IDC_SERIAL,EM_SETSEL,0,-1
  invoke SendDlgItemMessage,hWnd,IDC_SERIAL,WM_COPY,0,0
 .elseif eax==IDC_EXIT 
  invoke SendMessage,hWnd,WM_CLOSE,0,0
 .endif
.elseif uMsg == WM_CLOSE
 invoke EndDialog,hWnd,0
.endif        
    xor eax,eax
    ret 
DlgProc endp 

Generate proc
invoke lstrlen, addr NameBuffer
test eax, eax
jle NOINPUT
mov ecx, eax
mov esi, offset NameBuffer  
mov edi, offset SerialBuffer 
@@:
 dec ecx
 mov dl, BYTE ptr [esi+ecx]
 mov BYTE ptr[edi], dl
 inc edi
 or ecx, ecx
 ja @b
NOINPUT:
 ret
Generate endp

end start 

Теперь давайте проанализируем приведённый выше код:

Переменные

Есть 2 неинициализированные переменные строчного типа в которые будут помещены имя которое ввёл пользователь и сгенерированный серийный номер.

Процедура диалога

По кнопке Generate мы просто получаем имя введённое пользователем из поля ввода для имени (Name) и сохраняем его в строчную переменную NameBuffer, вызываем нашу процедуру генерации и выводим полученный в результате серийный номер в поле для серийника (Serial).

Кнопка Copy вызывает копирование всего что находиться в поле ввода серийника в буффер обмена. Вызывается это посылкой windows-сообщения полю для ввода серийника. Это намного просще, чем писать отдельную функцию для проделывания этой операции. Кстати заметьте что по спецификации из Win32.hlp, текст который должен быть скопирован, должен быть сперва выделен!:


Сообщение которое позволяет выделить всё что находиться в editbox приведено ниже:


Важно отметить, что в Windows есть масса сообщений разного рода для разных задач, позволяющих выполнить что-то без нужды написания дополнительного кода. Функция кнопки Exit была описанна в ранних уроках (прим. перев. Она просто завершает программу).

Процедура генерации и метки

Функция генерации - простой пример действия который меняет порядок символов в строке введённой в поле для имени (Name). Заметьте что мы не передаём функции никаких параметров, так же как и функция в свою очередь ничего не возвращает. Так что сдесь нет никакой необходимости в обьявлении прототипа функции и вызова её с помощью Invoke.

Сначала процедура генерации была написанна без следующих строк:

test eax,eax
jle NOINPUT
NOINPUT:
Но, нажатии на кнопку Generate вызывало сбой если буффер (переменная) NameBuffer был пуст (то есть пользователь не вводил ничего в поле для имени). Первая функция lstrlen подсчитывает длинну строки в буффере NameBuffer и возвращает результат в регистре EAX. Выдержка из Win32.hlp: "Функция lstrlen возвращает длинну в байтах (для ANSI версии) или в символах (Unicod версия) заданной строки (нулевой символ прерывания строки не учитываеться)".

Test eax,eax устанавливает флаг нуля если регистр EAX равен 0 (нулю) и совершаеться условный переход jle (Jump if Less or Equal) к метке NOINPUT и затем выполняется инструкция RET, если флаг нуля установлен!

Метки - это что-то вроде закладок, которыми вы можете подписать какой-то кусок (часть) кода для того чтобы в последствии совершать условные прыжки к этим меткам.
Когда вы определяете метку вы должны поставить после ней двоеточие, но когда вы вызываете метку или делаете на неё прыжок - двоеточие не пишеться (прим. перев: LABEL1: <- обьявили метку JMP LABEL1 <- прыгнули на метку).

Если длинна строки в EAX больше чем 0 (нуль), то длинна копируеться в регистр ECX по средствам инструкции MOV. ECX обычно используеться как счётчик который указывает сколько раз должна совершиться цикл (LOOP). В нашем примере мы используем это чтобы пройтись по всем символам в строке.

Затем в регистры ESI & EDI кладуться адреса в памяти переменных NameBuffer & SerialBuffer. Эти два регистра обычно используються в качестве источника и приёмника в строковых операциях.

@@: обьявляет анонимную метку. В длинных конструкциях используеться много переходов и/или циклов. Это заставляет нас обьявлять много разных имён для наших меток, но MASM может использовать ананимные метки для коротких прыжков и циклов. Для того чтобы использовать ананимную метку:

JMP @F - совершает прыжок вперёд по коду к ближайшей метке @@:
JMP @B - совершает прыжок назад по коду к ближайшей метке @@:

Соответственно F - Forward, B - Backward.

В общем конструкция перевода строки выглядит следующим образом:

Сначала счётчик ECX уменьшаеться на 1, так что финальный проход по циклу (петля) заканчиваеться на 0 (нуль) а не на 1. То есть если длинна строки была 6 символов, тогда ECX будет "петлять" от 5 до 0 и конструкция повториться 6 раз.

ESI содержит адрес первого символа переменной NameBuffer, то когда ECX=0, ESI+ECX - указывают на следующий символ и когда ECX=5, ESI+ECX - указывают на последний символ в строке.

Первая инструкция MOV копирует последний байт (символ) из NameBuffer в младший байт регистра EDX ( DL ).

Вторая инструкция MOV копирует этот байт на место первого байта в переменной SerialBuffer (адрес которой записанн в регистре EDI)

Потом значение EDI увеличиваеться на 1чтобы указать на второй байт переменной SerialBuffer и приготовиться ко второму проходу по циклу (ко второй петле).

И наконец инструкция OR (логическое ИЛИ) используеться с регистром ECX, которая установит флаг нуля если ECX достиг нуля. Инструкция JA (Jump if above) совершит прыжок, если флаг нуля НЕ установлен. Другими словами цикл будет продолжаться до тех пор пока ECX не достигнет нуля. Когда выполнение дойдёт до RET мы выйдем из функции в главную процедуру окна (диалога).

Это очень простой способ написания функции. Вы можете передавать функции параметр и получать возвращаеме значения в отличии от результата в EAX. Обьявление прототипа позволит вам вызвать вашу функцию с помощью Invoke. В следующих уроках мы добавим обложку для нашего кейгена и вставим в него музыку и графику.

Комментариев нет:

Отправить комментарий