				Easy Keygen Tutorial
				    HarvestR '98

---[ CONTENT ]--------------------------------------------------------------------------------

You should find in this archive:

keygentut.txt   : (you're reading it right now)
resizeimage.zip : our target, ResizeImage v3.3
wallpaper.zip   : a second target for you to practice, WallPaper 1.2

---[ WARNING ]--------------------------------------------------------------------------------

This Tutorial is for education purpose only. I wrote it to allow you to understand how are
coded some protections schemes in software. I didn't make it to allow you to use the target
program without paying the author. If you plan to use these programs regularly, please remeber
to send your $ to the authors, don't be a outlaw, and over all, don't be a LAMER !!!

---[ INTRO ]----------------------------------------------------------------------------------

target: ResizeImage 3.3
where : http://pages.whowhere.com/internet/mudry

Tools : SoftIce for Win9x v3.24
        Programming Language (C, Pascal, asm, anyone you want, I'll use our old QBASIC)

This is my first tutorial in english. I hope my bad spelling won't make this text 
too much hard to understand for you. :)

I'll try to teach you how to make a key generator for a program (aka keygen). Our target
will be an easy one, as the protection scheme is really easy to understand and follow.
I'll assume you know the following:

- basic use of SoftIce
- asm instructions (at least the ones used for cracking)

---[ TUTORIAL ]-------------------------------------------------------------------------------

At first, launch SoftICe (assuming you know the basics, and how to setup this Numega's
nice tool). Then launch our target, ResizeImage.exe ! A popup window shows up (called a 
nag-screen) asking to enter a name and a serial.

Well, we'll try to find how this protection is running. Let's enter HarvestR as a name
and 12121212 as a serial. Don't click the OK button yet, but hit CTRL & D to bring up 
SoftICe. We'll define a breakpoint, using the classical BPX GetWindowTextA. Hit CTRL-D
again to go back to the program. Click OK and... SoftICe pop up, with the words:

Break due to BPX USER32!GetWindowTextA
USER32!GetWindowTextA

Well, as we entered 2 fields (name and serial), let's type CTRL-D again. SoftIce pops again
with the same words than above. We should begin to trace the code from here, but while
cracking this program, I saw that another GetWindowTextA call was done, so, to avoid you
to trace in crappy code, just type again CTRL-D. Now we're at the right place, were the
breakpoint bringed us. (if u hit CTRL-D one more time, you'll get the message "wrong key",
meaning you missed the interesting part... the calculation of the true code).

Hit F11 key to go back to the code that called the GetWindowTextA API. You must see, in the
code window title, ResizeImage!.text......, and, under that, the begining of our code.
you should see hex value where I put xxxx, but as it can be different on each computer,
I'll use this way to paste the code here.

xxxx:00436280    CALL [USER32!GetWindowTextA] <---- our breakpoint (3rd)
xxxx:00436286    push FF
xxxx:00436288    mov ecx, [ebp+10]
xxxx:0043628B    call 00433DA5
xxxx:00436290    jmp 0043629D

We can step over the CALL at 0043628B (using F10) cause we won't find any interesting
thing in it, then we jump to 0043629D

xxxx:0043629D    pop edi    <--------- we jump here
xxxx:0043629E    pop esi
xxxx:0043629F    pop ebp
xxxx:004362A0    ret 000C

continuing to use F10, we come back from the call (RET 000C) and we land in the following
code:

xxxx:00406550    call 00436251
xxxx:00406555    pop edi         <----- we are back here, from the CALL above
xxxx:00406556    pop esi
xxxx:00406557    ret 0004

continuing (yep, back from another call...) we arrive here:

xxxx:00432974    call [eax+0000008C]
xxxx:0043297A    mov [ebp-18], 00000001  <---- we arrive here, back from the CALL
...
... several other lines of code here ...
...
xxxx:004329A3    ret 0004

continuing again, lots of CALL :)

xxxx:00406580    call 0043292C
xxxx:00406585    mov edi, [ebx] <--------- we are here this time...

