F-Secure v4.06
[Reversing essay]

Subject: Cracking
Target: F-Secure v4.06
Author: BlackB
Date: 1999-11-23
Tools used: SoftICE, W32DSM89, HIEW
Difficulty (scale 1-5): 2

Before starting!
This essay is for knowledge purposes only!!
Software developers spend much time in making their programs. They live from the money we give them!
Please buy good software!!
I. Introduction
Hi there again! Welcome to this tutorial, this time for the popular and extremely good (actually the best) anti-virus program in the world. Better than the slow and sometimes buggy McAfee, and the overbloated big Norton Antivirus. If you want good protection which doesn't slow down your system, get it man! It's used in many companies and therefore it's very reliable.
I made cracks for F-Secure 4.04 to 4.06 ... they all got the same protection: the timelock v2.0 . However, we won't crack the timelock protection :) It's not necessary. Enjoy!
II. About the protection
Timelock 2.0 a commercial protection scheme. (includes nag and 30-day trial )
III. Cracking it
As I said, it's protected with the timelock v2.0 commercial protection scheme (which is kinda outdated by now), BUT.....it can't be cracked the usual way (i.e. cracking the timelock dll), because it doesn't uses any serials. I've got a strong feeling it only uses timelock for the 30-day trial. Actually that's the first difficulty cracking it: don't start finding out about the timelock protection, just ignore it :)
If you look to the files that F-Secure installed, there are a lot a lot of .dll and .exe files. Only two of them need to be patched. Follow me how I found out...

When installed, F-Secure displays a nagscreen with the message you can only use it for 30 days and blablabla....with an okay button. I displays the nag when the gatekeeper (resident virus checking prog) is ran and when you run the main program. I decided to start with the nag of the main program. I set all sort of breakpoints in sice that might break on the nag, but none did. After some time i was desperate, but.....there was only one left i didn't use, a rediculous one, the good old MessageBoxA. So I set a bpx on it....and ah, take one goddamned (sorry) guess :) It worked!
Well then press F12 to exit the MessageBoxA procedure until you turn back to the main code....and oh look, it's located in a file "fpwm32". When looking into the f-secure directory you see this files 's named fpwm32.dll: our first file we gotta patch. Note the offset adress where you encountered the messageboxa in sice, disassemble the .dll file and goto that code location....you see this:

--------------------------------------Start-of-partial-code----------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00417B33(C), :00417B7A(C) <- Interesting....two conditional jumps :)
|
:00417B8A 6A40                    push 00000040
:00417B8C 8D45BC                  lea eax, dword ptr [ebp-44]
:00417B8F 50                      push eax
:00417B90 56                      push esi
:00417B91 FF750C                  push [ebp+0C]

* Reference To: USER32.MessageBoxA, Ord:0000h <- The nagscreen
                                  |
:00417B94 E8E3E10600              Call 00485D7C
:00417B99 56                      push esi
--------------------------------------End-of-partial-code------------------------------------
So let's take a look to one of the conditional jumps.....i chose adress 00417B7A :)

--------------------------------------Start-of-partial-code----------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00417B4B(C), :00417B54(U), :00417B66(C) <- Again some conditional jumps
|
:00417B6F 57                      push edi

* Reference To: cw3215._free, Ord:0000h
                                  |
:00417B70 E8E5DC0600              Call 0048585A
:00417B75 59                      pop ecx
:00417B76 837DFC00                cmp dword ptr [ebp-04], 00000000
:00417B7A 740E                    je 00417B8A <- If equal jump to nag
:00417B7C 56                      push esi
--------------------------------------End-of-partial-code------------------------------------

Maybe it was enough to patch the "je" at 00417B7A, but didn't try it.....i checked out adress 00417B4B:

--------------------------------------Start-of-partial-code----------------------------------
:00417B33 7455                    je 00417B8A
:00417B35 837B0403                cmp dword ptr [ebx+04], 00000003
:00417B39 751B                    jne 00417B56 <- If expired then jump

* Possible StringData Ref from Data Obj ->"expiredmsg=0"
                                  |
:00417B3B 68542C4900              push 00492C54
:00417B40 57                      push edi

* Reference To: cw3215._strstr, Ord:0000h
                                  |
:00417B41 E822DE0600              Call 00485968
:00417B46 83C408                  add esp, 00000008
:00417B49 85C0                    test eax, eax
:00417B4B 7422                    je 00417B6F <- if trial then jump for nagscreen
:00417B4D C745FC01000000          mov [ebp-04], 00000001 <- not trial make registered
:00417B54 EB19                    jmp 00417B6F <- jump away from here, we're done
--------------------------------------End-of-partial-code------------------------------------

