Reversing AtomTime 98
How to reverse *completely* a protection scheme
Not Assigned
07 May 98
by The RudeBoy [PC]
Courtesy of Reverser's page of reverse engineering
slightly edited
by reverser+
1) "...I am going to explain 4 possible ways to crack our target..."
2) "...This is a simple and effective way to patch this application. However, have we learned anything from doing this? Not really. Let's continue on..."
3) "...We could stop here with a fully cracked/registered program. But, like I said that is not the goal of this essay. Let's figure out exactly how the program generates its' keys..."
D'I need to say more? That's the correct approach... I wish some other boys would be more Rude :-)
There is a crack, a crack in everything That's how the light gets in
( )Beginner (x)Intermediate ( )Advanced ( )Expert

An essay for crackers to see how to look inside a protection scheme and use different techniques to crack it.
Reversing AtomTime 98
How to reverse AtomTime 98
Written by The RudeBoy [PC]

I have grown tired of seeing essays describing how to do a simple patch of a program. Many offer only a simple explanation of what bytes the Author changed in order to remove the protection. In this essay I have tried to completely explain what is happening in the protection scheme, and where a few of the weak points are to be exploited by a cracker.

Tools required
Soft Ice - Whatever version you have should do
W32Dasm/IDA whichever you prefer, although the essay is aimed more towards w32dasm
Your Favorite Hex Editor, if you want to patch the program

Target's URL/FTP

Program History
i dunno, neither do I really care what this target actually does... it's just for the reversing part of it...

The object of this tutorial is not to crack the target, Atom Time 98 v2.0, but rather to teach you how you could crack this app. With almost any app there are a number of different methods which will effectively crack the application. Some are easy and some are harder, but the harder the crack, the more you learn. I am going to explain 4 possible ways to crack our target.
The first step in cracking any app is to run the app and see what happens when we try to register it. When we do this in Atom Time we get the message: "License data is invalid. Either the data was not entered correctly or the License key is invalid."
Ok, next it's time to get our good friend w32dasm out and disassemble our target. Go into the String Ref's section and look for the invalid license string. By looking at the code around the place where this string is referenced we see that there is a conditional jump at 406010, and that we never want to make that jump. The code at 406010 looks like this:

:00406009 E8A33D0000              call 00409DB1  ;IsValidInfo()
:0040600E 85C0                    test eax, eax	 ; 
:00406010 0F8488000000            je 0040609E	 ;je Beggar_Off

Ok, I must now make a quick point before we continue on. This point was the whole purpose of my last essay, but I will say it again here, changing the je at 406010 will NOT register the program. It will merely display the Good_Guy message when the data is entered.
What this code does tell us is that we want the IsValidInfo() routine to return a non-zero value in eax.

This brings us to the first method of cracking this app:
In w32dasm double click on the line of code a 406009 and then click on the call button, it will take you to the IsValidInfo() routine. All the only thing required in order for this program to be registered is for this routine to return 1 in eax. There are many methods you could use to do this, but here is my favorite:

6A01   push 	01
58     pop  	eax
C3     ret
This is a simple and effective way to patch this application. However, have we learned anything from doing this? Not really. Let's continue on and see what this program really does.

In softice set a breakpoint on GetWindowTextA. Then enter your fake information in the program and hit the OK button. The program breaks into softice. Now lets use the information we got from w32dasm to make life a little easier on ourselves. (This will not always work, but the majority of the time it does) type 'bpx 406009' and disable the GetWindowTextA breakpoint. Now hit F5 and wow, we break right on the IsValidCode() routine. Perfect, now lets begin tracing.

Eventually you will get to this line of code:

:00409DD0 837B0C00         cmp dword ptr [ebx+0C], 00000000
:00409DD4 750F             jne 00409DE5	;jne Code_Entered
The code at 409DD0 compares a dword in memory to 0, if it equals 0 then 0 is put into eax and the function returns. Hmm…I wonder what it is looking at. If you look at what is stored in memory at [ebx+0C] you will see that it is the code you entered, converted into hex. The data that I saw was:
78 56 34 12
(The code I entered was '12345678')