Use F10 to pass the line 406585. then type D EDI, and you'll see our name
in the data window. It seems we are in the right place...

xxxx:00406587    mov ecx, FFFFFFFF 
xxxx:0040658C    sub eax, eax
xxxx:0040658E    repnz
xxxx:0040658F    scasb
xxxx:00406590    not ecx
xxxx:00406592    dec ecx

That's becoming interesting. This code will calculate the number of characters
we entered as name. This number will be stored in ecx. Just after we have:

xxxx:00406593    je 004066A4

If ecx=0 (no name entered) then jump to the line 4066A4, if not, continue:

xxxx:00406599    mov edi, [esi+5C]

Hit F10 to pass the line 406599. then type D EDI. Bingo, our fake serial is
here. Seems like we're on the right way.

xxxx:0040659C    mov ecx, FFFFFFFF
xxxx:004065A1    sub eax, eax
xxxx:004065A3    repnz
xxxx:004065A4    scasb
xxxx:004065A5    not ecx
xxxx:004065A7    dec ecx
xxxx:004065A8    je 004066A4

Again, the test to define the length of the serial, and verifying it's not empty.
as our is 8 characters, we can continue:

xxxx:004065AE    push 00000000
xxxx:004065B0    mov ecx, ebx
xxxx:004065B2    call 00433D50

We now meet a CALL. you can pass over it, no interesting code inside... use F10 to
step over. We continue and meet another CALL :

xxxx:004065B7    push eax
xxxx:004065B8    mov ecx, esi
xxxx:004065BA    call 004066E0 <----------- interesting :)

Let's go into this code. Just type F8 to step into the jump. We can see:

xxxx:004066E0    sub esp, 0000002C

xxxx:004066E3    mov [esp], 00000005        *
xxxx:004066EB    mov [esp+04], 00000003     *
xxxx:004066F3    mov [esp+08], 00000007     *
xxxx:004066FB    mov [esp+0C], 00000001     * 

Hmm, that's really strange... The program is storing some fixed values... Well,
we'd better remember that... 5, 3, 7, 1. We could see them later.
 
xxxx:00406703    push ebx
xxxx:00406704    push esi
xxxx:00406705    push edi

And now, another strange line.

xxxx:00406706    mov ebx, 12345678           *

storing the hex number 12345678 in EBX register... well, let's see more...:

xxxx:0040670B    mov [esp+20], 00000002      * 
xxxx:00406713    mov [esp+24], 00000006      *
xxxx:0040671B    push ebp
xxxx:0040671C    push 00000009
xxxx:0040671E    mov [esp+30], 00000004      *

hmmm, some other hard coded numbers: 2, 6 and 4. Well, I think we'll meet them
again later. These numbers are not here without a reason, I presume. 

xxxx:00406726    xor ebp, ebp                *
xxxx:00406728    mov [esp+24], ebp           *

Hop, do not forget this one... with the XOR, we know that now EBP=0, and it's stored
too... hmm, resuming what we met earlier, we have: 5, 3, 7, 1, 0, 2, 6, 4. well, 
could be an special ordered suite... like "shaking" numbers from 0 to 7, no ? I you want to
see the exact order where this numbers are in, just type ED ESP+24, and hit CURSOR UP. 
In the data window, you'll see something like:

xxxx:0068E874 00000005 00000003 00000007 00000001
xxxx:0068E884 00000000 00000002 00000006 00000004

Well, now it's time to be on the next line, wich is a CALL

xxxx:0040672C    call 0041DFB0

nothing interesting here, several other CALLs inside, but nothing we need... Let's
pass over it with F10, to be on the following lines :

xxxx:00406731    mov edx, dword ptr [esp+44]

Hmmm, let's type D EDX, and we see that our name HarvestR is in the data window. Well
as we suppose that the serial number is build from our name, maybe that's becoming
interesting.

