winzip 7.0 stuff for a keygen...R!SC 28th May 1999...risc@notme.com...

..best to print this text then study it, it will make it easier to follow..

after bpx getdlgitemtext, twice (1 to get the name, 1 to get the code) you should soon 
end up near here.. (getdlgitemtext breaks @ 408036, @ 40805c is the main call to check 
the information)

* Reference To: USER32.GetDlgItemTextA, Ord:00F5h
                                  |
:00408036 FF150C844600            Call dword ptr [0046840C]
:0040803C 56                      push esi			<-- pointer to code
:0040803D E800160200              call 00429642		<-- kill extra spaces on the end
:00408042 59                      pop ecx
:00408043 56                      push esi
:00408044 E822160200              call 0042966B		<-- kill extra spaces at the beginning
:00408049 803D18D9470000          cmp byte ptr [0047D918], 00	<-- check first char of name
:00408050 59                      pop ecx					      - if NULL, no information was
:00408051 745F                    je 004080B2					  - entered
:00408053 803D48D9470000          cmp byte ptr [0047D948], 00	<-- check first char of serial
:0040805A 7456                    je 004080B2					  - NULL==no info entered
:0040805C E8EAFAFFFF              call 00407B4B		<-- call the calculation routine


tracing into ':0040805C CALL 00407B4B' you will (should) soon end up here... 


:00407C0E 8D85C0FEFFFF            lea eax, dword ptr [ebp+FFFFFEC0]
:00407C14 50                      push eax		<--pointer to buffer for real reg-code to go
:00407C15 57                      push edi		<--pointer to ascii name we entered
:00407C16 E8AB000000              call 00407CC6	<--calculate the serial
:00407C1B 59                      pop ecx		<--pointer to ascii name we entered
:00407C1C BE48D94700              mov esi, 0047D948	<--ascii 'fake' serial we entered
:00407C21 59                      pop ecx		<--pointer to ascii real serial

there, see, the code is calculated when call 00407CC6 is executed, and the 'real' serial no.
is mirrored in memory, pointed to by ECX when you come out of the call :)

heres the routine that calculates the code(creates 2 word values from it, then using these,
creates the final valid number (being value#2value#1) i.e #1=0278 #2=1234, code = 12340278

* Referenced by a CALL at Address:
|:00407C16   
|
:00407CC6 55                      push ebp
:00407CC7 8BEC                    mov ebp, esp
:00407CC9 51                      push ecx
:00407CCA 8B4D08                  mov ecx, dword ptr [ebp+08]	<-- pointer to name
:00407CCD 8365FC00                and dword ptr [ebp-04], 00000000	<-- place to store value #1
:00407CD1 53                      push ebx
:00407CD2 56                      push esi
:00407CD3 8A11                    mov dl, byte ptr [ecx]	<-- first char into dl
:00407CD5 57                      push edi
:00407CD6 33C0                    xor eax, eax
:00407CD8 8BF1                    mov esi, ecx				<-- copy pointer to esi
:00407CDA 33FF                    xor edi, edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407CF1(U)
|
:00407CDC 84D2                    test dl, dl		<-- check for NULL
:00407CDE 7413                    je 00407CF3		  - if so, weve done the whole name
:00407CE0 660FB6D2                movzx dx, dl		<-- clear dh
:00407CE4 8BDF                    mov ebx, edi		<-- counter for what character were on
:00407CE6 0FAFDA                  imul ebx, edx		<-- multiple the count by the ascii value
:00407CE9 015DFC                  add dword ptr [ebp-04], ebx	<-- add the answer to value #1
:00407CEC 8A5601                  mov dl, byte ptr [esi+01]		<-- get next char
:00407CEF 47                      inc edi			<-- increase counter
:00407CF0 46                      inc esi			<-- increase character pointer
:00407CF1 EBE9                    jmp 00407CDC		<-- loop until char==NULL

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407CDE(C)
|
:00407CF3 C705DCD3470001000000    mov dword ptr [0047D3DC], 00000001
:00407CFD 8BF1                    mov esi, ecx		<-- copy pointer to name
:00407CFF 8A09                    mov cl, byte ptr [ecx]	<-- get first char 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407D1C(U)
|
:00407D01 84C9                    test cl, cl		<-- check for NULL
:00407D03 7419                    je 00407D1E		  - if so, weve done every letter
:00407D05 660FB6C9                movzx cx, cl		<-- clear ch
:00407D09 6821100000              push 00001021		<-- magic xor value
:00407D0E 51                      push ecx			<-- the characters ascii value
:00407D0F 50                      push eax			<-- value #2 
:00407D10 E82A000000              call 00407D3F		<-- do some real complicated stuff (see ARRGH!!)
:00407D15 8A4E01                  mov cl, byte ptr [esi+01]	<-- get next char
:00407D18 83C40C                  add esp, 0000000C
:00407D1B 46                      inc esi			<-- increase char pointer
:00407D1C EBE3                    jmp 00407D01		<-- loop until [char]==NULL

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407D03(C)
|
:00407D1E 0FB74DFC                movzx ecx, word ptr [ebp-04]	<-- retrive value #1 (dw)
:00407D22 83C063                  add eax, 00000063	<-- fuckup value #2 a bit more
:00407D25 51                      push ecx			<-- push value #2
:00407D26 0FB7C0                  movzx eax, ax		<-- knock value #2 down to a dw
:00407D29 50                      push eax			<-- push value #1

* Possible StringData Ref from Data Obj ->"%04X%04X"
                                  |
:00407D2A 687CF44600              push 0046F47C
:00407D2F FF750C                  push [ebp+0C]
:00407D32 E809E20400              call 00455F40		<-- convert HEX value's #1 & #2 into ASCii
:00407D37 83C410                  add esp, 00000010	  - in reverse order, so the value reads #2#1
:00407D3A 5F                      pop edi
:00407D3B 5E                      pop esi
:00407D3C 5B                      pop ebx
:00407D3D C9                      leave
:00407D3E C3                      ret

=====ARRGH!!!=======================================

* Referenced by a CALL at Addresses:
|:00407D10   , :00407DFB   big bad value #2 creator routine
|
:00407D3F 55                      push ebp
:00407D40 8BEC                    mov ebp, esp
:00407D42 8B4508                  mov eax, dword ptr [ebp+08]
:00407D45 56                      push esi
:00407D46 33C9                    xor ecx, ecx		<-- clear ecx
:00407D48 6A08                    push 00000008		<-- how many times to do maths on every character
:00407D4A 8A6D0C                  mov ch, byte ptr [ebp+0C]	<-- ch==ascii value of name
:00407D4D 5A                      pop edx			<-- edx==8 (loop counter)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407D65(C)
|
:00407D4E 8BF1                    mov esi, ecx		<-- copy ecx into esi
:00407D50 33F0                    xor esi, eax	<-- xor old value #2 with ascii letter from name
:00407D52 66F7C60080              test si, 8000	<-- i think this checks if higest bit is set..
:00407D57 7407                    je 00407D60	  - i.e is it signed or unsigned, positive or neg..
:00407D59 03C0                    add eax, eax	<-- add old value #2 to itself
:00407D5B 334510                  xor eax, dword ptr [ebp+10]	<-- our magic xor number (00001021)
:00407D5E EB02                    jmp 00407D62

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407D57(C)
|
:00407D60 D1E0                    shl eax, 1	<-- shift contents of eax over to the left by 1 bit

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407D5E(U)
|
:00407D62 D1E1                    shl ecx, 1	<-- shift contents of ecx over to the left by 1 bit
:00407D64 4A                      dec edx		<-- decrease counter
:00407D65 75E7                    jne 00407D4E
:00407D67 5E                      pop esi
:00407D68 5D                      pop ebp
:00407D69 C3                      ret


okay, we have the code calculation routine, quite simple ;) so lets rewrite it in asm 
(erm win32asm, but just the calculation bit, no input / output for you...)

;--winzip keygen code--R!SC--http://csir.cjb.net--risc@notme.com--28th May 1999--

input_name	db	'R!SC'
			db	40 dup (0)
value_1		dd	0
value_2		dd	0
finalvalue	dd	0

start:		;)

