Simple Keygen Template
- Using the clipboard with windows messages
- Writing your own functions
- Conditional jumps and Labels
- Loops and Anonymous Labels
New API functions:
In this tutorial we will make a simple keygen and add code for an example serial generation procedure which can be substituted for a serial generating algorithm ripped from whatever protection routine. We will also add code to copy the generated serial to the clipboard.
We will use WinAsm, which is a free assembly IDE programme for developing 32-bit Windows and 16-bit DOS programs.
Start up WinAsm, create a new standard exe project and add a new resource script. In the Resources tab of the project explorer bar click Add New Dialog and then Resources to add our icon (same as in last tutorial).
Add 2 edit controls to enter our name and display our serial, 2 static controls to label the editboxes and 3 buttons as shown:
Change the Style of the dialogbox to include DS_CENTER, the 2 static labels to include SS_CENTERIMAGE and the Serial editbox to include ES_READONLY. The script is included in the sourcecode section as simplekeygen.rc
Now switch to simplekeygen.asm in the project explorer bar and paste in the code from the sourcecode section. Here is the main body of the app:
.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
Followed by the Dialog Procedure:
And the Generate procedure which calculates the serial number:
Now we will analyse the above code.
There are 2 uninitialised string variables in which to store the user input (name) and the calculated serial.
The Dialog Procedure
We have routines to process user input from our 3 buttons.
In response to the Generate button, we simply get the user input from the Name editbox and store it in the NameBuffer string variable, call our Generate routine and display the calculated serial in the Serial editbox.
The Copy button causes whatever is displayed in the Serial editbox to be copied to the clipboard. This is achieved entirely by sending windows messages to the Serial editbox. This is much easier than writing assembly instructions to perform the same thing as the code for this is rather messy. Note that from Win32.hlp the text to be copied has to be selected first:
and the code to select the entire contents of an editbox is:
It is important to note that there are windows messages to accomplish a huge number of tasks in windows without writing out lengthy code to do the same job.
The Exit button functions as described previously.
The Generate Procedure and Labels
The Generate function is a simple example routine that reverses the order of letters in the string entered in the Name editbox. Note that we are not passing any parameters to the function and it is not returning a value as such. There is therefore no advantage in writing a prototype for it and calling it with invoke.
The routine was first written without the lines
but clicking Generate caused a crash if NameBuffer was empty (ie there was no user input). The first instruction lstrlen calculates the length of the string in NameBuffer and puts the result in eax. From Win32.hlp file: "The lstrlen function returns the length in bytes (ANSI version) or characters (Unicode version) of the specified string (not including the terminating null character)".
Test eax,eax sets the zero flag if eax is zero and jle is a conditional jump (jump if less or equal) which jumps to label NOINPUT and the ret instruction if the zero flag is set. In other words the Generate function just returns without executing any of its internal instructions instead of crashing if there is no user input.
Labels are names you can give to bookmark part of the code for a conditional jump instruction to jump to. When a label is defined it is followed by a colon but when the label appears in the jump instruction the colon is omitted.
If the string length in eax is above zero then it is copied to ecx by the mov instruction. ECX is commonly used as a counter to specify how many times a looping instruction is to occur - in this case to process each character in the string and then return.
Next the memory addresses of the NameBuffer and SerialBuffer variables are copied into esi and edi. These 2 registers are used to index the source and destination for string manipulations.
@@: declares an anonymous label. In long routines using lots of jumps or loops it is cumbersome to type in different names for all necessary labels so MASM can use anonymous labels for short jumps or loops. To use the label in the code @f jumps forward to the next @@: and @b jumps backward to the nearest @@:
Finally the string reversing routine works like this:
First the counter ecx is decreased by 1 so that the final loop ends on a zero instead of a 1. Eg if the Name string length was 6 characters then ecx will now loop from 5 to 0 and the routine will execute 6 times.
Esi contains the address of the first byte (character) of NameBuffer so when ecx=0, esi+ecx points to the first character and when ecx=5, esi+ecx points to the final character.
The first mov instruction copies the final byte in NameBuffer to the low byte of the edx register (called dl).
The second mov instruction copies this byte to the first byte of SerialBuffer (stored in edi).
Next the value of edi is increased by 1 to point to the second byte of SerialBuffer in readiness for the next loop of the routine.
Finally a logical OR operation is performed on ecx which would set the zero flag if ecx had reached zero. The ja (jump if above) instruction jumps if the zero flag is NOT set. In other words the routine keeps looping until ecx has reached 0 when it continues on to the ret instruction and exits back to the dialog procedure.
This is a very simple way of writing a function. You can pass your own functions a number of parameters and have the function return either a result or a success/error flag in eax as the API functions do. Writing a prototype for the function will allow the use of invoke. We will cover this in the next tutorial and customise our keygen with graphics and a sound:-P:-P
that's it guys .I won't writing be writing another tut for this section i have lots of other work ,Sorry if i ever find time will ping back here
Edited by James.H, 03 April 2010 - 08:21 AM.