How to make a keygen for HappyIcon v2.01 by ucaze

Hello and welcome to my first tutorial, please excuse my gramatical faults, my english could
be better ;) Today, we want to make a keygen for HappyIcon v2.01, you can download from
http://www.logipole.com! The algorithm is very easy, so if you can keygen this will be no
challenge, but my tutorial is not for beginners, you should have fished some serials before.

You will need Softice and Pascal to code our keygen, download both from crackstore.com
you also can use the keygen source for Delphi, just change some things. Ok, that's all!

Start:
Let's begin .. start softice and set breakpoint on hmemcpy by typing 'bpx hmemcpy'. First,
disable your bp, because we want to enter our data without jumping to softice. Now start
HappyIcon, open register-screen and enter you name, first name and serial, i enter:

Name : ucaze
First Name : TNT
Serial : 11229966

Enable hmemcpy .. and press register-button. You will notice softice will break 3 times,
so press 2x F5, then F11 to get out of the call. Now you should be in Kernel32.dll, we want
in HappyIcon.exe, so press F12 until you see on the bottom line 'HAPPYICON!.text+...'
Now we are in HappyIcon.exe, now it should look like this: (code taken from w32dasm)


:0041403D	test eax, eax			; eax=length of fake serial
:0041403F	jne 00414079			; if not zero, jump to 00414079
:00414041	push 00000010			; else...
:00414043	push 0042490C			; push error messages
:00414048	push 004248BC			; for ..
:0041404D	push ebp
:0041404E	Call dword ptr [004202AC]	; .. MessageBox
:00414054	push 00000471
:00414059	push ebp
:0041405A	Call dword ptr [004202B0]
:00414060	push eax
:00414061	Call dword ptr [004202B4]
:00414067	mov eax, 00000001		; eax=1 => bad boy
:0041406C	pop edi				; stack .. blabla
:0041406D	pop esi
:0041406E	pop ebp
:0041406F	pop ebx
:00414070	add esp, 00000784
:00414076	ret 0010			; leave call with eax=1
:00414079	mov ebx, dword ptr [004202F4]	; we land here if serial is entered
:0041407F	lea edx, dword ptr [esp+14]	; edx=name
:00414083	push edx
:00414084	lea eax, dword ptr [esp+6C]	; eax=first name
:00414088	push 00422178			; push 'HappyIcon' (constant)
:0041408D	push eax
:0041408E	lea ecx, dword ptr [esp+5A0]
:00414095	push 004248B4			; push '%s%s%s'
:0041409A	push ecx
:0041409B	call ebx			; this call make our new string
:0041409D	lea edi, dword ptr [esp+5A8] 	; and mov it to edi
:004140A4	or ecx, FFFFFFFF
:004140A7	xor eax, eax
:004140A9	add esp, 00000014
:004140AC	repnz
:004140AD	scasb
:004140AE	not ecx
:004140B0	sub edi, ecx
:004140B2	lea edx, dword ptr [esp+00000190]
:004140B9	mov eax, ecx
:004140BB	mov esi, edi
:004140BD	mov edi, edx
:004140BF	shr ecx, 02
:004140C2	repz
:004140C3	movsd
:004140C4	mov ecx, eax
:004140C6	lea eax, dword ptr [esp+190]	; new string to eax
:004140CD	and ecx, 00000003
:004140D0	repz
:004140D1	movsb
:004140D2	mov cl, byte ptr [esp+190]	; CALCULATION BEGINS HERE
:004140D9	test cl, cl			; cl=ascii of first char
:004140DB	je 004140FC			; if there's no ascii jmp
:004140DD	cmp byte ptr [eax], 5F		; cmp ascii with 5Fh ('_')
:004140E0	jne 004140E5			; if so, ...
:004140E2	mov byte ptr [eax], 20		; ascii is 20h (' ')
:004140E5	movsx ecx, byte ptr [eax]	; ascii to ecx
:004140E8	xor ecx, dword ptr [esp+10]	; xor ecx with [esp+10]
:004140EC	xor ecx, 13579ACE		; xor ecx with 13579ACEh
:004140F2	inc eax				; eax(name) + 1 (next char)
:004140F3	mov dword ptr [esp+10], ecx	; [esp+10] = ecx
:004140F7	cmp byte ptr [eax], 00		; cmp name with 00		    .. LOOP	 
:004140FA	jne 004140DD			; if there're some chars, jump back .. LOOP
:004140FC	lea edx, dword ptr [esp+0BC]	; fake serial to edx
:00414103	push edx
:00414104	call 0041637C			; fake serial testet (if avaible etc.)
:00414109	mov ecx, dword ptr [esp+14]	; mov [esp+10] (from calculation) to ecx
:0041410D	add esp, 00000004
:00414110	xor ecx, 2468BDF0		; xor ecx (= [esp+10]) with 2468BDF0h
:00414116	cmp eax, ecx			; cmp fake serial(? eax) with real(? ecx)
:00414118	je 00414148			; :)

