April 1998
"Bounds Checker V5.02"
(The all in one crack)
Win'95 Code Reversing
by The Sandman 
Code Reversing For Beginners 
Program Details
Program Name: Bounds Checker V5.02
Program Type: Code Analyser/Debugger
Program Location:  Here or Here
Program Size: 8.37 megs 
Tools Required:
Softice v3.2
Easy (   )  Medium ( X )  Hard (    )  Pro (    ) 
There is a crack, a crack in everything. That's how the light gets in.
How to crack Bounds Checker V5.02
( And ANY program using TL32V2.DLL! )
Written by The Sandman

Having read Harwi's essay on: Bounds Checker Time limit (Persistent file Protection) I immediately decided to locate a copy of Bounds Checker from the Web and try and follow Harwi's steps in the hope of learning something new about reverse code engineering and besides, Bounds Checker sounds like an ideal tool to learn how programs really operate under windoze '95!.

This *crack* represents my first MAJOR crack to date, however, on this occasion it turned out to be the easiest and most enlightening crack I have ever come across. This crack took me LESS than five minutes to figure out and if I'm honest here it didn't require much knowledge on Assembler since I don't know much at all!.

So what's the deal here!. Harwi's approach to cracking Bounds Checker is based on his experience and knowledge in reverse engineering and as expected, the protection system was written and designed on how experienced crackers *might* try and de-code it's hidden secrets.  Fair enough, nothing wrong here but what-if someone, like me who has little experience or knowledge on such matters tried to 'attack' this same code, would not my approach be one based on 'gut feeling' or perhaps based on a little Zen?.

Can you see where I'm leading you to?

Have you ever noticed that when someone is being taught say a new card game that they seem to win more times than say someone who has played the same game many times and knows the game quite well?. We would put this down to 'Beginners Luck'.

The reason why this happens is because the novice card player isn't bogged down with the rules of the game, nor is he able to draw upon past experience of the game so he relies purely on the scraps of information he has so far managed to get on the game and then uses 'educated guesses' to work out what card to play next.. So how does this tie into how I cracked Bounds Checker, patience, I'm getting there..

My knowledge of Assembler is very sketchy, I know the basics and that's it so like the person learning a new card game I too have to rely on  'Educational Guesses' to find my way round this new game of cracking.

( +ORC goes to great lengths to teaching us that Zen is not just based on  knowledge or experience, but how 'we feel' about the code itself! ).

As our knowledge and experience in reverse engineering increases we tend to start to rely more on this and less on the true 'Zen' we once possessed as newbies!.

We might now see that newbies to cracking have in many ways, a clearer insight into cracking an unfamiliar protection system when compared to some of the more "experienced" crackers simply because we can't be mis-lead by fake routines or bogged down in routines we know nothing about since we have only 'Zen' to help us through this jungle of code.  Ever heard the saying: 'Can't see the wood for the trees?'.

Harwi's essay was based on Bounds Checker V5.1, while the copy I found was V5.2 so rather than waste anytime on trying to patch my copy of Bounds Checker (the addresses I thought would be different to the ones Harwi used ) I decided to see if I could somehow find another, much easier way to accomplish the same thing.

What I found by accident was a way to crack Bounds Checker V5.2 AND ANY OTHER PROGRAM THAT USES THE SAME PROTECTION SYSTEM and that it requires just one Softice BPX command and NO patching of any files!!. A newbie's dream crack!.
About this protection system
The whole of this protection system is housed in a single DLL file called TL32V2.DLL (TimeLock32) and in the case of Bounds Checker V5.2 it can be found in the C:\Windows directory, not as you would expect in the C:\Windows\System directory.

