January 1999
"WinRAR V2.06"
Code Patching
Win '95 PROGRAM
Win Code Reversing
 
 
by Gimmee 
 
 
Code Reversing For Beginners 
 
 
 
Program Details
Program Name: wrar206.exe
Program Type: Windoze File Compressor
Program Location: Here 
Program Size: 476K
 
      
Tools Used:
 Softice V3.2 - Win'95 Debugger
W32Dasm V8.93 - Disassembler
Winice.Dat - Softice settings I used
 
Rating
Easy ( X )  Medium ( )  Hard ( )  Pro (    ) 
There is a crack, a crack in everything. That's how the light gets in.
 
     
 
WinRAR V2.06
Code Patching
Written by Gimmee
 
 
Introduction
    
WinRAR is a 32-bit Windows version of the RAR archiver - a powerful tool which allows you to create, manage and control archive files.

 There are three versions of RAR for Windows:

- console version for Windows 95 and Windows NT
- version with Windows 3.1 standard user interface for Windows 3.1 with Win32s installed,
  Windows 95 and Windows NT
- version with Windows 95 user interface for Windows 95 (WinRAR 95)
       
About this protection system
 
MWinRAR 95 is the one we will be cracking. Actually we will be patching it. I don't know enough assembly to understand the final manipulation of the serial you type in. I'v only been doing this for 4 months so excuse anything I've messed up on.

Your name or registration (AV) text has the first 5 characters encrypted, these 5 encrypted characters are compared with 5 encrypted serial numbers. I will show you as much as I know on this, hopefully someone who knows something can help me with the final manipulation of the serial.
     
The Essay 
 
Alrighty then, lets crack.

Install WinRar and fire it up. We are at the main program interface with the title WinRAR (Evaluation Copy). Under options go to Registration.

Enter your name in the registration (AV) text: The Headlesschickens
Enter your registration code: 9999999999

Press OK, it comes up registration failed, yep as usual the program has a bug *grin*, lets fix that so it says thanks good cracker.

Where to start, well as i'm just beginning I have trouble getting the overall picture with WinIce so I use WinIce in conjunction with a dead listing from W32Dasm V8.9, it just helps me follow things through when tracing through the code in WinIce. So if you wan't go ahead and make a dead listing but if not you can still follow this tut as I have done the hard work for you.

Go back to the registration screen and enter a name and serial. Now we want to break into the code and see whats going on, I use either getwindowtexta, getdlgitemtexta, hmemcpy, messageboxa. Usually i will break in at the start with something like getdlgitemtexta then mark on my deadlisting where it goes from here, then break in at the messagebox error, mark on my deadlisting where this is and work backwards. I usually end somewhere in the middle and it gives me a good complete picture of the protection scheme.

After you have entered your name and serial Press Ctrl-D at the same time to pop up WinIce. We want to break when the program gets our name and serial then follow it through. For this we can set a breakpoint on getdlgitemtexta, how do i know, well i just try either the previous one or getwindowtexta, if that doesn't work the i use hmemcpy.

Type in BPX getdlgitemtexta DO "d esp->C;"       then press enter to activate our breakpoint
(This will set a breakpoint on the windows API function getdlgitemtexta)

PS: I know nothing about windows programing except what little I have picked up from some cracking tuts, if i have said something wrong about breakpoints or API's please feel free to correct me or edit this tut.

Press F5 to go back to our program. Press OK to register. We land back in WinIce at our breakpoint. Press F12, which is return to caller and pause. Down the bottom of the WinIce code screen you will see WINRAR95 CODE!0001234 or something like this, the important part is to look for the winrar95, this tells us we are in the winrar code. Also see in the data window of WinIce our name appears, this is from the breakpoint command DO "d esp->c;" this part of the command saves us from having to search where our name is first stored, if we wan't we could now set a breakpoint on range of the name and follow what happens without having to step through all the code, i usually get lost without my deadlisting when i do this but i guess its just experience.

Press F5 again and WinInce will break again, Press F12 to get back to the caller. This is done twice because the program has to get our name then our serial number. You now will see your serial number in the data window if everything is working alright. The more experienced cracker would now put a BPR (break point range) on the serial as well then follow from there. Seem we are learning we will just step through and follow what happens.

We land here after our net breakpoint return:

* Reference To: USER32.GetDlgItemTextA, Ord:0000h

:00413C31 E8000D0100          Call 00424936
:00413C36 80BD54FFFFFF00      cmp byte ptr [ebp+FFFFFF54], 00  ;We land here, check
                                                               ;check we have entered

:00413C3D 751A                                jne 00413C59     ;a serial number then
                                                               ;jumps if we have.
 

Jump to here from above:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00413C3D(C)
|
:00413C59 8D559C         lea edx, dword ptr [ebp-64]
:00413C5C 52             push edx
:00413C5D 6830AD4200     push 0042AD30
:00413C62 E839920000     call 0041CEA0
:00413C67 83C408         add esp, 00000008
:00413C6A 8D8D54FFFFFF   lea ecx, dword ptr [ebp+FFFFFF54]
:00413C70 51             push ecx
:00413C71 8D459C         lea eax, dword ptr [ebp-64]
:00413C74 50             push eax
:00413C75 E84768FFFF     call 0040A4C1
:00413C7A 83C408         add esp, 00000008
:00413C7D 85C0           test eax, eax
:00413C7F 7532           jne 00413CB3

