Crack NetFor2 v1.0 by juicyfruit^drn

The purpose of this tutorial is to teach you something about message boxes. NetFor2 is a good example of how to get around a message box.

The problem in this program isn't the timer but the messagebox. I won't spend much time explaining how I found the timer because it's not the purpose of this file, but I will show you where to find it and skip it.

I looked in WDASM 8.93 (windows disassembler) to see what they used as a timer. Look under the IMPORT MODULES section. It uses the function 'GetSystemTime' and it does what it says.

Set a breakpoint on it and start NetFor2 and SoftIce will break then press F5 once and then follow the code till you get to the last jump before the last call to the error message. Then change the jump and it will skip the timer. I patched it at 00401E22 and changed the jbe 00401E44 to jmp 00401E44 (just change the first byte to EB).

The program also checks to see if you have set the time back after you started your trial period. Just find the error message in W32Dasm' string reference and scroll a little back to the first jump you see and reverse it. I patched it at 00401D80 and changed the first byte to EB.

The messagebox in the beginning (the nagscreen) uses the same procedure as the messagebox in the end. The messagebox in the ending is a part of the program and the messagebox in the beginning is the nagscreen. Not a part of the program if you're a cracker :).

We can't just force the program to skip the messagebox because the messagebox in the beginning and ending is different from each other. You'll notice that almost all messageboxes look the same in all windows programs.

In programming each messagebox has it's own standard code. example, a messagebox with an OK button in it has the code (?)48 and a messagebox with two buttons like OK and Cancel has the code 78 or whatever. Because of this, messageboxes uses the same procedure as I'm about to explain (except if the messagebox is made specially but very unlikely).

The first messagebox (nagscreen) only have an OK button. If you set a breakpoint on 'bpx MessageBoxa' before you start the program and then run the program it will break into Softice. Softice breaks on the messagebox in the memory where the code is currently being executed. Notice the high memory address :BFF5412F or whatever it is. We don't want to be here. Press F11 to get to the real code (the caller).

Usually the program will break right into the code where we want to be but not when you are breaking on a messagebox because the messagebox expects some input from the user (that's you). Once you have pressed F11 the program will exit Softice and pop the messagebox with the OK button and wait for your input. If you press the OK button, Softice will pop up again because you gave it some input.

You should be looking at this code :

* Reference To: USER32.MessageBoxA, Ord:0195h
                                  |
:00423AB5 FF15643A4800            Call dword ptr [00483A64] 
:00423ABB 5F                      pop edi   <== This is where you are
:00423ABC 5E                      pop esi
:00423ABD C20C00                  ret 000C

This function 'MessageBoxa' will put your input into the register EAX. Check and see what the register EAX says. EAX should be 1. This means that when you press the OK button EAX equals 1 and then the program can remove the messagebox.

Now press F5 (or CTRL-D) and it will exit SoftIce. Now if you exit NetFor2, SoftIce will break again because another messagebox will pop up. Press F11 and the messagebox will pop up but this time with two options, Yes and No. Press a button to get back into SoftIce. Notice the memory address. The address is the same as the messagebox before.

Usually a program uses a new messagebox for each message. This is the reason why we cant just jump over the messagebox. That would give an error message. If you check EAX you can see that it's different from the first messagebox. EAX is 6 if you pressed Yes and 7 if you pressed No.

What we want the program to do, is to skip the first messagebox (nagscreen) and let us choose if we want to exit the program in the second messagebox. First thing to do, is to go a little back in the code. Just scroll up right before the messagebox and you should be looking at this :

:00423A8F 85FF                    test edi, edi
:00423A91 7508                    jne 00423A9B
:00423A93 E8C5400000              call 00427B5D
:00423A98 8B7810                  mov edi, dword ptr [eax+10]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00423A91(C)
|
:00423A9B E86A3D0000              call 0042780A
:00423AA0 85F6                    test esi, esi     <==== These are *
:00423AA2 7504                    jne 00423AA8      <==== the bytes *
:00423AA4 33C0                    xor eax, eax      <==== we are    *
:00423AA6 EB03                    jmp 00423AAB      <==== about to  *

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00423AA2(C)
|
:00423AA8 8B461C                  mov eax, dword ptr [esi+1C] <=== change *

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00423AA6(U)
|
:00423AAB FF742414                push [esp+14]
:00423AAF 57                      push edi
:00423AB0 FF742414                push [esp+14]
:00423AB4 50                      push eax

* Reference To: USER32.MessageBoxA, Ord:0195h
                                  |
:00423AB5 FF15643A4800            Call dword ptr [00483A64] 
:00423ABB 5F                      pop edi   <== This is where you are
:00423ABC 5E                      pop esi
:00423ABD C20C00                  ret 000C

I don't know exactly what the call at 00423A9B contains but it's probably determine which of the messageboxes to show.

It's not relevant to our problem, all we need to do is to change eax to 1 when it starts up and 0 when it closes. As we found out in the beginning the program waits for the user to push the button and when the OK button is pushed EAX is set to 1. What I did (there are many ways to do this) was to look for a value in any of the registers that were different when you closed the program, and when you opened the program.

I found ESI and EBX. TEST performs a logical AND of the two operands updating the flags register without saving the result. Those bytes I marked with a * is the bytes I changed into this :

:00423A9B E86A3D0000 call 0042780A
:00423AA0 85F6       test esi, esi <==> 33C0 xor EAX, EAX
:00423AA2 7504       jne 00423AA8  <==> 85F3 test EBX, ESI
:00423AA4 33C0       xor eax, eax  <==> 7505 jne 00423AAB
:00423AA6 EB03       jmp 00423AAB  <============> 83C001 add EAX, 00000001 
:00423AA8 8B461C mov eax, dword ptr [esi+1C] <==> 90     nop
						  90     nop

In WDASM it will look like this now :

:00423A91 7508                    jne 00423A9B
:00423A93 E8C5400000              call 00427B5D
:00423A98 8B7810                  mov edi, dword ptr [eax+10]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00423A91(C)
|
:00423A9B E86A3D0000              call 0042780A
:00423AA0 33C0                    xor eax, eax      *1
:00423AA2 85F3                    test ebx, esi     *2
:00423AA4 7505                    jne 00423AAB      *3
:00423AA6 83C001                  add eax, 00000001 *4
:00423AA9 90                      nop               *5
:00423AAA 90                      nop               *6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00423AA4(C)
|
:00423AAB FF742414                push [esp+14]
:00423AAF 57                      push edi
:00423AB0 FF742414                push [esp+14]
:00423AB4 50                      push eax

Now I'll explain what I did :
*1 set EAX to 0
*2 it checks to see if EBX is 0 or higher.
*3 if EBX is 0 don't jump, if EBX is higher jump
*4 add 1 to EAX (EAX + 1)
*5 No operation (just to fill out the last bytes I didn't use)
*6 No operation

When the program starts up EBX is 0 and it will set EAX to 1 thus skip the nagscreen. When you close the program EBX is higher than 0, and it will jump to 00423AAB and EAX is 0 thus wait for a reply from user.

Everything I have said in this tutorial might as well have been done another way. There is several different ways of doing this. This isn't supposed to be a manual about cracking but a source of inspiration (hopefully). This is the way I do it and I do it this way because I think it's the easiest way. I change my opinion all the time because I learn new stuff all the time. In a month I'll probably have found an easier way to crack this.

Have fun.

Congrats partner you have read my tutorial :0)

-JuicyFruit^dRN