xxxx:00406735    add esp, 00000004
xxxx:00406738    mov esi, eax
xxxx:0040673A    mov edi, edx
xxxx:0040673C    mov ecx, FFFFFFFF
xxxx:00406741    sub eax, eax
xxxx:00406743    repnz
xxxx:00406744    scasb
xxxx:00406745    not ecx
xxxx:00406747    dec ecx
xxxx:00406748    je 00406764

Hmm, how long is our name ? more than 0 ? good, let's continue

xxxx:0040674A    inc ebp

Wait... EBP is now equal to 1... maybe a counter ?

xxxx:0040674B    mov edi, edx
xxxx:0040674D    movsx eax, byte ptr [edx+ebp-01]    *

Hehehe, this line 0040674D is really interesting. We know that EBP=1 for now. So, in
EAX, will be loaded the byte (because of MOVSX instruction) at EDX+EBP-01, wich for
now is equal to EDX+1-01, equal to EDX... :) Well, EDX is where is stored our name, so it 
looks like the calculation is beginning. EX is now 48, the hex value for letter H.

xxxx:00406752    add ebx, eax

Bingo !!! You remember the line 00406706 [if no, just scroll up :)] ? EBX=12345678, and, now
we have EBX=EBX+EAX, so we have EBX=12345678+48. Our piece of code just added the hex value
of the first letter of our name to ebx... let's see further.

xxxx:00406754    mov ecx, FFFFFFFF
xxxx:00406759    sub eax, eax
xxxx:0040675B    repnz
xxxx:0040675C    scasb
xxxx:0040675D    not ecx
xxxx:0040675F    dec ecx
xxxx:00406760    cmp ecx, ebp
xxxx:00406762    ja 0040674A

Well, the code recalculates again the lenght of our name (still 8) and compare it to the
value of EBP (wich is 1, as we saw sooner). While EBP < ECX, we loop to the line 0040674A.

2nd Loop 
ebp=2 (INC EBP)
eax=61 (hex value for a)
ebx=12345678+48+61

3rd Loop
ebp=3 (INC EBP)
eax=72 (hex value for r)
ebx=12345678+48+61+72

...

8th Loop (and last one)
ebp=8 (INC EBP)
eax=52 (hex value for R)
ebx=12345678+48+61+72+76+65+73+74+52
      basis + H  a  r  v  e  s  t  R

Well, I hope you followed me here :). The value in EBX is now 123459A7 (don't forget our
addition is in hexa, not in decimal). Let's examine what's happening after that. We are now 
on the line:

xxxx:00406762    ja 0040674A

But this time, as ECX=EBP, we won't jump and continue bellow:

xxxx:00406764 lea eax, dword ptr [esp+30]
xxxx:00406768 push ebx
xxxx:00406769 push 00442854
xxxx:0040676E push eax
xxxx:0040676F call 0041D2F0

In line 00406768, it saves EBX, for a further use of it. We can bypass the CALL at 40676F
using F10 key, then continue here:

xxxx:00406774 add esp, 0000000C
xxxx:00406777 xor eax, eax

Bellow is another loop, from 406779 to 406789. Hehe, this part is really interesting for 
us... it's creating the key we need to register our program. Let's have a look at it.

xxxx:00406779 mov ecx, dword ptr [esp+4*eax+10]

This move in ECX the value at ESP+10 (because EAX=0). Typing D ECX will show you the 
value 5... remember the suite of numbers we met earlier ? 5, 3, 7, 1, 0, 4, 6, 2....
 
xxxx:0040677D inc eax

Now EAX=1 

xxxx:0040677E cmp eax, 00000008

if EAX=8, we're in the last loop

xxxx:00406781 mov cl, byte ptr [esp+ecx+30]
xxxx:00406785 mov byte ptr [eax+esi-01], cl
xxxx:00406789 jb 00406779                      <----- Loop while EAX < 8

These two lines are creating the final serial (the one we need to register the proggy).

1st Loop
   ECX=5
   EAX=1
   CL= 9 (the number that is at [ESP+30] + 5)
   store CL in [EAX+ESI-1] (=ESI)