Now we some pushes and a call, is this call important, to check lets see what is getting pushed onto the stack.
 
 F10 until you are on the line:
 
:00413C5C 52                              push edx

type in Softice:    d edx

look in the data window of SI and we see our name, so our name is going to have something done to it in  this call

Lets trace into this call and see whats happening. F10 until you are at :00413C62
 
E839920000       call 0041CEA0

Press F8 to trace into this call, we see below:

|:0041A579   , :0041A66D   , :0041A7BC   , :0041BA8A   , :0041BAA8
|:0041BAC6   , :0041BB35   , :0041BB73   , :0041BB9C   , :0041BBC2
|:0041BD40   , :0041BD65   , :0041BD83   , :0041BDB6   , :0041BDD4
|:0041BDF2   , :0041C1D2   , :0041C4CA   , :0041CA1F   , :0041CA3A
|:0041CA55   , :0041CA70   , :0041CA8B
|
:0041CEA0 55            push ebp
:0041CEA1 8BEC          mov ebp, esp
:0041CEA3 56            push esi
:0041CEA4 57            push edi
:0041CEA5 8B7D0C        mov edi, dword ptr [ebp+0C] ;move the address of my name
                                                    ;into edi
:0041CEA8 8BF7          mov esi, edi          ; move the address of my name into esi
:0041CEAA B9FFFFFFFF    mov ecx, FFFFFFFF ecx ;is our counter register and will
                                              ;end up with the len of our name
:0041CEAF 32C0          xor al, al            ;length of our name in hex
:0041CEB1 FC            cld
:0041CEB2 F2            repnz
:0041CEB3 AE            scasb     ; repeat while not zero scan our name
:0041CEB4 F7D1          not ecx   ; ecx is negative so to get the length we have
                                  ; to neg it   (-(-ecx) = ecx)
:0041CEB6 8B7D08        mov edi, dword ptr [ebp+08] ; move address where name
                                                    ;will be copied to edi
:0041CEB9 8BC7          mov eax, edi
:0041CEBB 8BD1          mov edx, ecx
:0041CEBD D1E9          shr ecx, 1
:0041CEBF D1E9          shr ecx, 1
:0041CEC1 FC            cld       ;clear direction flag so it increments forward
:0041CEC2 F3            repz
:0041CEC3 A5            movsd     ;move data to new memory area  pointed to by es:edi
:0041CEC4 8BCA          mov ecx, edx
:0041CEC6 83E103        and ecx, 00000003
:0041CEC9 F3            repz
:0041CECA A4            movsb
:0041CECB 5F            pop edi    ;restore registers then return
:0041CECC 5E            pop esi
:0041CECD 5D            pop ebp
:0041CECE C3            ret

This routine scans the length of our name then copies it to another location, so we now have 2 locations in memory for our name. Whenever you see ECX being loaded with FFFFFFFF then repnz then scasb, this is getting the length of something, in this case our name. I have commented each line for you as best as I can.

To really understand what is going on just trace through each line with SI then watch the ecx register and see what happens.  Whenever you see repz then movsd, this is a sign that something is being copied to another memory location. Movsd is assembly for move string data, and it copies from what is pointed to by the register ds:esi  (source index) to the new address at es:dsi (destiny index). I usually F10 to the movsd the in SI type d es:edi, this will show in the data window the memory area where something is being copied. Press F10 to step over the movsd and watch the data window, whatever was being copied will appear in the data window. The more experienced cracker would now set a BPR on this memory location as well.

Ok trace through the rest of the call to the return, F10 to get back to the main part of the program.  We end up here after our call:

:00413C67 83C408            add esp, 00000008   ;clear the stack
:00413C6A 8D8D54FFFFFF      lea ecx, dword ptr [ebp+FFFFFF54] ;load my
                                                              ;serial
                                                              ;address
                                                              ;into ecx
:00413C70 51                push ecx ;push the address onto the stack
:00413C71 8D459C            lea eax, dword ptr [ebp-64] ;load my name
                                                        ;address into eax
:00413C74 50                push eax           ;push my name address
:00413C75 E84768FFFF        call 0040A4C1      ;must be an important call
:00413C7A 83C408            add esp, 00000008  ;clear stack
:00413C7D 85C0              test eax, eax   ;is eax zero or something else
:00413C7F 7532              jne 00413CB3    ;eax =0 don't jump bad cracker
:00413C81 6A30              push 00000030
:00413C83 6A1A              push 0000001A <--"Warning"
:00413C85 E801650000        call 0041A18B
:00413C8A 59                pop ecx
:00413C8B 50                push eax
:00413C8C 6A6A              push 0000006A
:00413C8E E8F8640000        call 0041A18B
:00413C93 59                pop ecx
:00413C94 50                push eax
:00413C95 FF7508            push [ebp+08]
 

We can see something important is happening, leading up to the next call, our name and serial address are being pushed, you can see this by typing in SI, d ecx when you are at :00413C70  51     push ecx , you will see your serial in the data window of SI, then d eax when you are at :00413C74  50     push eax      , you will see your name in the data window of SI.

You can see there is a test eax,eax after the call then a jnz to somewhere, so lets see where this jump goes. Trace down by pressing F10 until you get to :00413C7F 7532     jne 00413CB3. We have traced right over the important call where our name and serial was pushed and landed at this jne 00413cb3 after the test eax,eax. If we look down from here in our deadlisting we see the words Normal, Warning, Registration Failed. Because our test on eax came back zero we will not be taking this jump and heading straight down into all these bad words. So lets not go there.

