www.pudn.com > Kgensrcs.zip > ID3-SER.ASM


; Serial Number generator by Lord Soth. Version 1.0 
; for ID crackme number 3. 
; Any comments are welcome, but will be ignored :) 
;----------------------------------------------------------------- 
model compact 
.data 
 
 
querystr db 'Enter your soon to be registered name: $' 
headline db 'Immortal Descendants CrackMe 3 serial number generator!$' 
sernumstr db 'Your serial number is: $' 
creditstr db 'Cracked and brought to you by Lord Soth!!$' 
zerostr db 'ERROR: Zero length string.$' 
username db 256 DUP (0)		; max length of string that can be brought by a dialog box 
 
str_out db 12 DUP (0)		; length of final serial 
ser_len dw 0000 
 
.code 
.startup 
.386C 
 
MOV AH,0 
MOV AL,3 
INT 10h					; set normal text video mode. 
MOV AX,0625h			; set 25 lines to scroll up 
MOV BH,1Fh				; set color attribute for blank chars 
MOV CX,0000				; set upper-left corner of window 
MOV DX,184Fh			; set lower-right corner of window 
INT 10h					; fill screen with blue death :) 
 
push ds 
pop es 
mov ah,13h 
mov al,1 
mov bh,0 
mov bl,0eh 
mov cx,37h 
mov dx,0 
mov ebp,offset es:headline		; this will print the headline string.. 
int 10h 
 
MOV Ah,3 
MOV BH,0 
INT 10h							; get cursor position 
 
ADD DH,2						; go down 2 lines 
MOV AH,2 
MOV DL,0 
PUSH DX 
MOV BH,0 
INT 10h							; set cursor on new position 
 
POP DX 
MOV AH,13h 
MOV AL,1 
MOV BX,1Fh 
MOV CX,27h						; 39 chars to print 
MOV EBP,offset ES:querystr		; load offset of string 
INT 10h							; print the damn string :) 
 
; get the user name from the user, of course.. who did u think? :) 
 
MOV CX,0FFh						; counter from 255 to 0 (bytes read) 
mov bx,0						; pointer for memory 
LEA DI,username 
 
KBread:	MOV AH,0 
	INT 16h						; get char from keyboard 
	MOV BX,CX 
	OR BX,0FF00h 
	NOT BX						; BX will be used to point to the memory where char is stored 
	CMP AH,1Ch					; check for Enter pressed 
	JZ  CreateUserName 			; Bug outa here 
	CMP AH,0Eh					; check for backspace 
	JNZ store 
	CALL delchar 
	JMP Kbread 
 
store:	MOV [DI+BX],AL 			; store ASCII byte in username buffer 
		MOV AH,0Ah 
		MOV BX,0 
		PUSH CX					; store counter on stack 
		MOV CX,1 
		INT 10h					; print the char on screen 
		MOV AH,3 
		INT 10h					; get cursor position 
		INC DL		 			; increase X pos by 1 
		MOV AH,2 
		MOV BH,0 
		INT 10h					; set on new pos 
		POP CX	 
		LOOP KBread				; get another char (CX decreases) 
 
; Create the REAL username the program has to calculate the serial from 
 
CreateUserName :  
 
NOT CL							; reversing CX makes it the string length 
CMP CL,0						; if no chars, get outa here :) 
JNZ contuser					;  
JMP out_of_prog					; this is a fixed JMP, if your calculation routine is long 
								; this might be needed 
 
contuser: 
 
MOV AX,0						; initailize to 0 
LEA SI,username					; pointer to the username we entered 
MOV CX,5						; 5 chars to process 
MOV BX,0						; set BX to 0 
LEA DI,str_out          		; load target string offset into EDI :) 
 
;Calculation of the serial number , those 4 little lines :) 
calc: 
 
MOV AL,[SI+BX]			; get char 
CALL num2str			; turn it into an ASCII digit 
INC BX					; next char 
LOOP calc				; all over again.. 
 
