.model tiny .386 org 100h .data GroupLogo db 13,10 db ' ммммм ',13,10 db ' л м л ',13,10 db ' лпппппппп м ппппп п пппппппппппппппппппппл лппппппппппппппп п ппппл ',13,10 db ' л ГАллллллл ГВлллллллп ГАлллплппппппп п пппп ГАлллплпппппВллллВм л ',13,10 db ' л ГБллллллл ГВллллллл ГБллллллл ГВлллллллп ГБллллллл ГВллллллл л ',13,10 db ' л ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВллллллл л ',13,10 db ' п ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВллллллл лммм ',13,10 db ' п ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВлллллллм м л ',13,10 db ' л ГВллллллл ГВллллллл ГВллллллл ГВллллллл ГВллллллл л ',13,10 db ' л ГВлллллллмммммлмлВп ГВлллллллмммммлмлллл ГВлллллллпп п п л ',13,10 db ' лммммммммммммммммммммммммммм м мммммммммммммммммммммм п лппппппппп п пп ',13,10 db ' .::[ u n i t e d њ c r ‘ c k i n g њ f o r c e ]::. л п л Antibody ',13,10 db ' лммммммммммммммммммммммммммм м мммммммммммммммммммммм п лппппппппп п пп ',13,10 db ' -----=====----- ',13,10 db ' [ў] MicroChart/32 v7.04 - Key Generator by Quantico [ў] ',13,10 db ' -----=====----- ',13,10 db ' ',13,10,'$' IntroMsgOne db 13,10,'Enter a name please : ','$' ErrorMsg db 13,10,'Need 5-20 digits, try again...',13,10,'$' ShowCodeMsg db 13,10,'Registration number : ' CodeBuffer db 20 dup(0),13,10 db 13,10,'You can use any company name. ',13,10,'$' NameBuffer db 18h, 19h dup(0) Convert_Digs db '0123456789ABCDEF' namelength db 0 datatable db 1100h dup(00h) .code .startup main proc near mov ah, 09h ; lea edx, GroupLogo ; int 21h ; show group logo mov ah, 09h ; lea edx, IntroMsgOne ; int 21h ; show intro and ask for input mov bx, 1405h ; limits for string input lea edi, NameBuffer ; call getstr ; read user input jc @error ; call keygen ; create serial number mov ah, 09h ; lea dx, ShowCodeMsg ; int 21h ; print serial number jmp @exit ; finished, quit @error: mov ah, 09h lea dx, ErrorMsg int 21h @exit: mov al, 00h ; mov ah, 4Ch ; int 21h ; terminate program main endp keygen proc near int 3 ; for debugging xor eax, eax ; eax = 0 bigloop: mov ecx, eax ; ecx = eax mov edx, 08 ; edx = 8 smallerloop: test cl, 01 ; decide whether to xor or not je overthexor shr ecx, 1 xor ecx, 0EDB88320h ; xor ecx with EDB88320h jmp overtheshr ; jump overthexor: shr ecx, 1 ; shift right ecx by 1 overtheshr: dec edx ; edx -1 (7,6,5,4,3,2,1,0) jne smallerloop ; if not 0 then jump back mov dword ptr [datatable+4*eax], ecx ; store magic value from previous loop inc eax ; eax+1 cmp eax, 100h ; is eax = 100h jl bigloop ; if not, jump to make another magic value ; end of datatable creation ; The above code creates a data lookup table using an inner and an outer ; loop. The inner loop repeats 8 times and builds up a single value for ; the datatable. When the innerloop exits, the magic value is stored in ; the table and the outerloop count increases by one. The whole thing ; repeats until the datatable contains 256 values which are used when the ; code is being made. This requires 256*8 repititions of the inner loop. xor ecx, ecx ; ecx = 0 movzx esi, byte ptr [namelength] ; esi = length of name mov edi, offset [NameBuffer+2] ; edi = pointer to name mov eax, 0AFBECDDCh ; eax = starting value createcode: xor edx, edx ; clear edx mov ebx, eax ; ebx = eax mov dl, byte ptr [ecx+edi] ; dl = byte of name and ebx, 0FFh ; keep bl, clear rest of ebx xor edx, ebx ; xor shr eax, 08 ; shift right eax by 8 mov edx, dword ptr [datatable+4*edx]; magic number from datatable xor eax, edx ; xor eax with magic num from table inc ecx ; ecx+1 cmp ecx, esi ; is loopcount = namelength jl createcode ; if not, then go again ; this section repeats for each letter of the username, performing some maths ; with each letter, the starting value and the 'magic numbers' which were built in ; the previous loop. xor edx, edx ; clear edx mov ecx, 0000000Ah ; ecx = 10 (base 10 for convert_num proc) lea edi, CodeBuffer ; place to store converted string call convert_num ; convert decimal number to printable string ; thanks Stone [UCF] ret ; end of procedure, return to caller keygen endp ; get string from user ; input : ; edi = pointer to buffer ; bl = min length ; bh = max length ; output : ; CF error, cx number of bytes read getstr proc near push dx ; save dx mov dx, di ; mov ah, 0Ah ; int 21h ; get user input movsx ecx, byte ptr [edi + 1] ; get number of digits mov byte ptr [edi + ecx + 2], 00h cmp cl, bh ; check maximum jg @@0 cmp cl, bl ; check minimum jl @@0 mov [namelength], cl ; store length xor ch, ch clc ; clear CF jmp @@1 @@0: stc ; set CF (carry flag) @@1: pop dx ; restore dx ret getstr endp Convert_Num proc near pushf pushAD sub esp, 4 mov ebp,esp cld mov esi, edi push esi ;--- loop for each digit sub bh, bh mov dword ptr [ebp], eax ;save low word mov dword ptr [ebp+4], edx ;save high word sub esi, esi ;count digits Connum1: inc esi mov eax, dword ptr [ebp+4] ;high word of value sub edx, edx ;clear for divide div ecx ;divide, DX gets remainder mov dword ptr [ebp+4],eax ;save quotient (new high word) mov eax, dword ptr [ebp] ;low word of value div ecx ;divide, DX gets remainder ; (the digit) mov dword ptr [ebp], eax ;save quotient (new low word) mov bl, dl mov al, byte ptr [Convert_Digs+ebx] ;get the digit stosb ;store cmp dword ptr [ebp], 0 ;check if low word zero jne Connum1 ;jump if not cmp dword ptr [ebp+4], 0 ;check if high word zero jne Connum1 ;jump if not sub al, al stosb ;store the terminator ;--- reverse digits pop ecx ;restore start of string xchg ecx, esi shr ecx, 1 ;number of reverses jz Connum3 ;jump if none xchg edi, esi sub esi, 2 ;point to last digit Connum2 : mov al, byte ptr [edi] ;load front character xchg al, byte ptr [esi] ;swap with end character stosb ;store new front character dec esi ;back up loopd Connum2 ;loop back for each digit ;--- finished Connum3 : add esp, 4 popad popf ret endp ;Convert_Num end main