In SI type RFL Z, this toggles the register flag, so now it isn't zero we will jump instead and see where we go.  Press F5 to let the program run. Whoa, Thank you for your support. We have registered it, surely it can't be that easy,well no. Close your program and run it again, damn it is back to being an evaluation copy so we know from this it saves our original name and serial then rechecks everything again when the program runs. Doesn't matter because we also know that after the important call eax must come back with a 1 in it so we will take the jump. We can now concentrate on the important call which as we soon will see encrypts the first 5 letters of our name, manipulates the serial, compares the first 5 encryypted letters of our name with the 5 encrypted serial numbers, flags a memory location to tell the program whether it is registered or not, then pops out eventually with eax set to good guy or bad guy.

Seem we are only patching it the most important part of the routine is to find the compare and where in memory the good guy, bad guy flag gets set. As much as I can I will go through the name manipulation which wasn't to hard, and as much of the serial as I can show you before I got lost.

Go back and register your name and serial, set your bpx getdlgitemtexta, Press F5, Press OK to enter your info at the registration box. Press F12 to return to caller and arrive in the WinRAR code. Now type in SI u 00413c75, this will unassemble in the code window the area where want to stop, double click on this line so that it is highlighted, this means there is a breakpoint set on this line of code. You can check this by typing in SI bl, this will show you what breakpoints you have set. Disable the getdlgitemtexta breakpoint by typing bd0, we don't need it anymore. Press F5 and you should land right on top of our important call just before the test eax,eax and the jne 00413CB3.

Press F8 to trace into this call, I printed out this call from W32Dasm and ended up with 5 pages of code, somewhere in here we are going to find what we are looking for, lets trace.
 

The start important call:

* Referenced by a CALL at Addresses:
|:00408044   , :00413C75
|
:0040A4C1 55                 push ebp
:0040A4C2 8BEC               mov ebp, esp
:0040A4C4 81C42CFFFFFF       add esp, FFFFFF2C
:0040A4CA 53                 push ebx
:0040A4CB 56                 push esi
:0040A4CC 57                 push edi
 
We can see in our deadlisting it is called from 2 places, 1 from where we have just come at :00413C75. It would be interesting to see where the other call is from. In W32Dasm click on the goto button and type the other address :00408044.

We see this:
 
:0040802C E81FC70100       Call KERNEL32.GetPrivateProfileStringA
:00408031 803D30AD420000   cmp byte ptr [0042AD30], 00
:00408038 7412             je 0040804C
:0040803A 6880AD4200       push 0042AD80  'push our serial
:0040803F 6830AD4200       push 0042AD30  'push my name
:00408044 E878240000       call 0040A4C1  ;Our important call
:00408049 83C408           add esp, 00000008

From sandmans essays we know getprivateprofilestringa gets info from an ini file, in this case our name and serial. This usually is done at the start of a program to recheck if our information is correct. The important thing here is that to check our information at the start of the program it uses the same routine as the registration checking routine. So if we patch that routine in the right place we will have the program registered correctly when we restart the program. This is why after we registered correctly before, then closed the program then restarted it, it still was only an evaluation copy. Lets get back to our important call and crack this babe.

 Referenced by a CALL at Addresses:
|:00408044   , :00413C75
|
:0040A4C1 55                push ebp
:0040A4C2 8BEC              mov ebp, esp
:0040A4C4 81C42CFFFFFF      add esp, FFFFFF2C
:0040A4CA 53                push ebx
:0040A4CB 56                push esi
:0040A4CC 57                push edi

* Reference to String Resource ID=00070: "Authenticity verification FAILED"
 
:0040A4CD 6A46              push 00000046
:0040A4CF 6A00              push 00000000
:0040A4D1 8D8574FFFFFF      lea eax, dword ptr [ebp+FFFFFF74]
:0040A4D7 50                push eax      ;This call is like the movsb
                                          ;routine I showed you above,
:0040A4D8 E803290100        call 0041CDE0 ;except it uses stosd, trace into
                                          ;it the stop at the stosd.
:0040A4DD 83C40C            add esp, 0000000C

In SI, type d es:edi, F10 and you will see what gets copied.

In this case you will see a whole lot of zeros appear. So this call just clears a memory area. Just like cleaning an area on a whiteboard so you can write something there. It will most probably copy our name or serial here some time soon.

* Possible Reference to Dialog: ARCINFODLG, CONTROL_ID:0009, "Help"
 
:0040A4E0 6A09          push 00000009
:0040A4E2 6A00          push 00000000
:0040A4E4 68EFB84200    push 0042B8EF
:0040A4E9 E8F2280100    call 0041CDE0 ;Same call as above,clear memory
                                      ;area.
:0040A4EE 83C40C        add esp, 0000000C
:0040A4F1 FF7508        push [ebp+08] ;Push address of my name onto stack
:0040A4F4 8D9574FFFFFF  lea edx, dword ptr [ebp+FFFFFF74]
:0040A4FA 52            push edx       ;Address of memory area that we
                                       ;filled with zeros.
:0040A4FB E8A0290100    call 0041CEA0  ;See above on explanation on Call
                                       ;0041CEA0, it moves
:0040A500 83C408        add esp, 00000008 ;our name to another memory
                                          ;location