Ok, good to know. Remember that [ebx+0C] contains your code. Now, if you look ahead a little in the code you will see this:

:00409DE5 8BCB             mov ecx, ebx
:00409DE7 E839000000       call 00409E25 	;GetValidKey()
:00409DEC 89C6             mov esi, eax	;Put the key into esi
:00409DEE 8B4B0C           mov ecx, dword ptr [ebx+0C] ;our key into ecx
:00409DF1 3BCE             cmp ecx, esi	;Compare the keys
:00409DF3 7516             jne 00409E0B	;jne Beggar_Off
Here is where the 2nd and 3rd cracks take place.
Crack #2:
This is a very easy, IMHO lame way to crack this app. You have gotten this far, you might as well get a serial or make a keygen, but, if you must: Simply change the instruction at 409DF3 from 7516 to EB00. This has the same effect as nopping the jump, but as we all know, it is better not to nop. :)
Crack #3:
Write down the value in eax after the GetValidKey() function is called. This serial # will be valid if you put your name into the name field, make sure that the date field contains the same date as when you got the serial and that the same licensing option is selected (e.g. Site or Single License)
We could stop here with a fully cracked/registered program. But, like I said, that is not the goal of this essay. Let's figure out exactly how the program generates its' keys. To do this we trace into GetValidKey().
This function starts off by doing some string manipulations to the Date and the Name that you entered. It strips any non-alpha and non-numeric characters from the name and converts it to all upper case. The date is converted into a string in the format of "YYMMDD". You can follow the changes that are made to these strings either by watching the data passed to the calls, or by tracing the calls themselves. Although it is not necesary to trace all these calls in order to crack the application, it is a good way to learn about what is happening.
After the strings have been manipulated you get to this line of code:

:00409F05 50               push eax
:00409F06 E8DCF3FFFF       call 004092E7	
:00409F0B 8945E8           mov dword ptr [ebp-18], eax
If you trace over that call you will see that eax has the real serial # in it. Re Enter your registration and this time step into this call. A few lines into this routine we see this:

:004092F8 C6440DD400       mov [ebp+ecx-2C], 00  ;Move '00' into memory
:004092FD FF7508           push [ebp+08]
:00409300 8BCE             mov ecx, esi
:00409302 8D55D4           lea edx, dword ptr [ebp-2C]
:00409305 03CA             add ecx, edx
:00409307 51               push ecx
:00409308 E89F470000       call 0040DAAC ;Put the name after the null
It then calculates the length of the name and we get this:

Ebx = the length of name

:0040931D 83FB1E           cmp ebx, 0000001E  ;compare ebx to 30
:00409320 7D0A             jge 0040932C	    ;jump if greater or equal
:00409322 8BCE             mov ecx, esi
:00409324 46               inc esi
:00409325 885C0DD4         mov byte ptr [ebp+ecx-2C], bl ;put bl into mem
:00409329 43               inc ebx		    ;increment ebx
:0040932A EBF1             jmp 0040931D	    ;loop
:0040932C 8BCE             mov ecx, esi
:0040932E 46               inc esi
:0040932F C6440DD440       mov [ebp+ecx-2C], 40 ;put 40 into memory
:00409334 8BCE             mov ecx, esi
:00409336 46               inc esi
:00409337 C6440DD408       mov [ebp+ecx-2C], 08 ;put 08 into memory
What the above code does is set up a section of memory to look like this:

00RUDEBOY0708090A0B0C0D0E0F10112131415161718191A1B1C1D (This is for my name with yours it will vary slightly)

It's not done yet. It then takes the date, converts the numbers from ascii to hex and appends those numbers to this.
We then come to these lines of code:

