VBox 4.2 - A generic crack explained

No more hairs on WeiJunLi's head !

Written by +Tsehp

You first have to read all the previous essays about VBox to understand this one. Those are written by marigold who first discovered the way to beat the first versions and the ancient timelock.


I will not explain what VBox is, it is actually used by Symantec and others. This ready made commercial protector was easy to beat in the past and this time, the author WeiJunLi seems to have learned a lot ! What is new though :-

1. Global check of vboxt420.dll injected in the executable, so you can't write a global crack by distributing this cracked dll, you have to manually patch the protected executable at first.

2. Multiple auto-decrypts of the code in several places in memory, run time memory patches are FINISHED!.

3. The license file and all the dlls are located in systemroot\vbox\. This license file allows prolongations of trial or number of executions. Buy options included.

4. You still can't dump your executable from memory to restore virginity, it uses crypted parameters at run time.

Tools required

Windows NT 2000 (should also work on Win98).
SoftICE 4.0.
Hex Editor.
FrogsICE (for the anti-SoftICE checks).

* A more devious brain than WeiJunLi. That helps.

Target's URL/FTP

http://www.previewsystems.com - Just to download the VBox builder.


I used VBox Builder to protect ProcDump, the purpose was to write a method that could work on any program protected by VBox, remember that I'm on WinNT so the memory locations of the listings could be slightly different.

First Part : Allowing the patches

If you want to make this work, you'll have to patch vboxt420.dll. I first tried a local APIspoofing and it was not working. The purpose is simplistic you have to patch this file when it is loaded,the previous version was possible too by using API spoofing at level, I mean modifying the file import table values to redirect the API call to your routine, but this time it's not possible, because the entire file integrity is checked by your VBoxed executable and not in vboxt420 at first.

But what does the executable need ? API's ! So we'll patch the windows API's themselves to redirect the flow to the patching routines. Where to put those routines ? In your VBoxed executable at the beginning of your file in the places where thay are not used. I will not explain this in detail, it's been done in other essays re: API spoofing. Well WeiJunLi, you can check whatever you want, but you just can't check the operating system, so we'll have to patch windows in memory, just at the time the program does this call.

To understand this technique that I will not explain, read iceman's essays. An explanation of what I've done :-

I deviate the first instruction to 43D7A0, patching one of the few not crypted imports (getprocaddress) that was at ProcDump's memory location 428298, so at the first call to getprocaddress, it goes to this address. I want to intercept the call to getprocaddress, I remove the memory write protect by a call to virtualprotect. I patch window's getprocaddress so it goes back to my ProcDumps writings and when we don't need it anymore we put the good values back to the API, it could be used by other programs :-) AND IT WORKS !!! Just think of all the possibilities of this wonderful method discovered by iceman. The protected programs will NEVER be able to detect a sudden patch to windows.

Second Part : Anti-SoftICE routines...

Since VBox 4.1, this protection checks for the memory presence of SoftICE. The essay about VBox 4.1 gave you a way to avoid the check but the check was not explained by the author. SoftICE can be triggered by another process, this process does the following :-

B81109 MOV AX,0911 ; execute command.
8B17 MOV DX,[BX] ; ds:dx point to the command (see below).
BE4746 MOV SI,4647 ; 1st magic value.
BF4D4A MOV DI,4A4D ; 2nd magic value.
CC INT 3 ; Int call.(if SIce is not loaded, jmp)

Whats happening? if SoftICE is loaded, the int 3 call is not executed by the processor to the IDT corresponding table because SoftICE triggers it. In VBox scheme, they used the same, the int 3 is a "must do" call for vboxt420 to continue its execution. If SoftICE is present, the int 3 triggers and VBox detects

How could you find the place to patch ? you could search for BE4746 for example in vboxt420 but no way, just not present. This could be too easy for sure ! WeijunLi knew that, he did the following : just before VBox needs this routine : it allocates some memory with VirtualAlloc, decrypts a part of its code and puts it in memory, executes it and then deletes it with a good VirtualFree... well done. Not resident in memory and crypted inside vboxt420.

But he made a terrible mistake : there are other debuggers on the market and he could not trick all of them. So I used Windebug from Microsoft to find this int 3 location. Just putting a breakpoint on int 3 and it stopped just in the middle of this stealth tricky routine. How to defeat this ? just change one of the magic values and SoftICE doesn't trigger anymore.

Third Part : A look at the protection