:0040A503 FF7508        push [ebp+08]
:0040A506 E8C5290100    call 0041CED0   ;This call gets the length of our
                                        ;name similar to Call 0041CEA0
:0040A50B 59            pop ecx
:0040A50C 8945FC        mov dword ptr [ebp-04], eax ;Move length of our
                                                    ;name into this memory
                                                    ;area
:0040A50F 85C0          test eax, eax               ;Is there a name
                                                    ;present
:0040A511 7406          je 0040A519
:0040A513 837DFC3C      cmp dword ptr [ebp-04], 0000003C Is it more than
                                                        ;3C hex long or
:0040A517 7E07          jle 0040A520                    ;60 characters.

We land here after the check on the length of our name, the next call has all sorts of stuff that I don't understand happening in it but if you look in your deadlisting you can see below the call there are the words warning and Not enough memory for registration. We can make a good guess then that this is just checking memory and is not where we should be checking for our protection.

:0040A520 6800001000     push 00100000
:0040A525 E8468C0100     call 00423170
:0040A52A 59             pop ecx
:0040A52B A33C574200     mov dword ptr [0042573C], eax
:0040A530 85C0           test eax, eax
:0040A532 7529           jne 0040A55D 'Jump here if there is enough memory
:0040A534 6A00           push 00000000

* Possible Reference to String Resource ID=00026: "Warning"

 :0040A536 6A1A          push 0000001A
:0040A538 E84EFC0000     call 0041A18B
:0040A53D 59             pop ecx
:0040A53E 50             push eax

*Reference to String  "Not enough memory for registration"
 
:0040A53F 68BF000000     push 000000BF
:0040A544 E842FC0000     call 0041A18B
:0040A549 59             pop ecx
:0040A54A 50             push eax
:0040A54B FF35A0644200   push dword ptr [004264A0]

We land at the section of code below, this is where things start getting interesting and our code manipulation begins, so here goes, sorry if i haven't explained this very well but i'm struggling to understand key generation myself at this stage.

:0040A55D 8B15F4BE4200            mov edx, dword ptr [0042BEF4]
:0040A563 8955F4                  mov dword ptr [ebp-0C], edx
:0040A566 C705F4BE420001000000    mov dword ptr [0042BEF4], 00000001
:0040A570 FF750C                  push [ebp+0C]   ;Push my serial onto the stack
:0040A573 8D8D2CFFFFFF            lea ecx, dword ptr [ebp+FFFFFF2C]
:0040A579 51                      push ecx
:0040A57A E821290100              call 0041CEA0 ;Get the length of  our serial.
:0040A57F 83C408                  add esp, 00000008
:0040A582 C605EEB8420000          mov byte ptr [0042B8EE], 00
:0040A589 C6050ABF420000          mov byte ptr [0042BF0A], 00 ;Not to sure about
:0040A590 C60509BF420001          mov byte ptr [0042BF09], 01 ;the importance of
:0040A597 C60508BF420002          mov byte ptr [0042BF08], 02 ;moves?
:0040A59E 33C0                    xor eax, eax        Zero eax
:0040A5A0 89C3                    mov ebx, eax        Zero ebx
:0040A5A2 8945F8                  mov dword ptr [ebp-08], eax  ;[ebp-08] will have a
                                                               ;zero put in it
:0040A5A5 8D841D74FFFFFF          lea eax, dword ptr [ebp+ebx-0000008C] ;eax holds
                                                                        ;name address
:0040A5AC 3B5DFC                  cmp ebx, dword ptr [ebp-04]  ;= the length of our
                                                               ;name
:0040A5AF 7D0E                    jge 0040A5BF   ;Don't jump do little calculation.

:0040A5B1 33D2                    xor edx, edx   zero edx
:0040A5B3 8A10                    mov dl, byte ptr [eax]  move first letter of name into dl
:0040A5B5 3155F8                  xor dword ptr [ebp-08], edx Xor it with value at [ebp-08], start=0
:0040A5B8 43                      inc ebx
:0040A5B9 40                      inc eax
:0040A5BA 3B5DFC                  cmp ebx, dword ptr [ebp-04] ;have we been through
                                                              ;the whole name
:0040A5BD 7CF2                    jl 0040A5B1   ;if not jump and do calculation for
                                                ;next letter

What I found this little routine above does is take the first letter of your name and Xor it with 0 at [ebp-08], then get your next letter of your name in hex and Xor it with the new value at [ebp-08], this goes right through the whole name and includes any spaces. At the end of this calc you will have a value at [ebp-08]. This value is used later on and is Xor with our serial number we typed in.
 
I will give you an example, you might want to use a hex base calc for this:

Name:   The Headlesschickens
Hex Code for each letter is:  54,68,65,20,48,65,61,64,6C,65,73,73,63,68,69,63,6B,65,6E,73

[ebp-08]=0

Xor first letter with 0, 0 Xor 54 = 54
Xor second letter with value in [ebp-08], 54 Xor 68 = 3C
then  3C Xor 65 = 59 and so on until you have done all the letters of your name. The final result will be stored in [ebp-08].

Mine worked out to be 4A hex using the name, The Headlesschickens

To see this being done just type in SI d ebp-08, Press F10 through the whole routine and watch the data window as you step through the routine. You will now see in the data window the result of each calculation.