;Get string length and check against 10, which is max 
LEA SI,str_out 
MOV DI,SI 
not_end: 
INC SI 
CMP BYTE PTR [SI],0				; check for end of string 
JNZ not_end 
SUB SI,DI						; substract will give the length 
CMP SI,0Ah						; compare to 10 
JLE good_num					; if 10 or less, continue, this is a good number 
MOV SI,0Ah						; if more than 10, set to 10, coz 10 is the max the prog uses.. 
good_num: 
MOV WORD PTR [ser_len],SI			; store length of serial number 
 
		 
	MOV AH,3 
	MOV BX,0 
	INT 10h				; get cursor position 
	ADD DH,2 
	MOV DL,0 
	MOV AX,1301h 
	MOV BX,1Fh 
	MOV CX,17h			; 23 chars to print - "Your serial number...." 
	MOV EBP,offset sernumstr 
	INT 10h 
	MOV AH,3 
	MOV BX,0 
	INT 10h				; get cursor position 
	MOV CX,WORD PTR [ser_len] ; get serial length 
	MOV AX,1301h 
	MOV BX,1Fh 
	MOV EBP,offset str_out 
	INC EBP 
	INT 10h				; print serial number 
	MOV AH,3 
	MOV BX,0 
	INT 10h				; get cursor position 
	ADD DH,3			; increase Y pos by 3 
	MOV DL,0			; X pos = 0, start of line 
	MOV AX,1301h 
	MOV BX,1Fh 
	MOV CX,29h 
	MOV EBP,offset creditstr 
	INT 10h				; print my name 
	POP BP 
	MOV AX,4C00h 
	INT 21h				; get da fuck outa here :) 
 
out_of_prog :  
	MOV AH,3 
	MOV BX,0 
	INT 10h				; get cursor position 
	MOV AX,1301h 
	MOV DL,0 
	ADD DH,3 
	MOV BX,1Fh 
	MOV CX,1Ah			; 26 chars to print, "ERROR: Zero length..." 
	MOV EBP,offset ES:zerostr 
	INT 10h 
	POP BP 
	MOV AX,4C00h 
	INT 21h				; get outa here, no chars in username 
 
delchar PROC near 
	PUSH CX 
	PUSH AX 
	CMP BX,0 
	JZ nochars 
	MOV BYTE PTR [DI+BX],0		; store null char on the buffer 
	DEC BX						; reduce memory pointer by 1 
	PUSH BX 
	MOV BH,0 
	MOV AH,3 
	INT 10h				; get cursor position 
	DEC DL 
	MOV AH,2 
	MOV BH,0 
	INT 10h				; set it on X-1 pos 
	MOV AX,0A20h		; store "space" on screen pos 
	MOV BX,0 
	MOV CX,1 
	INT 10H				; write space on screen 
	POP BX			 
	POP AX 
	POP CX 
	INC CX				; increase CX, coz it normally decreases 
						; and we want to go back 1 char 
	RET					; return to caller 
 
nochars:MOV BX,0		; zero out BX, no chars to del 
		POP AX 
		POP CX			; free stack 
		MOV CX,0FFh		; zero out counter, intial value is FFh 
		RET 
delchar	ENDP 
 
num2str PROC near 
		; AX assumed to hold the 3 digit number 
		; BX used in indirection to put the ASCII in memory 
		; CX used to divide by 100, 10 etc..... 
 
		PUSH CX 
		MOV CX,64h			; to divide by 100, find hundreds-digit 
		CWD 
		IDIV CX 
		CMP AX,0 
		JZ  zero_dig 
		ADD AX,30h			; add 30h to make it ASCII 
		MOV [EDI],AL 
		SUB AX,30h			; return me to normal numbers 
		INC EDI 
zero_dig:MOV CX,0Ah 
		MOV AX,DX 
		CWD 
		IDIV CX 
 	    ADD AX,30h 
		ADD DX,30h 
		MOV [EDI],AL 
		INC EDI 
		MOV [EDI],DL 
		INC EDI		 
		POP CX 
		RET 
num2str	ENDP 
 
.exit 
END