RingZ3ro - How to crack Conseal PC Firewall

Author : NeuRaL NoiSE, 18/08/1999


SoftICE v4.x, BoundsChecker v6.01, Hiew v6.15
ProcDump v1.5, OpGen v1.0b, TASM v4.1


It's quite some time that I don't crack anymore, like my friends know, I prefer to dedicate to the (imho) much richest, more interesting and intriguing Reverse Engineering scenario, meanwhile, during a chat and a nuke to a friend I happened to notice that my precious firewall (Conseal PC Firewall, I think it's one of the best ones) goes down. License has expired.

Typical background for a common quick crack (I haven't been settling for long cracking sessions for quite a while...), neverthless I soon realized that there were some good aspects that led to something nicer than a plain serial or a jz/jnz check. Let me just say that this tutorial will be as short as possible (not for the fact that it's 4.30am here and I'm quite tired, but because I don't really want to flood you with tons of text....let's try.

The Crack

Ok, this is the story.

The program, once expired, and once ran, doesn't make you suspect anything, when, after like 2/3 seconds, a nag tells us that we have finished our time. I'm using version 1.37. As I was saying, there's a nag, but we won't break on MessageBoxA, we said we wan't to have fun, no usual stuff. So let's open BoundsChecker and launch frw.exe, being careful to monitor all the API's used. If you are careful enough and collapse every thread created at the start of the program, you'll notice 6 initial threads and, right before the nag pops, the creation of a seventh thread. Interesting, let's take a look at this 7th thread.

You'll notice an overwhelming amount of registry poking, querying and so on, well nothing strange, nothing changed, as Bob Marley put it. But let's take a look at the values being checked, you'll notice a certain repetition of LicenseInfo, LicenseID etc. Let's open regedit for a second and look for LicenseID, a nice trio of interesting keys, LicenseCode contains probably the encrypted version of the installation date, LicenseID has a default string for our universal license, LicenseInfo with various unidentified stuff, what are we going to do?, a couple of bpm's, looking for the decrypting routine, and we write our crack?, NO :-).

We said in an unusual way...so let's close regedit (I'll reserve the decrypting routine for the next time, might be an interesting algorithm)... anyway, as we were saying, let's come back to our 7th thread, re-popping BoundsChecker again. Browsing a bit downwards among the API calls, we'll reach a zone where a heap gets allocated+freed, then what's that GetLocalTime, yup, it's this easy... GetLocalTime gets the current date and hour... then it's obvious that the program decrypts the LicenseCode key, gets the installation date, and then makes his calculations.

What are we gonna do? we could patch the checks in a quick and dirty way, but we talked about having fun. Let's close BoundsChecker after a quick look at the rest of the (useless) API calls... open the file with Hiew... a little surprise for us, there's a .WWP32 section... the file is packed with WWPack32... ProcDump unpacks it I think... but we are hard headed... we want the packed file, which is cooler and less space-consuming :-), at this point a little pervert thought crossed my mind... let's see... GetLocalTime. Gets year, month and day... I installed Conseal the 17th of July 1999... if I make him believe that it's always the 18th of July 1999 we'll all live in peace... it would be interesting, but how to do it?, the solution is easy... a IAT hook that intercepts every GetLocalTime call and that fakes the result... easy to do, just that the file is packed, so the problems are basically 2 :-

i). How to install the hook, and...
ii). Two, WHERE to inject the hooking routine...

Well, installing the hook is as easy as smoking a cigarette, neverthless the situation was interesting and I thought I'd keep walking this path :-). IAT hooking is basically, really easy in the concept. I assume that the reader has a medium knowledge of the PE structure, and that he/she knows what an Import Table is... if not, may I suggest you read some good docs, the best ones are imo Pietrek's and Luevelsmeyer's.

Now, we know that in the Import Table there's an array called FirstThunk, which gets patched at runtime with the addresses of the functions that the program imports... the concept of IAT hooking is based on this :- you retrieve the spot that concerns the function we want to hook, and you patch the VA of our hooking routine inside it. This done, when the program will call the function (and thus will pass for the deviation inside the Import Address Table (aka FirstThunk array)), instead of running straight towards the kernel woods, it'll run towards our injected routine's lair... at that point we'll quietly examine the passed params, we forward them to the kernel, or we keep them, or we reset the system, or we make a window pop up saying something or whatever else pleases us. Well, you got it. Obviously, we can as well fake the result of a call, in our case GetLocalTime, returning to our dear friend frw.exe the perpetual date of 18th July 1999.