After this routine has been through you will follow onto the next piece of code that actually encrypts the first 5 bytes of our name. These 5 bytes are what the encrypted serial will be checked against, so at least we know some of the code manipulation.
What it does is take the first letter of your name and add it to the first letter of your name, then it takes the 5th letter of your name and add it to the first value. Then get the 10th value of your name and adds it to the first value. The amount of times this is done is the (total length of your name divided by 5). So the first letter of your name will be encrpted, you can see this happening by typing in SI d esi, press F10 and follow what happens you will see the first letter of your name change several times depending on the length of your name. It then gets the 6th letter of your name and adds it to the second letter of your name ( this is all in Hex of course), and so on with the 3rd letter and fourth letter and 5th letter until you see your first 5 letters of your name encrpted. While watching the data window at esi just hold down the F10 key and watch the code form before your eyes. Write down the values you see or do a print screen in softice so you know when you come to your main compare what you should be looking for.
 

:0040A5BF 33DB                xor ebx, ebx    zero ebx
:0040A5C1 8D8574FFFFFF        lea eax, dword ptr [ebp+FFFFFF74] ;move user name to eax
:0040A5C7 8945F0              mov dword ptr [ebp-10], eax  ;move address of name
:0040A5CA 8BC3                mov eax, ebx
:0040A5CC 8B55F0              mov edx, dword ptr [ebp-10] ;address of name into edx
:0040A5CF 8BF2                mov esi, edx                ;address of name into esi
:0040A5D1 8D940574FFFFFF      lea edx, dword ptr [ebp+eax-0000008C]
:0040A5D8 3B45FC              cmp eax, dword ptr [ebp-04] ;compare length of name
:0040A5DB 7D0F                jge 0040A5EC
:0040A5DD 8A0A                mov cl, byte ptr [edx]   ;move first letter into cl
:0040A5DF 000E                add byte ptr [esi], cl   ;add first letter to first
                                                       ;letter of name
:0040A5E1 83C005              add eax, 00000005  ;add 5 for comparing with name length
:0040A5E4 83C205              add edx, 00000005  ;move name pointer along 5 letters
:0040A5E7 3B45FC              cmp eax, dword ptr [ebp-04]  ;At the end of the name yet
:0040A5EA 7CF1                jl 0040A5DD    no do again
:0040A5EC 43                  inc ebx   increase ebx,  ;when ebx = 5 means 5 letters
                                                       ;have been encrypted
:0040A5ED FF45F0              inc [ebp-10]             ;point to second letter of
                                                       ;name, next one to be encrypted
:0040A5F0 83FB05              cmp ebx, 00000005   ;have we encrypted 5 letters yet?
:0040A5F3 7CD5                jl 0040A5CA         ;no? well carry on encrypting
:0040A5F5 8D852CFFFFFF        lea eax, dword ptr [ebp+FFFFFF2C]
:0040A5FB 50                  push eax    push the address of serial onto the stack
:0040A5FC E8CF280100          call 0041CED0    ;Heres our get length call again,
:0040A601 59                  pop ecx
:0040A602 8BF8                mov edi, eax     ;move length of serial into edi
:0040A604 33DB                xor ebx, ebx
:0040A606 8DB52CFFFFFF        lea esi, dword ptr [ebp+FFFFFF2C]
:0040A60C 3BFB                cmp edi, ebx
:0040A60E 7E1F                jle 0040A62F

This is setting up for some code manipulation, I get lost after this but I will tell you what I know. At the routine below it tests each value of your serial pointed to be esi with hex 39, which is 9 in the real world, so if it is a number add hex D0 to it, if it is above hex 39 it must be a letter so it goes and adds -20 to the hex value,( just minus 20 from the hex value) then adds hex C9 to it then puts it back where it got it from. In SI do your d esi to see what your numbers change into.

:0040A610 803E39          mp byte ptr [esi], 39 ;compare first serial
                                                ;number at esi with dec 9
:0040A613 7611            jbe 0040A626          ;if  below must be a number
                                                ;go and add (D0) to it
:0040A615 33C0            xor eax, eax
:0040A617 8A06            mov al, byte ptr [esi]
:0040A619 50              push eax              ;push serial onto stack,
                                                ;must be a letter
:0040A61A E815810100      call 00422734         ;minus 20h from the value
:0040A61F 59              pop ecx
:0040A620 04C9            add al, C9   add C9 to value
:0040A622 8806            mov byte ptr [esi], al ;put new value where you
                                                 ;got it from
:0040A624 EB03            jmp 0040A629
:0040A626 8006D0          add byte ptr [esi], D0 ;must be a num, so add D0
:0040A629 43              inc ebx
:0040A62A 46              inc esi                ;point next serial value
:0040A62B 3BFB            cmp edi, ebx           ;are we at the end of the
                                                 ;serial yet
:0040A62D 7FE1            jg 0040A610
 

This next part of the serial calculation uses our value that we created from our name and stored in [ebp-08]. I will just comment the code as best as I can, it then comes to a call where I think the final manipulation takes place, I didn't understand much after that so I hope someone can help me out at a later date with it.

:0040A62F 33DB                              xor ebx, ebx
:0040A631 8D852CFFFFFF            lea eax, dword ptr [ebp+FFFFFF2C] points to our encrpted serial
:0040A637 3BFB                             cmp edi, ebx
:0040A639 7E22                               jle 0040A65D
 

:0040A63B 8A10          mov dl, byte ptr [eax] ;move serial into dl
:0040A63D C1E204        shl edx, 04            ;shift it left 4 times, i
                                               ;think this is the same as
                                               ;serial number * 4, ?