Ok, now the analyse .. we start with 0041409B. Here you see 'call ebx', in this call our
entered data are added to one string. Type 'd edi' to see it, my new string is:

TNTHappyIconucaze

So syntax is: first_name/HappyIcon(constant)/name
004140D2: calculation begins. Here the ascii of first char is moved to cl and tested if a
name is entered, if not, jump nearly direct to serial comparation (when no serial is
generated it's 100% wrong ;). Then ascii is in eax, eax is compared with 5Fh, the ascii for
'_', if it's '_', eax is ' ' (20h), else we go on without changes. This means:

'ucaze_TNT' would be the same as 'ucaze TNT'

On 004140E5 ascii (in eax) move to ecx. Then ecx is xored with [esp+10]. You see the value
of this register by typing 'd esp+10'. Look at hex-code and you will see FFFFFFFF (-1).
After this ecx is xored with 13579ACEh. On 004140F3 you see that [esp+10] is now ecx, so on
next loop it will be another value ;)
004140F2: inc eax ... you know our name is in eax, when you inc eax, it can look like this:

eax = ucaze
inc eax
eax = caze

So he take the next char when he make a loop. When eax is 00, he quit loop and go on!
When he finished loop, our fake serial is tested in call 0041637C, but it's uninteresting.
The next line our value which was calculated in the loop move to ecx. Then ecx is xored
with 2468BDF0h ... and ... our serial is complete. Now type '? eax' to see our fake serial
and '? ecx' you see your REAL SERIAL!!!


Fisnish:
Now we need a keygen that you can release your work! I made a pascal script, you also can use
it for delhpi, but pascal files are smaller (~7kb). Perhaps there are ways to make it better
but i used this code all the time ;)


uses crt;						; standart
var							; declare variables
  name, fname, endname: string				; all strings
  ecx, i : longint;					; register as longint
  esp: longword;					; MUST BE longword ...
							; or you get negative code
begin							; code start
writeln('KeyGen for HappyIcon v2.01 by ucaze / TNT!');	; Text blabla
writeln;
write('Name: ');
readln(name);						; read in your name
write('First Name: ');				
readln(fname);						; read in first name
endname:= fname, 'HappyIcon', name;			; make string
esp:= $FFFFFFFF;					; first value of esp

For i:= 1 to length(endname) do				; start loop
  begin
    ecx:= ord(endname[i]);				;\
      If ecx = $5F then ecx:= $20;			; \
    ecx:= ecx ord esp;					;  > Calculation
    ecx:= ecx ord $13579ACE;				; /
    esp:= ecx;						;/
  end;

  esp:= esp xor $2468BDF0;				; xor loop result

writeln('Serial: ', esp);				; post serial
end.

So, that's it. If you don't understand something don't hesitate writing me emails or
visit #tntcrackers on IRC EFnet and talk with me ;) If my tutorial is bad or whatever,
just write to me, i like feedback :P


regards, ucaze (TNT!Crack!Team http://kickme.to/tnt)