That's quite clear isn't it :) So what to do to patch?
Change 417B39 into two NOP instructions
Change 417B4B into two NOP instructions

Do that in your favorite hex-editor (mine is HIEW, yours should be too). Run F-Secure main program.....goddamned....the nag is gone, but the prog doesn't start! Ehe, must be a second check. Let's find out what our program does after the "jump away from here, we're gone" jump (see previous code snippet). So in sice, set a breakpoint on it and watch what the prog does :)

--------------------------------------Start-of-partial-code----------------------------------
                                  |
:00417B70 E8E5DC0600              Call 0048585A
:00417B75 59                      pop ecx
:00417B76 837DFC00                cmp dword ptr [ebp-04], 00000000 <- Trial?
:00417B7A 740E                    je 00417B8A <- If trial, then jump to display nagscreen

                                  (it won't jump as ebp-04 will contain "1" after
                                   we applied the patch)
								  
:00417B7C 56                      push esi

* Reference To: cw3215._free, Ord:0000h
                                  |
:00417B7D E8D8DC0600              Call 0048585A
:00417B82 59                      pop ecx
:00417B83 B801000000              mov eax, 00000001 <- of importance, see later
:00417B88 EB1B                    jmp 00417BA5 <- Goto that adress pall

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00417B33(C), :00417B7A(C)
|
:00417B8A 6A40                    push 00000040
:00417B8C 8D45BC                  lea eax, dword ptr [ebp-44]
:00417B8F 50                      push eax
:00417B90 56                      push esi
:00417B91 FF750C                  push [ebp+0C]

* Reference To: USER32.MessageBoxA, Ord:0000h
                                  |
:00417B94 E8E3E10600              Call 00485D7C
:00417B99 56                      push esi

* Reference To: cw3215._free, Ord:0000h
                                  |
:00417B9A E8BBDC0600              Call 0048585A
:00417B9F 59                      pop ecx
:00417BA0 B801000000              mov eax, 00000001

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00417AB4(U), :00417B0C(U), :00417B88(U)
|
:00417BA5 5F                      pop edi <- Heh, we quit this trial-or-not routine
:00417BA6 5E                      pop esi
:00417BA7 5B                      pop ebx
:00417BA8 8BE5                    mov esp, ebp
:00417BAA 5D                      pop ebp
:00417BAB C3                      ret [After executing this instruction....you see this ->]

...........

:00464BD1 E8BF2EFBFF              call 00417A95
:00464BD6 83C40C                  add esp, 0000000C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00464BC5(U)
|
:00464BD9 85FF                    test edi, edi
:00464BDB 7409                    je 00464BE6 <- double check, doesn't seem to jump
:00464BDD 83BDD4FEFFFF03          cmp dword ptr [ebp+FFFFFED4], 00000003
:00464BE4 7517                    jne 00464BFD <- If expired or nag not displayed don't jump

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00464BDB(C)
|
:00464BE6 B801000000              mov eax, 00000001 <- Set expired
:00464BEB 8B9508FFFFFF            mov edx, dword ptr [ebp+FFFFFF08]
:00464BF1 64891500000000          mov dword ptr fs:[00000000], edx
:00464BF8 E91A080000              jmp 00465417
--------------------------------------End-of-partial-code------------------------------------

Hope that's clear :) Only thing we've gotta do is changing:
:00464BE4 7517 jne 00464BFD into...
:00464BE4 EB17 jmp 00464BFD

....and the job is done....at least for the F-Secure main program :) Btw, I know I could have done this in some easier and / or more simple way, but I only explain how I was thinking at the moment i was cracking...it's up to you to improve it, and that is certainly possible :)

Heh, so far so good, now the gatekeeper which is somewhat more difficult, but it uses the same sort of "protection". First thing we gotta know is the file where the second check (that one for the gatekeeper) is located. So I set a bpx on MessageBoxA again, but with the gatekeeper, no result! Okay, so i (accidentally) tried MessageBox (the 16-bit instruction). And ahaa, there our good old sice pops up!