:0040A640 025001        add dl, byte ptr [eax+01] ;add the next serial
                                                  ;value to dl
:0040A643 3255F8        xor dl, byte ptr [ebp-08] ;Xor dl with our value
                                                  ;from our name
:0040A646 8BCB          mov ecx, ebx
:0040A648 D1F9          sar ecx, 1
:0040A64A 7903          jns 0040A64F  jump here
:0040A64C 83D100        adc ecx, 00000000
:0040A64F 88540DBC      mov byte ptr [ebp+ecx-44], dl ;move new value back
                                                      ;into memory
:0040A653 83C302        add ebx, 00000002             ;add 2 to ebx for
                                                      ;compare with serial
                                                      ;length
:0040A656 83C002        add eax, 00000002             ;move serial pointer
                                                      ;along 2 places
:0040A659 3BFB          cmp edi, ebx
:0040A65B 7FDE          jg 0040A63B                   ;are we finished with
                                                      ;the new encrypted
                                                      ;serial

After this just F10 down the listing there are a whole lot of Xor on registers then moving the 0's to different memory addresses. Not to sure of the importance of this. I got lost with the call below
 
:0040A6DB E8499EFFFF      call 00404529
 
I'm sure it has something to do with the final encryption of the serial, anybody who can show me the light on this would be much appreciated
 
:0040A6CE 6A00             push 00000000
:0040A6D0 6800100000       push 00001000
:0040A6D5 FF353C574200     push dword ptr [0042573C] ;Probably the address
                                                     ;for the encrypted
                                                     ;serial
:0040A6DB E8499EFFFF       call 00404529             ;Final manipulation of
                                                     ;serial?
:0040A6E0 83C40C           add esp, 0000000C

This next piece of code below decrypts the code at [esi] which amazingly turns into the first 5 encrpted bytes of our name, I'm not to sure how this relates to anything but maybe it has something to do with the serial manipulation. Just trace through the code with F10 and keep your eye on the data window pointed to by esi to watch your code form when you trace.

:0040A6E3 33DB          xor ebx, ebx
:0040A6E5 BEEEB84200    mov esi, 0042B8EE       ;point to encrpted name data
:0040A6EA A104BF4200    mov eax, dword ptr [0042BF04] ;point to our decrption bytes
:0040A6EF 8A10          mov dl, byte ptr [eax]  ;move decryption byte to dl
:0040A6F1 3016          xor byte ptr [esi], dl  ;type: d esi to see your encrpted
                                                ;name
:0040A6F3 43            inc ebx                 ;bytes form,  they will be the same as
                                                ;the ones that you wrote before.
:0040A6F4 46            inc esi
:0040A6F5 40            inc eax
:0040A6F6 83FB0A        cmp ebx, 0000000A       ;keep decrypting until ebx = 0A
:0040A6F9 7CF4          jl 0040A6EF

The next piece of code and call we come to I also don't know what the point is. What happens is your whole name with the encrypted first 5 letters are pushed onto the stack. Then it pushs your 5 encrpted bytes of your name from the small routine before. In the call all it seems to do is copy the 5 encrypted bytes from the name onto each other. Not to sure why or the importance of it. I have commented it below. Anyway we are almost at our main checking call. The bingo.
 

:0040A6FB 6A05            push 00000005     ;there are 5 bytes to check so push 5
:0040A6FD 8D8D74FFFFFF    lea ecx, dword ptr [ebp+FFFFFF74] ;ecx= address of name
:0040A703 51              push ecx          ;first 5 bytes encrypted then push onto
                                            ;the stack
:0040A704 68E4B84200      push 0042B8E4     ;push 5 encrpted bytes of name onto stack
:0040A709 E862260100      call 0041CD70     ;Copies them onto each other, why???
:0040A70E 83C40C          add esp, 0000000C
:0040A711 8B45F4          mov eax, dword ptr [ebp-0C]
:0040A714 A3F4BE4200      mov dword ptr [0042BEF4], eax
 

Finally we come to the most important part of this tutorial. Lets see what is getting pushed, first of all a 5, we know we are only checking the first 5 encrypted bytes of our name. F10 to you land at 0040A721  52     push edx  , in SI type d edx, we see in our data window our name with the first 5 bytes encrypted, in SI type d 0042BF04 (our last push before the call 0041CF6C), in the data window we see some funny looking hex bytes, write or print screen the first 5 hex numbers. This is what our encrypted name gets compared to so somewhere along the line our serial has turned into these encrypted hex bytes. Before we trace into the call look what follows, there is a test eax,eax usually when you see something like this it means something important is being checked . So what we have after the call is this: If the compare doesn't match which we know it won't then eax will come out at anything but zero, thats bad because we then have :0040A732   0F94C1      sete cl  which will mov a 01 into cl only if eax was Zero, which in our case there won't be a 01 put in cl, then : 0040A735 83E101        and ecx, 00000001,  when we and 01 with 0 we get zero. Then the next command is the most important :0040A738 890D5C574200      mov dword ptr [0042575C], ecx  , move whatever is in ecx into this memory location. This is the memory location that tells if the program is registered. We have seen that a bad compare of our name and serial will end up with a 0 in ecx, thus 0 will be put in this memory location  [0042575C], program unregistered. We want a 1 in this memory location and to do that we have to pop out of the call 0041CF6C with eax set to 0.