:0040936F 8A4D10           mov cl, byte ptr [ebp+10] ;Move a value into cl
:00409372 8BD6             mov edx, esi
:00409374 46               inc esi
:00409375 884C15D4         mov byte ptr [ebp+edx-2C], cl ;append cl to our 'string'
:00409379 8BCE             mov ecx, esi
:0040937B 46               inc esi
:0040937C C6440DD406       mov [ebp+ecx-2C], 06   ;write a '6'
:00409381 8BCE             mov ecx, esi
:00409383 46               inc esi
:00409384 C6440DD402       mov [ebp+ecx-2C], 02	  ;write a '2'
:00409389 C64435D400       mov [ebp+esi-2C], 00   ;write a '0'
:0040938E 8D4DD4           lea ecx, dword ptr [ebp-2C]  ;point ecx to our 'string'
:00409391 51               push ecx
:00409392 6AFF             push FFFFFFFF
:00409394 6A2B             push 0000002B
:00409396 E810FFFFFF       call 004092AB  ;MakeCode()
:0040939B 89C3             mov ebx, eax	;Put the new code into ebx
:0040939D F7D3             not ebx		;Perform a bitwise NOT
The bitwise NOT can also be called "1's Complement". Basically it changes the value of each bit. If it is a '1' it becomes a '0' and vice versa.
So far we have created a long "string" in memory that is composed of a few constant values, the name, the date, and another value (see 40936F). This whole "string" begins at [ebp-2C]. Now, what is this mystery value from lines 40936F and 409375? Well, let's think about this. The value that is in there for me is '1'. What other data could be gathered off the form where you enter your registration information? Of course, the license type. I have selected single user license, I wonder what happens if I change that to a site license…
Set a breakpoint on the call to MakeCode(), exit softice, change the license type and hit enter. Hmm…take a look at the "string" and what do I see? Sure enough that '1' has changed to a '2'. Ok, now we know what each part of the "string" is. Now that we understand what is in the string it's time to take at look at the last part of this registration number generating routine. The MakeCode() function.
The function starts out with some general initializations.
It puts 0x2B into esi (this was passed to the function, it also happens to be the length of our "string")
It puts 0xFFFFFFFF into edx (also passed to the function)
And it puts the location of our "string" into ebx.
It then moves the length from esi into ecx and subtracts one from esi…hmm..a counter perhaps? It appears so because it then tests ecx to see if it is 0 and jumps over a bunch of code if it is. We now begin the actual code generation:

:004092C0 8BCA            mov ecx, edx ;move the code into ecx
:004092C2 C1E908          shr ecx, 08  ;shift it over 1 byte
:004092C5 81E1FFFFFF00    and ecx, 00FFFFFF ;cut off the leftmost byte
:004092CB 8BC3            mov eax, ebx ;location of our string into eax
:004092CD 43              inc ebx      ;point to the next byte 
:004092CE 0FB600          movzx eax, byte ptr [eax] ;move the byte from the string into eax
:004092D1 33C2            xor eax, edx 
:004092D3 0FB6C0          movzx eax, al
:004092D6 330C8590BD4300  xor ecx, dword ptr [4*eax+0043BD90] ;INTeresting
:004092DD 89CA            mov edx, ecx  ;mov the new value into edx
This code loops until it has covered every byte in the string. The most interesting part is the code at 4092D6. It uses al to reference a value from an array of 256 int's* that begins at 43BD90. It then xors the value from the integer array with ecx. In order to do a keygen for this application you must reproduce this array of ints (thank you +Quine for softdump ;). Other than that, this is a very straightforward routine to generate the registration code. (Don't forget that when the code is returned it has a logical not performed on it to swap the value of all the bits :).

* More precisely it is an array of DWORD's, with a 32 bit C compiler an int is a DWORD.

Well, that concludes our analysis of the protection used by Atom Time 98 v 2.0.
If you didn't figure it out the 4th type of crack is a keygen. In order to create the keygen you must reproduce the code that creates the "string" as well as the MakeCode() function. You can do this in any language, such as: asm, c, or pascal (yuck).

Final Notes
I have given you 4 ways to crack this program. There are MANY more, but the ones I gave you are the ones that made the most sense to me. When you crack, be creative, have fun, that's what it's really all about anyway, isn't it?

Ob Duh
I wont even bother explaining you 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.

You are deep inside reverser's page of reverse engineering, choose your way out:

redhomepage redlinks redsearch_forms red+ORC redstudents' essays redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_reverser
redIs reverse engineering legal?