4.2 A generic crack explained
Published and written by +Tsehp
No more hairs on WeiJunLi's head !
Written by +Tsehp
I will not explain what vbox is all about, 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 :
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-A 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 his virginity, it use crypted parameters at run time. Some essays tells you to use this technique, well if you want look to the future, those smart guys could find new tricks to detect procdump, so better avoid this and use your brain.
*A more devious brain than WeiJunLi. That helps.
I used vbox builder to protect notepad.exe, the purpose was to write a method that could work on any prog protected by vbox, remember that I'm on Win NT so the mem locations of the listings could be slight different.
If you want to make this work, you'll have to patch vboxt420.dll. I first tried a local Api spoofing and it was not working. The purpose is simplistic you have to patch this file when it is loaded,the precedent version was possible to 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,'cause 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 windoze apis 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 rsc places where thay are not used. I will not explain this in detail it's done in other essays about 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 prog 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 notepad's memory location 428298, so at the first call to getnotepad, 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 notepads 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 wonderfull method discovered by iceman.
The protected progs will NEVER be able to detecte a sudden patch to windows.
Since vbox 4.1, this prog 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 have to do 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 to 00AD)
extracted from frogsice doc (courtesy of frog's print)
Whats happening ? if sice 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 Sice is present, the int 3 triggers sice and vbox detects
How could you find the place to patch ? you could search for be4746 for example in vbox7420 but no way, just not present. This could be too easy for sure !
Weijun knew that, he did just the following : just before vbox needs this routine : it allocates some mem by virtualAlloc, decrypts a part of its code and put it
in memory, executes it and then deletes it by a good VirtualFree... well done. Not resident in memory and crypted inside vboxt420.
But he made a terrible mistake : there are other debbugers 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 for the int 3.
Help : the protection part is called from 700f7a5...
Well you've got all the old protections (see precedent essays), we have more memory integrity tests -> Well have to patch this prog just at the right time, by the use of counters and remove the patches just after (same as 4.10).
You can also manually remove the marks thats vbox needs to see if there was date tampering, I used filemon and regmon and found :
Files : located in \system_root\osxxxxx.bin
located in \winX\system32\wsxxxx.ocx
located in \winX\vbox\licenses\*.*
reg keys : two regs keys (the serials could be different :
If you delete everything, you have to reinstall the lic files by executing vsetup.exe (only if you play with an executable that you vboxed yourself), just don't forget to
do it in the 30 days after you have vboxed your app.
What do we've got to do ?
1)Remove the nag (same as vbox 4.1)
2)Make believe vbox we're still in the first 30 days
The only modifications will be in smallest parts of your vboxed app and inside vboxt420.dll, but only temporary patches inside this dll, it's checked with crc after the
nag and if your patches remains -> GAME OVER.
To make it the more simple, we're gonna patch the own windows apis,the first will be getprocaddress called a lot of times. If we patch this api to land back inside your
app, vbox will see nothing and you will be able to execute your own code before calling back again the api. This is the hook.
The second and third will be getlocaltime and getsystemtime, so they will return always the same date and time to vbox, and your trial will execute for ever.
After the init, we will patch back the apis to their original state, just to do them work ok; we will need two counters for this. At this point you must know that this essay was written on windows 2000,the apis are not the same on all the windows versions, so you will have to adapt this essay to win95,98 especially about the virtualprotect
On the last essay about vbox , V porguen made a successful patch inside the
vbox dlls, in a part that was not checked, now this is kind of impossible 'cause
all the file is crc checked, so all the patches will reside outside of vbox, we
will use the own win apis,
where we can do what we want, just don't forget not to patch them on your hd...
Well at this point , you understand that it would be pretty difficult to do a generic crack inside vboxt420.dll, but this method can be easyly adapted to all the vboxed apps, all you have to do is to find suitable places to inject this code, and adapt the code, jumps and counters. My purpose was to teach you how to do this and not to give ready-made cracking lesson.
The patch will work like a virus, first at the start point of your vboxed exe
(notepad.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 mem checks) and you will jump back to the starting point. This exe doesn't check itself on disk. I choosed for the code location starting at the very beginning of the file 1000300, the vars are beginning at 103b848, this place because in the PE, mem writing is allowed.
In our case : notepad.exe start point at 1020248 :
//******************** Program Entry Point ********
seg000:01020248 jmp 1000300***This is replaced on the file, as a jump to our patching routines.What was first is replaced in my prog
First part of my prog, explained line by line. A litteral explanation will follow :
seg000:01000300 push 103B848h ; ascii ref to Kernel32
seg000:01000305 call near ptr 77E956DBh ; call to getModuleHandle
seg000:0100030A mov ds:103B850h, eax ; save the module
seg000:0100030F push 103B854h ; ascii ref to GetProcAddress warning it's case sensitive
seg000:01000314 push eax
seg000:01000315 call near ptr 77E9564Bh ; call to getprocadress to have the address of getprocaddress api
seg000:0100031A mov ds:103B863h, eax ; save this address
seg000:0100031F push 103B890h ; a mem var to have the ancient flag
seg000:01000324 push dword ptr ds:103B868h ; the flag we want to patch the winnt api 0x00000040 (from winnt.h)
seg000:0100032A mov eax, 4096h ; page length
seg000:0100032F push eax
seg000:01000330 push dword ptr ds:103B863h ; the adress of the api we patch
seg000:01000336 call near ptr 77E980E8h ; call to virtual protect
seg000:0100033B mov eax, ds:103B863h
seg000:01000340 mov dword ptr [eax], 16AD13E9h ; we patch this api for it to jump back to 1000363 when vbox calls it
seg000:01000346 mov byte ptr [eax+4], 89h
seg000:0100034A mov dword ptr ds:1020248h, 0C403E086h ; we patch back the entry point with original values
seg000:01000354 mov dword ptr ds:102024Ch, 0E0320075h
seg000:0100035E jmp start (jumps to entry point)
What I'm doing ? I need several parameters concerning the api function I want
to patch, In windows those functions are memory protected, so if you attend
to patch them directly you will produce some page faults. You can use a 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 diskor in memory.
Virtual protect needs 4 parameters :
1) address of mem to tweak
2) size of mem
3)a protection flag (meaning read / write / execute rights)
4)a mem location where this function will put the old protection flag (use it when you're finished)
***SPECIAL NOTE TO THE READER
This is working on windows nt4 and win2k, not on win 98, you
actually have to find the good parameters to write enable
the process or find another way on win 98. Read iceman's essay about this
At this point vbox executes and when it first calls to GetProcAddress, it lands here :
seg000:01000363 inc dword ptr ds:103B893h ; this counter to wait for vbox to decrypt after we patch back getprocaddress
seg000:01000369 cmp dword ptr ds:103B893h, 1B0h
seg000:01000373 jz short loc_0_100037F ; after vbox is decrypted
seg000:01000375 push ebp ; this statement was crushed by my patch, we do it before returning to getprocaddress
seg000:01000376 mov ebp, esp
seg000:01000378 push ecx
seg000:01000379 push ecx
seg000:0100037A jmp near ptr 77E95650h
The counter is incremented and the api is executed back into vbox, until the counter is at 1b0. We go Here :
seg000:0100037F loc_0_100037F: ; CODE XREF: seg000:01000373j
seg000:0100037F mov dword ptr ds:77E9564Bh, 51EC8B55h ; after vbox is decrypted
seg000:01000389 mov byte ptr ds:77E9564Fh, 51h ; put back original values in getprocaddress
seg000:01000390 push 103B848h ; ascii ref for kernel32
seg000:01000395 call near ptr 77E956DBh ; get a handle for module kernel32
seg000:0100039A mov ds:103B850h, eax ; save this handle
seg000:0100039F push 103B86Ch ; ascii ref for getLocalTime
seg000:010003A4 push eax
seg000:010003A5 call near ptr 77E9564Bh
seg000:010003AA mov ds:103B879h, eax
seg000:010003AF push 103B890h
seg000:010003B4 push cs:readwriteex_flag
seg000:010003BB mov eax, 4096h
seg000:010003C0 push eax
seg000:010003C1 push cs:var1_adr
seg000:010003C8 call near ptr 77E980E8h ; create hook for getLocalTime
seg000:010003CD mov eax, 77E9C3FFh
seg000:010003D2 mov dword ptr [eax], 164081E9h
seg000:010003D8 mov byte ptr [eax+4], 89h
seg000:010003DC push 103B848h
seg000:010003E1 call near ptr 77E956DBh
seg000:010003E6 push 103B87Dh
seg000:010003EB push eax
seg000:010003EC call near ptr 77E9564Bh
seg000:010003F1 mov ds:103B88Bh, eax
seg000:010003F6 push 103B890h
seg000:010003FB push cs:readwriteex_flag
seg000:01000402 mov eax, 4096h
seg000:01000407 push eax
seg000:01000408 push cs:var2_adr
seg000:0100040F call near ptr 77E980E8h ; create hook for getSystemTime
seg000:01000414 mov eax, 77E8DA28h
seg000:01000419 mov dword ptr [eax], 172A58E9h
seg000:0100041F mov byte ptr [eax+4], 89h
seg000:01000423 mov eax, ds:7085ABCh
seg000:01000428 mov ds:103B894h, eax
seg000:0100042D mov dword ptr ds:7085ABCh, 100043Ch ; at the next call to dialogbox this will land in 100043c
seg000:01000437 jmp near ptr 77E9564Bh ; go back to the procedure
Code,code and code. When the counter is 1b0 we patch back in mem the original values to getprocaddress, always do that as
soon as you can, other procs could use it !
We patch two ther apis : GetLocalTime and GetSystemtime, at their end this
time. They are called 0xEB inside vbox to check
for the trial's date and we want them to return always the same year and month inside the time-structure, read your winApi documentation for more explanations for this.
We create two hooks (like with getprocaddress) for vbox to go to 1000485, in this place I execute a crushed line of this api
and write 017d0 in [eax], just to force the year and month of trial's installation, so vbox will believe to be inside the 30 days
forever. At the end of the code, I patch the vbox import table for DialogboxParamA, see victor porguen's ( porvox.htm) essay for that, the purpose is to avoid the vbox nag.
I just reproduced what he did, in summary make believe the window procedure
called by dialogboxparama that it is finished and put eax to 0 when the call to
eg000:0100043C mov eax, [esp+10h] ; see victor porguen essay on vbox 4.10 for further explanations
seg000:01000440 mov ds:103B898h, eax
seg000:01000445 mov dword ptr [esp+10h], 1000467h
seg000:0100044E pop dword ptr ds:103B89Ch
seg000:01000454 push 100045Eh
seg000:01000459 jmp near ptr 77E37FA2h
seg000:0100045E ; ---------------------------------------------------------------------------
seg000:0100045E xor eax, eax
seg000:01000460 jmp cs:ret_adr
seg000:01000467 ; ---------------------------------------------------------------------------
seg000:01000467 cmp dword ptr [esp+8], 18h
seg000:0100046C jnz short loc_0_100047E
seg000:0100046E mov dword ptr [esp+8], 111h
seg000:01000476 mov dword ptr [esp+0Ch], 495h
seg000:0100047E loc_0_100047E: ; CODE XREF: seg000:0100046Cj
seg000:0100047E jmp cs:proc_adr
Now here's the final part, the place where the time_structures of getlocaltime and getsystemtime are forced :
seg000:01000485 ; ---------------------------------------------------------------------------
seg000:01000485 mov [eax+0Eh], cx
seg000:01000489 mov dword ptr [eax], 107D0h ; date year and month forced inside getlocal and system time
seg000:01000490 inc byte ptr ds:103B8A4h ; counter for occurences of getlocal and systemtime calls
seg000:01000496 cmp byte ptr ds:103B8A4h, 0EBh
seg000:0100049D jz short loc_0_10004A3 ; patch back time apis with original values
seg000:010004A0 retn 4
seg000:010004A3 ; ---------------------------------------------------------------------------
seg000:010004A3 loc_0_10004A3: ; CODE XREF: seg000:0100049Dj
seg000:010004A3 mov dword ptr ds:77E9C3FFh, 0E488966h ; patch back time apis with original values
seg000:010004AD mov byte ptr ds:77E9C403h, 0C9h
seg000:010004B4 mov dword ptr ds:77E8DA28h, 0E488966h
seg000:010004BE mov byte ptr ds:77E8DA2Ch, 0C9h
seg000:010004C6 retn 4
Warning : at line 1000489, the value of 107d0h was choosed because it
corresponds to jan 2000, check first
your date installation and choose one in the trial's time limit.
This is over, notepad works without the nag whenever you set the time. This method can be used on all the time
trial vboxed progs. Following is the vars locations, don't forget that the asc refs means that they must be written
directly to this address, in the corresponding file offset. You only have the addresses.
seg002:0103B848 kernel32_asc_re db ? ; unexplored
seg002:0103B850 var_handle_kern db ? ; unexplored
seg002:0103B854 GetProcAddress_asc_r db ? ; unexplored
seg002:0103B863 var_adr_getprocaddre db ? ; unexplored
seg002:0103B868 readwriteex_flag dd ? ; DATA XREF: seg000:010003B4r
seg002:0103B86C getlocaltime_asc_ref db ? ; unexplored
seg002:0103B879 var1_adr dd ? ; DATA XREF: seg000:010003C1r
seg002:0103B87D getsystemtime_asc_re db ? ; unexplored
seg002:0103B88B var2_adr dd ? ; DATA XREF: seg000:01000408r
seg002:0103B893 getprocaddress_count db ? ; unexplored
seg002:0103B894 dialogboxparama_impo db ? ; unexplored
seg002:0103B898 proc_adr dd ? ; DATA XREF: seg000:0100047Er
seg002:0103B89C*ret_adr dd ? ; DATA XREF: seg000:01000460r
seg002:0103B8A4*getlocals_counter db ?
Here you've got my original notepad.exe and my patched
one with the vsetup to execute first (installs the licence
files and the regs entries.
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.
Don't forget to mail me if you adapt this essay on win98Only for misunderstandings : tsehp(at)yahoo(point or dot)com
No crack requests