:0040A719 6A05           push 00000005                    ;number of times to loop
:0040A71B 8D9574FFFFFF   lea edx, dword ptr [ebp+FFFFFF74];edx= address of our name
:0040A721 52             push edx                         ;push it onto the stack
:0040A722 FF3504BF4200   push dword ptr [0042BF04]        ;push address of our
                                                          ;encrypted serial
:0040A728 E83F280100     call 0041CF6C                    ;Our main checking call
:0040A72D 83C40C         add esp, 0000000C
:0040A730 85C0           test eax, eax                    ;this must be 0 for good guy
:0040A732 0F94C1         sete cl                          ;set cl to 1 if Zero flag
                                                          ;set
:0040A735 83E101         and ecx, 00000001                ;ecx will then be 1 for good
                                                          ;guy
:0040A738 890D5C574200   mov dword ptr [0042575C], ecx    ;move 1, good guy memory location
 
Alrighty then lets trace into this last call and see whats happening and how we can get EAX to come back zero. So F8 at :0040A728   E83F280100      call 0041CF6C         Our main checking call we land here, lets go through it. Basically what happens is the first encrypted serial number is loaded into the bl register, then it is compared with whats at the memory address pointed to by the edx register which is our encrypted name.

It does this until there is not a match or until all 5 encrypted bytes have been compared then it takes the last encrypted serial number and the last encrypted name byte and subtracts them from each other. This will equal zero if we had put in the right serial number but in our case it will be a negative.

So now we know where we have to get our eax to equal zero. When you land at :0041CF79 85C9               test ecx, ecx  , you can type in SI d eax to see what our serial has been encrpted into, d edx to see your name with the first 5 bytes encrpted. If our serial was correct it should have come out the same as the first 5 encrypted bytes from our name.

 
:0041CF6C 55       push ebp
:0041CF6D 8BEC     mov ebp, esp
:0041CF6F 53       push ebx
:0041CF70 8B4D10   mov ecx, dword ptr [ebp+10] ;move 5 into ecx, our loop counter
:0041CF73 8B4508   mov eax, dword ptr [ebp+08] ;address of encrpted serial into eax
:0041CF76 8B550C   mov edx, dword ptr [ebp+0C] ;address of our encrpted name
:0041CF79 85C9     test ecx, ecx
:0041CF7B 751A     jne 0041CF97   ;jump to checking part
:0041CF7D 33C0     xor eax, eax
:0041CF7F 5B       pop ebx
:0041CF80 5D       pop ebp
:0041CF81 C3       ret
 

* Referenced by a C)onditional Jump at Address: 0041CF9E(C)
|
:0041CF82 8A18     mov bl, byte ptr [eax] ;move encrpted serial byte to bl
:0041CF84 3A1A     cmp bl, byte ptr [edx] ;compare it with our first encrpted name
                                          ;byte
:0041CF86 7504     jne 0041CF8C           ;beggar off cracker
:0041CF88 40       inc eax                ;point to next serial byte
:0041CF89 42       inc edx                ;point to next encypted name byte
:0041CF8A EB0B     jmp 0041CF97           ;continue loop

* Referenced by a (C)onditional Jump at Address: 0041CF86(C)
 
:0041CF8C 0FB600   movzx eax, byte ptr [eax]  ;land here if our check failed, then
                                              ;move last
:0041CF8F 0FB612   movzx edx, byte ptr [edx]  ;bytes compared into eax and edx
:0041CF92 2BC2     sub eax, edx   ;subtract them, eax will be minus, it might look
:0041CF94 5B       pop ebx        ;something like this,    FFFFFFAB
:0041CF95 5D       pop ebp
:0041CF96 C3       ret

* Referenced by a (C)onditional Jump at Addresses:0041CF7B(C), :0041CF8A(U)
|
:0041CF97 8BD9     mov ebx, ecx      ;our counter for looping 5 times
:0041CF99 83C1FF   add ecx, FFFFFFFF
:0041CF9C 85DB     test ebx, ebx     ;have we looped five times yet
:0041CF9E 75E2     jne 0041CF82      ;if not equal then compare next byte
:0041CFA0 0FB640FF movzx eax, byte ptr [eax-01] ;move last byte checked into eax and
                                                ;edx
:0041CFA4 0FB652FF movzx edx, byte ptr [edx-01] ;then subtract them from each other
:0041CFA8 2BC2     sub eax, edx  ;if we made it right through the loop they will
:0041CFAA 5B       pop ebx       ;equal zero,   eax = 00000000, good guy.
:0041CFAB 5D       pop ebp
:0041CFAC C3       ret
 
 
The Crack
     
There are many ways we could crack this now, see how many you can try, I have chosen to crack it by making sure it will always continue with the loop even when the encrypted bytes are compared and they don't match.Then to make sure eax will exit the routine with a zero. Heres my patch. I'm not to sure if it is a good one because I have only being doing this for 4 months. Any help from the more experienced crackers would be greatly appreciated.
 

So first at line:

:0041CF86    7504             jne 0041CF8C  beggar off cracker

change the jne to a jump to next line. This will let the program go through the full check of your serial and name.

Now looks like this

0041CF86    EB00             jmp 0041CF88  beggar off cracker

Then at lines:

0041CFA0 0FB640FF       movzx eax, byte ptr [eax-01] ;move last byte checked into eax and edx
:0041CFA4 0FB652FF      movzx edx, byte ptr [edx-01] ;then subtract them from each other
:0041CFA8 2BC2              sub eax, edx