There's a problem anyway. The file is packed... how and where to inject a hooking routine?. Well, the first idea that popped in my mind was writing a small hooker .exe, then, from within a memory patcher (unavoidable as we'll see) mapping it into memory and access to it from the unpacked process... easy to do since MMF's are mapped in the shared region of the linear address space, thus we wouldn't need any additional context switching routine etc... but then I thought, is it really worth it? let's make something quicker. I wanted to physically patch the routine inside frw.exe, and there was only one place safe from the fury of the storm caused by a decrypting stub that devastates the initial image of the file with his mathematcally cold decompression/patching... I'm talking about the so called caves... this term is particularly familiar to virii writers... caves are those empty spaces (in reality filled with 00-bytes) inside a PE file, in other words 'dead' spaces you can use for any code injection purpose... in our case, not viral code but a nice hooking routine.

Which cave are we going to use?, well, I'd say that the one between the Object Table and the first section's raw data will do fine... open the file with Hiew, just to make an idea... after the stub (this program can't be run in DOS mode) and the PE,0,0 signature we get the first file header data, then the optional header etc... browsing downwards we find the object table (.text with the relative data, .rdata with its data etc...) ... then we have a succession of zero bytes (our cave) starting from offset 268h and finally we get to .text section at offset 1000h... all this space isn't used/relocated/modified at all, by WWPack32's loader... now you have an idea of what we're going to do... you choose whether to keep reading or to destroy this htm file.

So..so... what do we need now?. Well, considered that we have to install a IAT hook, we need the decrypted image of the file.. in reality we have a 'notionistic' need of a couple of virtual addresses, that we'll be able to stick as patchspots from a memory patcher, even if the file we'll use will always be the packed one... so we open ProcDump, and we start Conseal... as soon as the process has been fired, press the right button inside ProcDump's tasklist and select Refresh list... here comes a new process, frw.exe... Quickly, right button on the taskname and then "Dump (Full)"... save the dump in a file, and close frw and ProcDump.

That file contains the image of frw.exe exactly as it appears once mapped+decrypted... now the problem is climbing to the import table, and then dwelling inside it until finding the FirstThunk array's dword relative to GetLocalTime's address... and this implies a DAMN BORING (at least for me) search... so what do we do? well, some time ago I got really sick of this situation (I had to face it every time I wanted to patch an API call inside a process... which is a rather common thing when you reverse programs, and I had to manually look for the spot in the IAT), so I decided to write a small tool, that I called OpGen, which contains another quite useful function too, it pratically generates opcodes for patching far jumps, only given the starting and the destination VA/RVA (Hiew sucks when it comes to far jumps)... but we're not interested in such feature, neverthless the little IT scanner that I put into it is useful here, it gives you the patchspot for every function in a snap... seen that I included it in conseal.zip, open it and choose Lookup Imports for patching... select our dumped file and what you'll get (among other things) will be this :-

GetLocalTime == CALL DWORD PTR [46459C]

Interesting, that ([46459C]) is the place where we'll stick the address of our hooking routine. Here we are at the point where we face the need of a memory patcher. Having to patch the hook inside the decrypted image of the file, let's open our dear UltraEdit with Tasm support (tm) and let's begin writing down some code.

.model flat, stdcall

extrn   ReadProcessMemory   :PROC
extrn   WriteProcessMemory  :PROC

include win32.inc

        exe_name            DB      "frw.exe",0
        processInfo         PROCESS_INFORMATION     <>
        ini_info            STARTUPINFO             <>

        iat_hooking_routine DD      04002A0h ; VA OF THE HOOKING ROUTINE (IN THE CAVE BETWEEN 
                                             ; THE OBJECT TABLE AND THE .TEXT SECTION).
        funct_va            DD      0
        dummybuffer         DB      0

        call    CreateProcessA, OFFSET exe_name, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS,0 ,0 ,OFFSET ini_info,OFFSET processInfo
        test    eax, eax
        jz      @@end

; we'll wait for frw.exe to be loaded and unpacked with a little loop (even if we're not able to hook every GetLocalTime 
; there's no problem, the ones we effectively need are the ones in the 7th thread, remember).

        mov     ecx, 100000000
        .WHILE  ecx != 0
          dec   ecx

; we retrieve the effective address of GetLocalTime in the kernel directly from the IAT of the unpacked process.
        call    ReadProcessMemory, [processInfo].pi_hProcess, 046459Ch, OFFSET funct_va, 4, OFFSET dummybuffer

; now we patch this address in a dword (@ 4002dd) that we'll call from the hooking routine when we want to call GetLocalTime.
        call    WriteProcessMemory, [processInfo].pi_hProcess, 04002DDh, OFFSET funct_va, 4, OFFSET dummybuffer

; and finally we'll effectively install the hook in the FirstThunk array, modifying the address that the program will 
; call inside the IAT with the address of our function (in the iat_hooking_routine dword).
        call    WriteProcessMemory, [processInfo].pi_hProcess, 046459Ch, OFFSET iat_hooking_routine, 4, OFFSET dummybuffer

        call    ExitProcess, 0  ; our job is done... now everything is in the hooking routine's hands.

end     start

At this point, once we compiled the program we'll have our memory patcher that creates the process, waits a bit, then retrieves GetLocalTime's address from the IAT, then patches it inside the hooking routine, and in the end installs the IAT hook in the decrypted image of the program. Now we only have the problem of the hooking routine. What do we need to put inside of it?.

Enter SoftICE and put a bpx getlocaltime... Start conseal pc firewall, and press f12 at the first pop. Write DD and then D ESP-4. This will show you the address that has been pushed on the stack before the call GetLocalTime (you can also find it by tracing through kernel until that "mov ecx, esp-c" (the fifth codeline in the function) where you'll find, in ECX, the same address. Anyway, as I was saying, type "d address" and you'll get the dump of the SYSTEMTIME structure, that gets filled with data concerning current time and date. Let's take a look at it's definition:

typedef struct _SYSTEMTIME {  // st
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;

Remember that we have to make the program believe that it's always the 18th of July 1999, in other words we have to modify the first, second and fourth Words in the structure... making them respectively 7CFh (1999 dec), 7, and 12h (18 dec)... if you want a closer look at the struct, give a DW and then analyze it... you'll see how easy this concept is.

So, let's make a summary. What will happen is this :- the program will call the IAT thinking that it's calling GetLocalTime, while the control will be passed to our hook routine (at 04002A0h)... at that point our situation will be this :- we'll save EAX pushing it and then [ESP+4] will hold the return address for the program's code, and we'll save it in a physical dword to call afterwards for the return (the same thing we did from the memory patcher for GetLocalTime's address)... then we'll pop EAX and we'll increase the stack pointer by 4 bytes... at that point [ESP] will point to the SYSTEMTIME structure... so we'll effectively call GetLocalTime... at the return, we'll have, in [ESP-4], the address of the SYSTEMTIME structure, and we'll start modifying it... but first we'll save the value of EAX in a third physical dword (we can't push it because often, if you analyze the code flow with SoftICE, the VA of the structure is dangerously close to the stack pointer, so a badly placed push could ruin the struct and crash the program) and we'll stick the VA of the struct inside it... at this point, we'll modify the words relative to year, month and day, then we restore EAX and we jump to the return address, that we saved at the beginning of the routine.

Now let's write the code... open Hiew and go to offset 2A0h (that'll become 4002A0h as soon as the file gets mapped and the imagebase gets added), and inject our hooking routine :-

push eax ; save EAX
mov eax, [esp+4] ; return VA in EAX
mov [4002E3h], eax ; we save it in a variable X
pop eax ; restore EAX
add esp, 4 ; [ESP] points to the SYSTEMTIME structure
call dword [4002DDh] ; == call GetLocalTime
mov [4002E9h], eax ; save EAX in a variable Y
mov eax, [esp-4] ; EAX holds a pointer to the structure
mov word [eax], 07CFh ; WORD wYear
mov word [eax+2], 07h ; WORD wMonth
mov word [eax+6], 012h ; WORD wDay
mov eax, [4002E9h] ; restore EAX from variable Y
jmp dword [4002E3h] ; back to .text via the variable X

Once you've done this, you can run our memory patcher, and everything will work perfectly... your Conseal PC firewall will never expire again, and we made something unusual for sure... I had some fun, what about you? :-).

Final Part

A greeting to all my ring0 and #cracking4newbies fellows is a must.

Indeed I put one but 1034 persons complained that I hadn't greeted them (my mind is weak, mostly early in the morning... or should I say late in the night?), so I democratically decided that I'd just leave a melancholy shade and I'd greet EVERYONE that knows he is being greeted :-).

Other stuff written by me can be found at http://neudump.cjb.net.

NeuRaL_NoiSE 1999