Well you've got all the old protections (see precedent essays), we have more memory integrity tests -> We'll have to patch this program just at the right time, by the use of counters and remove the patches just after (same as 4.10). So what's new ? I first applied all the old 4.1 tricks and the program crashed with a page memory error. I looked at what created this error and it's due to a decrypting routine with no end, so the memory access creates the crash. What is decrypted ? Well I saw in memory the first parts decrypted :-


This routine located around 7011C78 just decrypts the VBoxed import table, good at the first time and bad at the second, well you can believe me those guys did their job very well, they use a random key to decrypt this, it took me a very long time to find how and where and I will not detail how I found this, just try with under 30 days and above the time limit and use memory tracing techniques with SoftICE.

I traced the key, it's changed several times, crypted and decrypted, since the beginning of the program execution so I lead you directly to the key creation. The program uses the *.lic file to generate a good and a bad key....But the terrible mistake they make is that they couldn't avoid the good key generation when you're after the time period. At this point, a subroutine just chooses between the two keys if you're above or under the time limit :-

Called by 7032E22, at the second time we look at :-

703CD4E CALL 703fb40

In ebx+9e9 the memory location of the actual key and in ebx+9e9+4 the memory location of the good key. Those keys are generated after this call (this routine is called very often in VBox for other purposes), so exchange the keys only after the second call from 7032E22. If you invert the keys at this time, the program will we decrypt his import tables and work correctly.

ONE VERY STRANGE FEATURE :- After the first time you invert the keys, VBox re-generates a lic file and at the other times the good key will be generated every time even after the time limit ! Well I take that as a reconnaissance for the crackers, just to ease a little their work !.

Fourth Part : The patching

In the last essay about VBox , Victor Porguen made a successful patch inside the VBox dlls, in a part that was not checked, now this is kind of impossible because all the file is checked. Well at this point, you understand that it would be pretty difficult to do a generic crack inside vboxt420.dll. But the generic method I'll explain next should work on every program protected by it.

The patch will work like a virus, first at the start point of your VBoxed exe (procdump.exe in my example), you put a jump to your patching routines, this just will be replaced after the first patches by the original code (to fool the memory checks) and you will jump back to the starting point. This exe doesn't check itself on disk.

In our case :- procdump.exe entry point is 4221BC.

//******************** Program Entry Point ********

:004221BC E9DFB50100 JMP 0043D7A0 *** This is replaced on the file, as a jump to our 
                                      patching routines. What was first
                                      is replaced in my program.

First part of my program, explained line by line. Literal explanations will follow :-

:0043D700 6890D74300 PUSH 0043D790 * This location contains 'Kernel32'.
:0043D705 E86595A577 CALL KERNEL32!GetModuleHandleA * Get a valid handle for kernel32.
:0043D70A A380D74300 MOV [0043D780],EAX * Save this handle.
:0043D70F 6870D74300 PUSH 0043D770 * This location contains 'GetProcAddress', watchout 
                                    it's case sensitive.
:0043D714 50         PUSH EAX * As an argument to have the address of GetProcAddress API.
:0043D715 E80B6AA577 CALL KERNEL32!GetProcAddress * This returns in EAX the address 
                                                   of GetProcAddress.
:0043D71A A384D74300 MOV [KERNEL32!GetProcAddress],EAX * Save address in 43D784.

What am I doing?. I need several parameters concerning the API function I want to patch. In windows those functions are memory protected, so if you attempt to patch them directly you will produce page faults. You can use an API called VirtualProtect to remove (and put back) the memory protection, so you can patch Windows in memory.

The purpose is to force the GetProcAddress function to return to our program everytime it will be called by VBox, so we don't have to first patch the files on disk or in memory.

VirtualProtect() needs 4 parameters :-

1) Address of memory to tweak.
2) Size of memory.
3) A protection flag (meaning read / write / execute rights).
4) A memory location where this function will put the old protection flag (use it when you're finished).

:0043D71F PUSH 0043D78C * Param 4 contains 0 in memory in our case.
:0043D724 PUSH DWORD PTR [0043D788] * IMPORTANT I'm on NT, the flag is 0x40.
:0043D72A MOV EAX, 00004096 * Size of 4096, large enough to patch 5 bytes ;-).
:0043D72F PUSH EAX * Param 2 pushed.
:0043D730 PUSH DWORD PTR [KERNEL32!GetProcAddress] * Param 1 pushed (result 
                                                   in 43D784 of the code above).

:0043D736 E8BC0DA577 CALL [KERNEL32!VirtualProtect] * Well the memory is write enabled, 
                                                    so we can patch it.