This DLL file is 91648 bytes long. ( Don't get this confused with the one installShield Express V2 uses which is 130,560 bytes long and which also uses the same filename. )

This DLL file is configured as a self contained 'TimeLOCK Purchase Wizard' and is made by Preview Software Inc so that it can be used by anyone who has a licence to use it in their programs ( just as Installshield is used by many different programs and companies today. )
The Essay 
This essay is written through the eyes of a newbie and tries to explain how as a newbie, I was able to crack this protection system. The source code shown in this essay has limited documentation associated with it since I didn't rely on any when I opened the code up in Softice and besides, those new to Reverse Code Engineering usually just try and follow the flow of the target program as I did and hope for the best..:) It's only after gaining more experience and knowledge on protection systems do we start to actually
take notice of what each routine/function does and how it effects other parts of the program.

After installing Bounds Checker using:

Name: The Sandman
Keycode: *leave this blank for now*

I started up Bounds Checker and went directly to the Purchase Screen by loading Bugbench.exe from:

C:\BChecker\EXAMPLE\BUGBENCH\Bugbench.exe and then attempted to run
bugbench which resulted in the 14 Day trial screen popping up.

I selected the Purchase button and for the Keycode I typed in: 12345

You should have now:-

For the User Name: The Sandman
For the Company Name: -
For the Keycode: 12345

Harwi mentions in his essay that Bounds Checker expects 16 characters here but we don't really need to know this nor do we need to enter all 16 characters..:)

At this point I pressed Ctrl-D to get into Softice and typed:

BPX getwindowtext then pressed x to leave softice.

Now I Pressed the OK button and wham, Softice breaks as expected in the getwindowtext routine, so from here I pressed F12 then F12 again which now placed me in the main TL32V20.DLL code (TL32v20!text+1859) at address: 014f:10003e81

:10003E81 6834230000 
:10003E86 56  
:10003E87 FFD7  
:10003E89 50 
:10003E8A 8BD8 
:10003E8C FF15D4630110 
:10003E92 83F802  
:10003E95 7F1C 
:10003E97 6800200000  
:10003E9C 68193B0110 
:10003EA1 6829400110 
:10003EA6 6A00 
:10003EA8 FF15A8630110 
:10003EAE E939010000 
:10003EB3 6A27 
:10003EB5 8D4584 
:10003EB8 50 
:10003EB9 53 
:10003EBA FF15DC630110 
:10003EC0 6835230000 
:10003EC5 56 
:10003EC6 FFD7  
:10003EC8 6A31 
:10003ECA 68A0440110 
:10003ECF 50  
:10003ED0 FF15DC630110 
:10003ED6 8D45D8  
:10003ED9 50  
:10003EDA E885E9FFFF 
push 00002334   ;We land here 
push esi 
call edi 
 push eax 
mov ebx, eax 
Call dword ptr [100163D4] 
cmp eax, 00000002 ;Check for a valid Name 
jg 10003EB3 
push 00002000 
push 10013B19 
push 10014029 
push 00000000 
Call dword ptr [100163A8] ;Show 'invalid 
jmp 10003FEC              ;Name' Msgbox 
push 00000027 
lea eax, dword ptr [ebp-7C] 
push eax 
push ebx 
Call dword ptr [100163DC] 
push 00002335 
push esi 
call edi 
push 00000031 
push 100144A0 
push eax 
Call dword ptr [100163DC] 
lea eax, dword ptr [ebp-28] 
push eax 
call 10002864 ; CHECK REGKEY CODE 
                          ; HERE! 
From looking at the source code that Softice was showing me I noticed that:

1. I was not in the actual Bounds Checker code but in fact in the TIMELOCK32 DLL file which Harwi mentioned that he had managed to patch in several places to get Bounds Checker to run as a fully registered program.

2. Scrolling down the listing a little more that there were a few Pushes of  information onto the stack and a few system Call's with a liberal dose of conditional Jumps but nothing that showed the classical:-

 Cmp instruction
 conditional jump/Call statement.

While there are many other ways that Bounds Checker could test to see if the Keycode that I had typed was correct, I knew of only the above method so decided to follow this hunch through.

At this point I typed:-

BD 00 to clear away my breakpoint and began to start to pressing the F10 key and watched what each Call instruction did until the actual 'Wrong Keycode' message popped up on my screen, which told me that one of the Call instructions I had by-passed dealt with the verification of my fake Keycode.

Since I had only pressed the F10 key a few times before the 'Wrong Keycode' message appeared helped me narrow down the possible Call statements to just a small handful.

At this point I re-enabled my single breakpoint: BE 00

I exited out of softice and re-ran the purchase screen again, and once again Softice broke into the getwindowtext routine and once more pressed the F12 key TWICE to land back into the TL32V2.DLL code.

At this point I first dis-counted any Calls or Jumps to any of the system routines since I knew these wouldn't handle the process of actually creating a Keycode based on the User's entered text and then choose the FIRST Call I found that went called another routine/function in the actual TL32V2.DLL code which was found at:

:10003EDA E885E9FFFF              call 10002864

I moved the cursor on this line and told Softice to run the code normally from where I was until it reached THIS line.

I typed: here

Before we go any further lets disable our Softice breakpoint again by typing: BD 00
Now instead of pressing F10 I pressed the 'T' key so that I could trace into this call statement.

I then arrived to this routine:-

* Referenced by a CALL at Addresses: 10002B25   , :10003EDA
:10002864 55                      push ebp      ;We land here
:10002865 33C0                    xor eax, eax
:10002867 8BEC                    mov ebp, esp
:10002869 81ECB0000000            sub esp, 000000B0
:1000286F C68550FFFFFF00          mov byte ptr [ebp+FFFFFF50], 00
:10002876 56                      push esi
:10002877 57                      push edi
:10002878 8DBD51FFFFFF            lea edi, dword ptr [ebp+FFFFFF51]
:1000287E 33F6                    xor esi, esi
:10002880 AB                      stosd
:10002881 AB                      stosd
:10002882 AB                      stosd
:10002883 AB                      stosd
:10002884 6870100110              push 10011070
:10002889 8D45FC                  lea eax, dword ptr [ebp-04]
:1000288C 50                      push eax
:1000288D 46                      inc esi
:1000288E E8ED250000              call 10004E80
:10002893 83C408                  add esp, 00000008
:10002896 8D4DFC                  lea ecx, dword ptr [ebp-04]
:10002899 0FBE8632430110          movsx eax, byte ptr [esi+10014332]
:100028A0 50                      push eax
:100028A1 68B8140110              push 100114B8
:100028A6 51                      push ecx
:100028A7 E864250000              call 10004E10
:100028AC 83C40C                  add esp, 0000000C
:100028AF 8D4DFC                  lea ecx, dword ptr [ebp-04]
:100028B2 51                      push ecx
:100028B3 E848250000              call 10004E00
:100028B8 83C404                  add esp, 00000004
:100028BB 8944B5A0                mov dword ptr [ebp+4*esi-60], eax
:100028BF 83FE06                  cmp esi, 00000006
:100028C2 72C0                    jb 10002884
:100028C4 33F6                    xor esi, esi
:100028C6 6870100110              push 10011070
:100028CB 8D45FC                  lea eax, dword ptr [ebp-04]
:100028CE 50                      push eax
:100028CF 46                      inc esi
:100028D0 E8AB250000              call 10004E80
:100028D5 83C408                  add esp, 00000008
:100028D8 8D4DFC                  lea ecx, dword ptr [ebp-04]
:100028DB 0FBE86DF440110          movsx eax, byte ptr [esi+100144DF]
:100028E2 50                      push eax
:100028E3 68B8140110              push 100114B8
:100028E8 51                      push ecx
:100028E9 E822250000              call 10004E10
:100028EE 83C40C                  add esp, 0000000C
:100028F1 8D4DFC                  lea ecx, dword ptr [ebp-04]
:100028F4 51                      push ecx
:100028F5 E806250000              call 10004E00
:100028FA 83C404                  add esp, 00000004
:100028FD 8944B5B8                mov dword ptr [ebp+4*esi-48], eax
:10002901 83FE10                  cmp esi, 00000010
:10002904 72C0                    jb 100028C6
:10002906 FF75CC                  push [ebp-34]
:10002909 FF75F8                  push [ebp-08]
:1000290C FF75A4                  push [ebp-5C]
:1000290F FF75D8                  push [ebp-28]
:10002912 FF75BC                  push [ebp-44]
:10002915 E861FCFFFF              call 1000257B
:1000291A 83C414                  add esp, 00000014
:1000291D 898564FFFFFF            mov dword ptr [ebp+FFFFFF64], eax
:10002923 FF75D0                  push [ebp-30]
:10002926 FF75F4                  push [ebp-0C]
:10002929 FF75A8                  push [ebp-58]
:1000292C FF75D4                  push [ebp-2C]
:1000292F FF75C0                  push [ebp-40]
:10002932 E844FCFFFF              call 1000257B
----------- Snip -----------
:10002AB0 E8C6FAFFFF              call 1000257B
:10002AB5 83C414                  add esp, 00000014
:10002AB8 8DB564FFFFFF            lea esi, dword ptr [ebp+FFFFFF64]
:10002ABE 8945A0                  mov dword ptr [ebp-60], eax
:10002AC1 6870100110              push 10011070
:10002AC6 8D45FC                  lea eax, dword ptr [ebp-04]
:10002AC9 50                      push eax
:10002ACA E8B1230000              call 10004E80
:10002ACF 83C408                  add esp, 00000008
:10002AD2 8D4DFC                  lea ecx, dword ptr [ebp-04]
:10002AD5 FF36                    push dword ptr [esi]
:10002AD7 68B4140110              push 100114B4
:10002ADC 51                      push ecx
:10002ADD 83C604                  add esi, 00000004
:10002AE0 E82B230000              call 10004E10
:10002AE5 83C40C                  add esp, 0000000C
:10002AE8 8D4DFC                  lea ecx, dword ptr [ebp-04]
:10002AEB 8D9550FFFFFF            lea edx, dword ptr [ebp+FFFFFF50]
:10002AF1 51                      push ecx
:10002AF2 52                      push edx
:10002AF3 FF158C620110            Call dword ptr [1001628C]
:10002AF9 8D4DA4                  lea ecx, dword ptr [ebp-5C]
:10002AFC 3BF1                    cmp esi, ecx
:10002AFE 72C1                    jb 10002AC1   ;Cycle through  fake key 
:10002B00 8D8550FFFFFF            lea eax, dword ptr [ebp+FFFFFF50]
:10002B06 50                      push eax      ;Our real Keycode is here
:10002B07 FF7508                  push [ebp+08]
:10002B0A E871230000              call 10004E80
:10002B0F 83C408                  add esp, 00000008
:10002B12 B801000000              mov eax, 00000001
:10002B17 5F                      pop edi
:10002B18 5E                      pop esi
:10002B19 8BE5                    mov esp, ebp
:10002B1B 5D                      pop ebp
:10002B1C C3                      ret
Can you see a pattern in the above code?.  Noticed  a set of instructions that keep repeating themselves *can you feel it?*

:10002A4D 83C414            add esp, 00000014
:10002A50 894590            mov dword ptr [ebp-70], eax
:10002A53 FF75F8            push [ebp-08]
:10002A56 FF75E8            push [ebp-18]
:10002A59 FF75A4            push [ebp-5C]
:10002A5C FF75E8            push [ebp-18]
:10002A5F FF75EC            push [ebp-14]
:10002A62 E814FBFFFF        call 1000257B

I counted out of curiosity, the number of times this pattern repeated and  it came to 16 and since each 'Call' went to the same address this made me think of what Harwi said about there being 16 characters in the KeyReg  code!. Very interesting...

I guessed here that the registration key was being processed individually letter by letter ( 16 times) so again, I choose the FIRST Call instruction I found that came AFTER these 16 letter checks and placed my cursor  on this line and then told Softice to run the code as normal UNTIL it came to the line with my cursor on it.

I did this because I didn't want to try and figure out how the program worked out the registration code, I was only in the results of this process. )

:10002AC9 50                                 push eax
:10002ACA E8B1230000              call 10004E80 ;I stopped here

Remembering that the program had to somehow compare our fake Key registration with one that the program had generated and uses to check the registration code I typed:

D eax

The results of this showed nothing that made any sense to me so I then continued onto the next Call statement (call 10004E10 )and told Softice to break on this line where again I started to display the memory contents of the eax, esi registers using the Softice command D eax and D esi etc and again nothing was shown that resembled a keycode.
The next Call statement (Call dword ptr [1001628C]) still proved fruitless.

It was only at this point did I realize that the conditional jump at:-

:10002AFE 72C1                    jb 10002AC1 ;Cycle through our FAKE KEY

seem to cycle through the Call statements that I had been stopping on and displaying the memory contents of certain registers so in order to speed things up a little I decided to skip this JB instruction and stop on Call statement at:-

:10002B06 50                      push eax ; Our REAL Keycode is here!
:10002B07 FF7508                  push [ebp+08]
:10002B0A E871230000              call 10004E80

Bingo!, by typing: D eax the instruction push eax was pointing to an area of memory that had a 16 character code that looked like a key registration code!


I cleared Softice's breakpoints with BC * and exited Softice with x and now typed in this new Registration Key. Job done.
Crack Loader 
Final Notes 
Using the above procedure will not only defeat the protection system employed in Bounds Checker it will ALSO defeat other programs using the TL32V20.DLL file!. Because no patching of code is required anyone can defeat this protection system in just a few minutes using just ONE BPX command and a few F10's.
My thanks and gratitude goes to:
Harwi for his groundwork into how Bounds Checker works in relation to the TL32V2.DLL file.
Fravia for providing possibly the greatest source of Reverse Engineering knowledge on the Web.
+ORC for showing me the light at the end of the tunnel.
Ob Duh 
Do I really have to remind you all that by buying and NOT stealing the software you use will ensure that these software houses will continue to produce even *better* software for us to use and more importantly, to continue offering even more challenges to breaking their often weak protection systems.

If your looking for cracks or serial numbers from these pages then your wasting your time, try searching elsewhere on the Web under Warze, Cracks etc.

 Next   Return to Essay Index   Previous 

Essay by:          The Sandman
Page Created: 30th April 1998