2nd Loop
   ECX=3
   EAX=2
   CL= 4 (the number that is at [ESP+30] + 3)
   store CL in [EAX+ESI-1] (=ESI+1)

3rd Loop
   ECX=7
   EAX=3
   CL= 7 (the number that is at [ESP+30] + 7)
   store CL in [EAX+ESI-1] (=ESI+2)

...

Last Loop
   ECX=2
   EAX=8
   CL= 3 (the number that is at [ESP+30] + 2)
   store CL in [EAX+ESI-1] (=ESI+7)

Let's resume what happened. We have our magic number 123459A7 and the suite 
5, 3, 7, 1, 0, 4, 6, 2. With the loop above, the program move each number to his 
final position:

- get the number at position ESP+30+5, store it at ESI     (=9)
- get the number at position ESP+30+3, store it at ESI+1   (=4)
- get the number at position ESP+30+7, store it at ESI+2   (=7)
- get the number at position ESP+30+1, store it at ESI+3   (=2)
- get the number at position ESP+30+0, store it at ESI+4   (=1)
- get the number at position ESP+30+2, store it at ESI+5   (=3)
- get the number at position ESP+30+6, store it at ESI+6   (=A) 
- get the number at position ESP+30+4, store it at ESI+7   (=5)

Our final serial is 947213A5. Now we know how to calculate it, and that's the same
scheme for all the names we could enter. Here is the source of a QBASIC keygen (I know,
you could thing strange I use this old language, but it'll be easy for everyone to
convert it to any other language). I have added comments for some lines bellow:

---[ QBASIC CODE ]----------------------------------------------------------------------------

 1) | CLS                                                                           
 2) | LOCATE 2, 1
 3) | COLOR 3, 0: PRINT TAB(24); "Resize Image v3.3 «Serial Maker»"                 
 4) | COLOR 7, 0: PRINT TAB(30); "by "; : COLOR 15, 0: PRINT "HarvestR  CIA '98"; : 
 5) | LOCATE 5, 15: PRINT "Enter you Name :  "; : COLOR 15, 0: LINE INPUT ; name$   
 6) | TmpVal# = 305419896                                                           
 7) | FOR i = 1 TO LEN(name$)                                                       
 8) | TmpVal# = TmpVal# + ASC(MID$(name$, i, 1))                                
 9) | NEXT i                                                                        
10) | TmpVal$ = HEX$(TmpVal#)                                                       
11) | FOR i = 0 TO 7                                                                
12) | code$(i) = MID$(TmpVal$, i, 1)                                                
13) | NEXT i                                                                        
14) | serial$ = code$(5) + code$(3) + code$(7) + code$(1) + code$(0) + code$(2) + code$(6)
                + code$(4)
15) | LOCATE 6, 15: COLOR 7, 0: PRINT "Your serial is : "; : COLOR 7, 4: PRINT " "; 

---[ CODE EXPLANATION ]-----------------------------------------------------------------------

Lines 1 to 5   : display a short message and ask the user to enter his name.
Line 6         : declare TmpVal# = 305419896. Why ? Because that's the decimal value 
                 of 12345678 hex   :)
Lines 7 to 9   : add the ASCII value of each characters of the name to TmpVal#
Line 10        : convert the decimal value of TmpVal# into hex, puting them in a string.
Lines 11 to 13 : create a string called code$(i) for each number of our magic number
Line 14        : create the final serial by moving each number in the right place, according
                 to the suite we found (5,3,7,1,0,2,6,4)
Line 15        : display the final serial

Now you can register ResizeImage 3.3 with any name you want. To unregister and try with
another name, just delete resizeImage.ini in you Windows directory.

---[ TRAINING ]-------------------------------------------------------------------------------

You can try to make a keygen, using the same scheme, for this second program : 
WallPaper 1.2. 
It's made by the same company, and of course it use the same scheme to register it, 
with some little (easy) differences.

---[ THAT'S ALL FOLKS ]-----------------------------------------------------------------------

HarvestR 'CIA 98
================
