.model  tiny

.386

        org 100h

.data

GroupLogo       DB '       EmailWolf Pro v1.00 *keygen*      ',10,13
                DB 'ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ| QUANTICO! |ؤؤؤؤؤؤؤؤؤؤؤؤؤؤ',10,13
                DB '  ـــ   ـــ    ـــــــــ    ـــــــــ    ',10,13         
                DB '  غغغ   غغغ    غغغ          غغغـــ       ',10,13         
                DB '  غغغـ  غغغ    غغغـ         غغغ          ',10,13         
                DB '  ككككككككك    ككككككككك    ككك          ',10,13         
                DB 'ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ',10,13         
                DB 'u N I T E D  c R A C K I N G  f O R C E  ',10,13         
                DB '[wIN95/NT]ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ[Sep 1998]',10,13
                db '                                 ',13,10,'$'



IntroMsgOne     db 13,10,'   [‏]   EmailWolf Pro v1.00 - Key Generator by Quantico  [‏]',13,10
                db '',13,10
                db 13,10,'   Enter a name        : ','$'
           
IntroMsgTwo     db 13,10,'   Enter a company     : ','$'


ErrorMsg        db 13,10,'                     Need 5-20 digits, try again...',13,10,'$'

ShowCodeMsg     db 13,10,'                     Registration number : EP-'

CodeBuffer      db 10h dup(0),13,10,'$'

NameBuffer      db 18h, 50h dup(0)

Name4           db  4 dup(0),0h

Convert_Digs 	db '0123456789ABCDEF'

EP              db 'EP',00h

namelength      db 0



.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               ;
        mov     esi, offset namelength
        call    getstr                        ; read user input
        jc      @error                        ;
        xor     eax, eax                      ; clear eax

        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

        mov     esi, offset [NameBuffer+2]
        mov     edi, offset [Name4]
        mov     ecx, 04
        rep     movsb

        mov     esi, offset EP
@00410DB1:
        xor     ecx, ecx
        mov     dl, byte ptr [esi]
        add     dl, 0Bh
back5lines:
        mov     al, byte ptr [Name4+ecx]
        imul    dl
        mov     byte ptr [Name4+ecx], al
        inc     ecx
        cmp     ecx, 04
        jl      back5lines
        mov     dl, byte ptr [esi+1]
        inc     esi
        test    dl, dl
        jne     @00410DB1
        
        mov     edi, offset NameBuffer+2
        mov     cl, byte ptr [edi]
        test    cl, cl
        je      @00410DED
        mov     edx, edi
@00410DD6:
        xor     eax, eax
        add     cl, 0Bh
@00410DDB:
        xor     byte ptr [Name4+eax], cl
        inc     eax
        cmp     eax, 04
        jl      @00410DDB
        mov     cl, byte ptr [edx+1]
        inc     edx
        test    cl, cl
        jne     @00410DD6
@00410DED:
        mov     edx, dword ptr [Name4]
        test    edx, edx
        jge     @00410DF9
        neg     edx
        test    edx, edx
@00410DF9:
        jne     @00410E00
        mov     edx, 01
@00410E00:
        cmp     edx, 270Fh
        jge     @00410E15
@00410E08:
        lea     edx, dword ptr [edx+4*edx]
        shl     edx, 1
        cmp     edx, 270Fh
        jl      @00410E08  
@00410E15:
        cmp     edx, 0F423Fh
        jle     correct
@00410E1D:       
        mov     eax, 66666667h
        imul    edx
        sar     edx, 02
        mov     eax, edx
        shr     eax, 1Fh
        add     edx, eax
        cmp     edx, 0F423Fh
        jg      @00410E1D
correct:

        mov     eax, edx
        mov     edi, offset CodeBuffer
        mov     ecx, 0Ah
        xor     edx, edx
        call    Convert_Num

	ret
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     021h                          ; 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     byte ptr [esi], 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
        sub	ebx, ebx
        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

; concatenate 2 strings
; input :
;       esi = string one, ecx = length string one
;       edi = string two, edx = length string two
; output :
;       esi = string one + string two, edx = new length
cncstr  proc    near
        xor     eax, eax                     ;
        xor     ebp, ebp                     ; clear register

        push    esi                          ; save esi

        add     esi, ecx                     ; set esi at end of string one
        add     ecx, edx                     ; adjust new length
@cnc:
        mov     al, byte ptr [edi + ebp]     ; get digit of string two
        mov     byte ptr [esi + ebp], al     ; place digit after string one 
        inc     ebp                          ;
        dec     edx                          ;
        jnz @cnc                             ; loop for length of string two

        pop     esi                          ; restore esi
        mov     byte ptr [esi - 1], cl       ; update new length
        ret
cncstr  endp

; returns ECX= length of String in DS:ESI - terminated by CHAR in AL
; registers changed: ECX
; Assumes ES=DS

strlngth  PROC
	pushf
	push edi
	push esi
	push edx

	mov edi,esi
	xor ecx,ecx
	dec ecx
	cld
	repnz scasb
	xor edx,edx
	sub edx,ecx
	dec edx
	mov ecx,edx

	pop edx
	pop esi
	pop edi

	popf
	Ret

strlngth endp


end	main