We don't want the movzx lines for subtract because it won't equal zero so just asemble over them with the following.

:0041CFA0      B800000000    mov eax, 00000000      ;mov zero into eax for good guy
:0041CFA5     6640                 inc ax     ;we are five bytes short from original so we
:0041CFA7     90                     NOP       ;need to pad out the extra 5 bytes in a camoflauged
:0041CFA8     6648                 dec ax    ;way just incase the program looks for NOP's

The program will exit the routine with eax = 0 thus it will allow the proper value of 1 to be put in the memory flag area for good guy registered. Remember this is just my own patch here, there are probably heaps of better ones, just experiment and see what happens.
 

Before we make this patch permanent there is just one more thing we have to check. F10 out of this routine too you get back to the routine where a 0 or 1 is put in the main memory area that tells the program whether it is registered or not.

:0040A728 E83F280100       call 0041CF6C
:0040A72D 83C40C           add esp, 0000000C ;return with eax = 0 good guy
:0040A730 85C0             test eax, eax
:0040A732 0F94C1           sete cl
:0040A735 83E101           and ecx, 00000001
:0040A738 890D5C574200     mov dword ptr [0042575C], ;ecx move 1 into
                                                     ;memory location
                                                     ;0042575C

We have to make sure we get out of this whole checking routine with eax = 1 for the program to take it to the Thankyou for your support caption. Usually this will happen very close to the end of the routine so go to your dead listing and have a look where the routine ends, ie: look for the ret opcode. Look up from this and look for the last place where eax is set. You will see below:

* Referenced by a (C)onditional Jump at Addresses:
:0040A765(C), :0040A773(C), :0040A785(C), :0040A797(C)

       ;move what is at memory location 0042575C

:0040A79C A15C574200              mov eax, dword ptr [0042575C]  into eax,

      ;it just so happens to be the memory location that we put a 1 into
      ;for good guy.

* Referenced by a Conditional Jump at Addresses: :0040A51B(U),:0040A558(U)

:0040A7A1 5F                      pop edi
:0040A7A2 5E                      pop esi
:0040A7A3 5B                      pop ebx
:0040A7A4 8BE5                    mov esp, ebp
:0040A7A6 5D                      pop ebp
:0040A7A7 C3                      ret   ;return with eax = 1 for good guy.

So eax is set by whatever is in our magic memory location that the program checks if it is registered or not with a 0 = unregistered and a 1 = registered.

Now we just need to make this patch permanent. I usually go back to W32Dasm and highlight the lines I need to change then write down the offset at the bottom of the screen. Fire Hiew then overwrite the old hex data with the new. Lets go and do that.

Our first patch is at offsett ::0041CF86   in W32Dasm goto this offsett, with the highlight bar on it at the bottom of the screen you will see something like this @offsett 0001C586h in File:WinRAR
Write down the offsett 1C586, this is where we will goto in Hiew.

Then in W32Dasm goto offsett: :0041CFA0     , write down the value after the @offsett at the bottom of the screen, 1C5A0, this is where we will goto in Hiew and write the next part of our patch.

Make a backup copy of Winrar and rename it with an extension that is not .exe. eg: WinRAR95.crk

Start Hiew then highlight our backed up copy of WinRAR.crk. Press enter to load it. Press F4 then Decode, Press F5 then type in our first offsett from W32Dasm ie: 1C586, press enter and we land right where we have to write our first part of the patch. Press F3 for edit then type in EB00 which is hex for jump to the next line. Press F9 to update.

Then do the same again for our next offsett, Press F5 ,type in our next offset ie: 1C5A0, enter, Press F3 to edit then type in our new hex data. B8000000006640906648, Press F9 to update then F10 to exit. Rename the file back to WinRAR95.exe and put it back in the main Winrar directory if it is not already there. Fire it up for your evaluation free version of WinRAR.

For some reason if WinRAR95.exe is not in your main Winrar directory it will still show evaluation copy. I think this has something to do with it needing the rar.ini file which holds your registration information.

Your registration info, that is your name and registration you typed in are kept in the rar.ini file under the heading Registration. Rar.ini is kept in the main WinRAR directory.

 
Final Notes 
    
Well this is my first tutorial, I don't know if I explained it very well because I'm just learning myself. Any help with what are the best tools to write these tuts would be muchly appreciated. If you need help with anything or if you can help me with anything email me at darrin@voyager.co.nz.

I'd like to thank +ORC for his tuts which I am slowly getting through, its good to lie awake at night trying to work out some of his cyptic tutorials.

And +Greythorne I think it is for putting all +ORKs targets on the web, I was almost ready to give up finding even one of his game targets.

And The Sandman for his tuts which are really helping me with Windows stuff.

And the writer of WinRAr, Eugene Roshal for his target. I have now deleted your target off my computer Eugene, I just needed it to unzip some windows help files on API's.

Gimmee (thats my nickname i don't want anything)

 
Ob Duh 
 
Do I really have to remind you all that by buying and NOT stealing the software you use will ensure that these software houses will be encouraged to producing even *better* software for us to use and enjoy.

Ripping off software through serials and cracks is for lamers..
 
If your looking for cracks or serial numbers from these pages then your wasting your time, try searching elsewhere on the Web under Warze, Cracks etc.
   


 
 
 Back to Students Essay's 
 

Essay by:          Gimmee
Page Created: 27th January 1999