:0043D73B A184D74300 MOV EAX,[KERNEL32!GetProcAddress] * Get address of the API.
:0043D740 C700E925965A MOV DWORD PTR [EAX],5A9625E9 * Patch Win API with 5 bytes, those 
                                                    bytes in my case, mean unassembled 
                                                    JMP 43D74F in the beginning of 
                                                    GetProcAddress in memory.

:0043D746 C6400488 MOV BYTE PTR [EAX+04],88  * End of the patch.
:0043D74A E9D669A577 JMP KERNEL32!GetProcAddress * Go back to the real Win function to 
                                                 continue the program execution we land 
                                                 just in 43D74F.

We will land at this point now every time the GetProcAddress function is called :-

:0043D74F FF0500D84300 INC DWORD PTR [0043D800] * This variable is a counter.
:0043D755 813D00D84300B0010000 CMP DWORD PTR [0043D800],000001B0

* This value means the GetProcAddress function needs to be called 0x1B0 times for my 
program to go to 43D7C1 (just to let vboxt420 decrypt itself).

:0043D75F 7460 JZ 0043D7C1 * If GetProcAddress was called 0x1B0 times, we go there.
:0043D761 55 PUSH EBP * All of these are the normal first instructions inside 
                      GetProcAddress crushed by my patch, you sure have to execute them
                      for it to work fine.

:0043D762 8BEC MOV EBP,ESP
:0043D764 51 PUSH ECX
:0043D765 51 PUSH ECX
:0043D766 E9BF69A577 JMP 77E9412A * Continue in $GetProcAddress+5 (the patch was 5 bytes).

:0043D7C1 C7052541E977558BEC51 MOV DWORD PTR [KERNEL32!GetProcAddress],51EC8B55

* We don't need the patched API GetProcAddress so we put back the original values.

:0043D7CB C6052941E97751 MOV BYTE PTR [77E94129],51
:0043D7D2 E9B52AFCFF JMP 0040028C * Jump to the second part of my work.

The purpose of all this was to wait for vboxt420.dll to self decrypt in memory, GetProcAddress was called 0x1B0 times, this value was calculated for us to be able to patch vboxt420 after his first memory integrity checks, we had to wait just for the right moment, I mean patch the code just before it is used, and put it back the way it was just after its execution.

Next we have to deal with the VBox call to DialogboxParamA, this protection is already explained by V. Porguen on the VBox 4.10 essay (porvbox.htm). I just reproduced what he did, in summary make the window procedure believe dialogboxparama is finished and set EAX to 0 when the call returns.

Second part, we land here :-

:0040028C A1BC5A0807 MOV EAX,[07085ABC] * Put in EAX the table import address of 
                                        DialogBoxParamA of vboxt420.dll.
:00400291 A304D84300 MOV [USER32!DialogBoxParamA],EAX * Save this address in 43D84D.
:00400296 C705BC5A080776034000 MOV DWORD PTR [07085ABC],00400376

* Patch the table import so when VBox will call DialogBoxParamA, it will land in 400376.

0008:004002A0 C7054ECD0307E963353C MOV DWORD PTR [0703CD4E],3C3563E9

* Remember 703CD4E ? this is the place where VBox generates the decryption keys. I patch 
this address to force VBox to JMP to 4002B6 everytime 703CD4E is called.

:004002AA C60552CD0307F9 MOV BYTE PTR [0703CD52],F9 * End of patch.
:004002B1 E96F3EA977 JMP KERNEL32!GetProcAddress * Go back to normal prog execution.
:004002B6 6681FE7E4D CMP SI,4D7E * A call to 703CD4E occured! so the flow lands here. 
                                 When the keys are created, SI always contains 4D7E so 
                                 we test this.
:004002BB 740A JZ 004002C7 * We go there if we're in key creation state.
:004002BD E87EF8C306 CALL 0703FB40 * Original first statement of 703CD4E.
:004002C2 E98CCAC306 JMP 0703CD53 * Go back to VBox 703CD4E+5.
:004002C7 891DE4D74300 MOV [0043D7E4],EBX * We save EBX, this is a pointer to 
                                          retrieve the keys after the next CALL.
:004002CD E86EF8C306 CALL 0703FB40 * Generate the keys.
:004002D2 A3E0D74300 MOV [0043D7E0],EAX * We save EAX, to restore it to its original 
                                        state after our statements.
:004002D7 891DE8D74300 MOV [0043D7E8],EBX * Same with ebx.
:004002DD EB0D JMP 004002EC * Jump to the CRACK part :-).

:004002EC 8B1DE4D74300 MOV EBX,[0043D7E4] * Lets restore the keys pointer 
                                          (before the key creation).