--------------------------------------Start-of-partial-code----------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0011.060B(C), :0011.065B(C) <- You see, also two conditional jumps :)
|
:0011.066E FF7608                 push word ptr [bp+08]
:0011.0671 FF76FC                 push word ptr [bp-04]
:0011.0674 FF76FA                 push word ptr [bp-06]
:0011.0677 16                     push ss
:0011.0678 8D46B6                 lea ax, [bp-4A]
:0011.067B 50                     push ax
:0011.067C 6A40                   push 0040
:0011.067E 9AFFFF0000             call USER.MESSAGEBOX
:0011.0683 EBD8                   jmp 065D
--------------------------------------End-of-partial-code------------------------------------

Now as the segments of this file (dvp95_0.exe) are movable, you can't set breakpoints, or at least, i couldn't manage to set breakpoints on it. Now disassemble the file and goto the messagebox (i found it by searching to "lea ax, [bp-4A]") Then goto the 0011.065B conditional jump.

--------------------------------------Start-of-partial-code----------------------------------
:0011.064B FF76F8                 push word ptr [bp-08]
:0011.064E FF76F6                 push word ptr [bp-0A]
:0011.0651 9AFFFF0000             call 0001.3E99h
:0011.0656 83C404                 add sp, 0004
:0011.0659 0BFF                   or di, di
:0011.065B 7411                   je 066E <- If trial then jump

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0011.0683(U)
|
:0011.065D FF76FC                 push word ptr [bp-04]
:0011.0660 FF76FA                 push word ptr [bp-06]
:0011.0663 9AFFFF0000             call 0001.3E99h
:0011.0668 83C404                 add sp, 0004
:0011.066B E913FF                 jmp 0581 [Let's take a look where this jumps to->]

.............

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0011.0575(C), :0011.066B(U)
|
:0011.0581 B80100                 mov ax, 0001 <- Recognize this from the fpwm32.dll :)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0011.05E2(U)
|
:0011.0584 E9FE00                 jmp 0685 [Let's take a look where this jumps->]

.............

:0011.0685 5F                     pop di 
:0011.0686 5E                     pop si
:0011.0687 8D66FE                 lea sp, [bp-02]
:0011.068A 1F                     pop ds
:0011.068B 5D                     pop bp
:0011.068C 4D                     dec bp
:0011.068D CB                     retf <- Exits this checking procedure

--------------------------------------End-of-partial-code------------------------------------
Good! To disable the nag we have to change:
:0011.065B 7411 je 066E into....

:0011.065B 90 NOP :0011.065D 90 NOP

...but wait!! Remember that I said you can't set breakpoints? Well, we'll need the messagebox instruction to break on and to check if there is a second check (like there was one in fpwm32). So don't patch yet!
So set a "bpx messagebox", enable the gatekeeper, sice pops....and exec until you 've exited the procedure (i.e. when you executed the retf instruction). Now we come in the part where the second check is made, just like in the fpwm32.dll file.

--------------------------------------Start-of-partial-code----------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0002.0327(U)
|
:0002.0336 83C408                 add sp, 0008
:0002.0339 837EDA00               cmp word ptr [bp-26], 0000
:0002.033D 7406                   je 0345 <- Recognize it? 
:0002.033F 837EE203               cmp word ptr [bp-1E], 0003
:0002.0343 7503                   jne 0348 <- Recognize it? This has to jump always

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0002.033D(C)
|
:0002.0345 E922FF                 jmp 026A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0002.0343(C)
|
:0002.0348 89365600               mov [0056], si
:0002.034C 56                     push si
:0002.034D 1E                     push ds
:0002.034E 688419                 push 1984
:0002.0351 680001                 push 0100
:0002.0354 9AFFFF0000             call KERNEL.GETMODULEFILENAME <- Load gatekeeper etc...
--------------------------------------End-of-partial-code------------------------------------

Well that's it :) Change the "jne 0348" into "jmp 0348" :) Everything is cracked! Lazy protection for a 100 $ program, but it is a very good anti-vir :)
IV. In the end

Sorry if this essay was somewhat sloppy, or not very clear, but i'm tired, and i'm typing this in a hurry. I might correct this essay to a somewhat better level...buy hey....if your a real cracker, you'll manage! Oh yea, before i forget, when you startup the F-Secure mainprogram you have that annoying tips window. Disable it to make a file called f-protw.ini with following content:
[TIPS]
dontshow=1

Also, can be easily found out.....but that's up to you...cracker! ;)

Greets goto MMke, hatez goto BSA and SPA!
BlackB

Endnote:
Essay written by The Blackbird © 1999-2000
This essay can be freely distributed/ published/ printed etc... as long as no modifications are made.