calc_value_1:
	lea		esi, input_name
	xor		edi, edi
	mov		dword ptr [value_1], edi
	mov		dword ptr [value_2], edi
	mov		dword ptr [finalvalue], edi		; make sure all values are clear before we begin
	xor		eax, eax
	xor		ebx, ebx
	mov		dl, byte ptr [esi]
value_1_loop:
	test	dl, dl
	je		done_value_1
	movzx	dx, dl	
	mov		ebx, edi
	imul	ebx, edx
	add		dword ptr [value_1], ebx
	mov		dl, byte ptr [esi+1]
	inc		edi
	inc		esi
	jmp		value_1_loop
	
done_value_1:
	lea		esi, input_name
value_2_loop:
	xor		ecx, ecx
	mov		ch, byte ptr [esi]
	test	ch, ch
	je		done_value_2
	mov		edx, 8
arrgh_1:
	mov		ebx, ecx	; i use ebx instead of esi for this bit :)
	xor		ebx, eax
	test	bx, 08000h
	je		arrgh_signed
	add		eax, eax
	xor		eax, 00001021h
	jmp		arrgh_not_signed
arrgh_signed:
	shl		eax, 01
arrgh_not_signed:
	shl		ecx, 01
	dec		edx
	jne		arrgh_1
	
	inc		esi
	jmp		value_2_loop
done_value_2:
	add		eax, 063h
	movzx	eax, ax
	mov		word ptr [finalvalue+2], ax
	mov		eax, value_1
	mov		word ptr [finalvalue],ax
	mov		eax, [finalvalue]
	;int 03

;--winzip keygen code--R!SC--http://csir.cjb.net--risc@notme.com--28th May 1999--

	
i used this code in my keygen, and it worked 100% :)  

you can enter a maximum of 40 characters, extra leading & trailing spaces are chopped off

i.e
"R!SC    99   ",0 --> "R!SC    99",0
"  oh my       1",0 --> "oh my    1",0
"heh   ",0 --> "heh",0
'   R!SC !"    $%^& *()::',0 --> 'R!SC !"    $%^& *()::',0

okay! so you should have no problem coding your own keygen for winzip now!!

short & sweet keygen tutorial, with just the essential information
written friday afternoon, may 28th 1999 by R!SC

if you want the real messy source code (TASM 5) mail me
<eof>