:004002F2 8B83F1090000 MOV EAX,[EBX+000009F1] * EAX contains the address of the 
                                              good key.
:004002F8 8983E9090000 MOV [EBX+000009E9],EAX * THE CRACK ! put the good key 
                                              over the bad one.
0008:004002FE 8983F9090000 MOV [EBX+000009F9],EAX * On this address too.

After this, the good key replaces the bad one, the ProcDump import table will be correctly decrypted. How did I find this ? It could take me one week long to explain, use the tracing methods.

:00400304 C6050D1C0007EB MOV BYTE PTR [07001C0D],EB * This patch is like the one 
                                                      made in VBox 4.10 (JNZ to JMP).
:0040030B C705821C0007E9210300MOV DWORD PTR [07001C82],000321E9 * Same as above.

:00400315 A1E0D74300 MOV EAX,[0043D7E0] * Restore EAX.
:0040031A 8B1DE8D74300 MOV EBX,[0043D7E8] * And EBX.

:00400320 C705A81F0007E989E33FMOV DWORD PTR [07001FA8],3FE389E9

* At this place, all the serious protections will be passed, so we patch this point to 
put back the original values inside vboxt420.dll before the other integrity checks occur.

:0040032A C605AC1F0007F9 MOV BYTE PTR [07001FAC],F9 * End of the patch.
:00400331 E91DCAC306 JMP 0703CD53 * Back to VBox.
:00400336 C7054ECD0307E8ED2D00 MOV DWORD PTR [0703CD4E],002DEDE8

* In VBox, 7001FA8 is reached, so we land here.

:00400340 C60552CD030700 MOV BYTE PTR [0703CD52],00 * Put all the values
:00400347 C6050D1C000775 MOV BYTE PTR [07001C0D],75 * in their
:0040034E C705821C00070F852003 MOV DWORD PTR [07001C82],0320850F * original state.
:00400358 C705A81F00078065FC00 MOV DWORD PTR [07001FA8],00FC6580 * To defeat mem checks.
:00400362 C605AC1F00076A MOV BYTE PTR [07001FAC],6A
:00400369 E93A1CC006 JMP 07001FA8 * Go back to VBox and its no time limits anymore!.

The DialogBoxParamA trick (copied from V. Porguen essay about vboxt410.dll).

:00400376 8B442410 MOV EAX,[ESP+10] * We patched VBox import table address to land here at 
                                    every call to DialogBoxParamA (address 40028C). EAX 
                                    contains DialogBoxParamA procedure.

To understand all this, read the essay I'm talking about.

:0040037A A308D84300 MOV [0043D808],EAX * Save the procedure address.
:0040037F C7442410A0034000 MOV DWORD PTR [ESP+10],004003A0 * Replace proc. with 4003A0.
:00400387 8F050CD84300 POP DWORD PTR [0043D80C] * This is made to trick the 
                                                return address of DialogBoxParamA.
:0040038D 6898034000 PUSH 00400398 * To go to 400398.
:00400392 FF2504D84300 JMP [USER32!DialogBoxParamA]
:00400398 33C0 XOR EAX,EAX * Make VBox think you pressed the try button.
:0040039A FF250CD84300 JMP [0043D80C] * Go to window procedure.
:004003A0 837C240818 CMP DWORD PTR [ESP+08],18 * Is it finished loading?.
:004003A5 7510 JNZ 004003B7 * No, we loop.
:004003A7 C744240811010000 MOV DWORD PTR [ESP+08],00000111 * Finished loading, force 
                                                           the window procedure exit.
:004003AF C744240C95040000 MOV DWORD PTR [ESP+0C],00000495 * By modifying the window 
:004003B7 FF2508D84300 JMP [0043D808] * Go back to win procedure.

Final Notes

At this point the crack is finished, this should work on every VBoxed prog. Sure you've got to put this prog every time inside the VBoxed executable to make this work. Now let me tell you something, I e-mailed Preview Software for the incoming release of this crack, you know, just to tell them that we could give them information to help them build some better protections and they didn't even answer me ! Maybe they're too proud or sceptical.

So feel motivated to crack every prog protected by this, you will make a good action for them. They need to learn more and maybe the next time they will be more polite.

Only for misunderstandings : tsehp(at)yahoo(point or dot)com.

Definitely NO crack requests.

Ob Duh

Actually as your reading this tutorial on CrackZ's Reverse Engineering site so the Ob Duh doesn't really apply but here it is for posterity anyhow :-).

I wont even bother explaining that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.