Site hosted by Angelfire.com: Build your free website today!
Back to index
                                               Basic Cracking knowledge 

Probably a god way to start is by explaining the anatomy of a CPU or the system processor, its quite important to 
understand some fundamental things on how it operates, so heres my attempt at describing just that, with the
emphasis on cracking and what you need to know for it.

The CPU has something called registers, im sure youve seen them in softice, the common ones are the ones you can
see in the top screen in softice, EAX EBX ECX EDX EDI ESI EBP and ESP. The CPU has other registers too like MMX
registers (8 of thoose) and the debug registers (got a few of thoose as well) and the test registers (very odd things)
But we will only focus on the basic 8 registers, EAX - EDX are what we call general purpose registers, they are there
so that we can store just about anything in them and it doest really matter too much which ones you use for what,
they are each 32 bit in size (thats 4 bytes:-) theese are the most common ones to use when moving things in and out
of memory locations. You can take this as an example MOV EAX,12345678   this will move the value/number/address
12345678 into the CPU register EAX when this value has been placed in EAX it can then be moved from EAX into a new
memory location. You have to move it via the register (EAX) to be able to mov it into the new address, you cant just
move from one memory address to another, it doesnt work that way.
You should now understand that you could of course substitute the EAX in the example with any of the general purpose
registers EBX ECX etc.... you get the point.

Lets not go into what is special about EDI and ESI and EBP just yet, because its not necessary at this stage, but we 
need to clarify a few thigns about ESP.

The ESP is the stack pointer, i know that you probably may not completley sure what a stack pointer does, but 
im here to explain it to the best of my ability.
We can just refer to the ESP as the stack from now on to make it easier.
Every program you run will be given its own stack and a stack is exactly what it sounds like, its a pile of things 
that you place on it, we place something on the stack withthe opcode PUSH and we get something from the 
stack with the opcode POP.

Lets say that we have just started a program, we havent got anything on our stack yet, our stack is empty.
Now we PUSH 123456 
The number 123456 will now be placed on the stack, its at the top of it and if we want to retrive it we simply use POP
now to use POP we also need a destination, so we do POP EAX  and the 123456 will be placed in EAX.
if we now PUSH EAX we will place the 123456 back on the stack, and if we after the PUSH EAX decide to PUSH
something else, for instance PUSH 555555 the stack will look like this:

stacktop------>555555
stackbottom->123456

we now PUSH another thing lets say PUSH 999999 and then the stack looks like this:

stacktop------>999999
---------------->555555
stackbottom->123456

I think you now understand that each new value is placed on top of the ast one that we pushed, and if we now decide
to POP EAX we will place the last number we pushed in EAX.
We POP EAX adn we get 999999 in EAX, then we POP EBX and we get 555555 in EBX, im sure you can guess what
we get if we now POP into somthing else say for instance ECX.

Now you may wonder what a stack is good for, and how does it affect our cracking?
Well the stack is used by every program you run in one way or another and actually understanding how it works
is very uncommon with newbies.
The stack is very useful when it comes to the RET function taht you see in all programs as well, the RET is used
by a program when it wants to return from a subroutine to a main routine, for instance after a serial number has been
compared/encrypted or whatever.
The last value placed on the stack is the address that the program will return to.
So if you if you see a program that modifies ESP before a RET, it could for instance do something like ADD ESP,52
and if it does you may sometimes wanna note the value in ESP before the ADD so you know where you would have
returned to if the program had not added 52 to it.  
Hmm maybe that was a bit confusing, but i think you get the point, what im tryingt say is that once in a while having
a look at ESP (the stack) can help a great deal in understanding the flow of execution in the program.

blah blah im bored now... i will write more later.
go practice with the tracing guide.

Hello :-)
Im not bored or tired anymore, so heres some other thigns to read, i dont feel like going on about the processor at
the moment so instead i'll give you a sall cracking example, this will let you practice what you learned in The Tracing
Guide, for this exercise you need TraceMe3.zip 

Ok what we have here is a time trial, the program only runs properly at 14:00 to 14:10, if you run it at any other time
it will display a message telling you that. Try it by setting your clock to 14:00 or something and then to another time.
What this program does is call one of windows API functions (theese are briefly mentioned in The Tracing Guide)
This particular API is called GetLocalTime and does exactly what its name indicates, it gets the current time of your 
computer.
This API call is sometimes used by regular timetrials and by knowing how it can be used you can of course also learn
to defeat theese schemes.
The protection of this program is very simple and is very (if not exactly) the same as the TraceMe2, but in this case
the registration flag is set by the time and not by the serial.

This traceme however does not come with symbols, this one is just like a live target porogram would be, but of curse
very small and very simple to break.

So now what do we do?, well its time to set a brekapoint, and what better breakpoint to set then just bpx GetocalTime
Another thing to keep in mind is that when you break on an API function you land on the START or ENTRYPOINT of that
particular function, a good way to find the caller (the part of the program which called this function) is to press F12
F12 takes you to the next RET (remember the stack thing and RETs?) and when you RET you often enough land exactly
under the call to this particular function. So we press F12 to return to the program code.
Now when you run the program you will notice that it also calls another windows function, this one is called 
GetTimeFormatA , this API function simply takes the time delivered by GetocalTime and makes it readable, it converts
it to an Ascii string (readable letters), this has to be done if you want to be able to read the time normally because
GetocalTime delivers the time in a hexadecimal format.

After the time (in hex format) has been converted to a readable Ascii string by GetTimeFormatA we notice how there is 
another call, now this call is not to an API function it goes to the time trial check which finds out if the program is
allowed to run or not. This is how the program looks in softice after we break on GetLocalTime:

00401005  E8A3000000          CALL      KERNEL32!GetLocalTime             
0040100A  6A09                    PUSH      09                  <--This is where we are after breaking and pressing F12              
0040100C  6890204000          PUSH      00402090                           
00401011  6A00                    PUSH      00                                 
00401013  6A00                    PUSH      00                                 
00401015  6800000080          PUSH      80000000                           
0040101A  6800040000          PUSH      00000400                           
0040101F  E871000000          CALL      KERNEL32!GetTimeFormatA   <-This call transforms the bizarr hex time to text         
00401024  E838000000          CALL      00401061 <--This is the call to the actual checking of the time (run or not run)                        
00401029  803D9120400001   CMP       BYTE PTR [00402091],01             

Here is the call that checks if the time is right and the program is allowed to run:
Important note!! The registration flag i speak of is not at all the same as the Zero Flag!! 

00401061  B890204000            MOV       EAX,00402090 <-this moves the address at which the time that we got from
                                                                              <-GetLocalTime and GetTimeFormat is stored into EAX
                                                                              <-not the time itself but the Address   
                                                                              <-type D 402090 here to see what time it is :-)                   
00401066  BB86204000            MOV       EBX,00402086 <-This moves the address of the time to comapare the 
                                                                              <-current time to, the time at this address is hardcoded
                                                                              <-it is only there to for comparing to the time we got above
                                                                           <-type D 402086 here to see when the program is allowed to run                      
0040106B  8B08                      MOV       ECX,[EAX]      <-This moves the content of the Address which EAX is pointing
                                                                             <-now we have the current time in ECX but since ECX or any
                                                                             <-of the four general purpose registers can only store 32 bits
                                                                             <-or 4 bytes we only have the first 4 bytes of the time                      
0040106D  8B13                      MOV       EDX,[EBX]     <-same thing here but with the hardcoded time
0040106F  3BCA                      CMP       ECX,EDX <- we comapare the current time to the hardcoded time                           
00401071  7507                       JNZ       0040107A   <-If the times arent the same the program jumps over the next
                                                                          <-instruction, Jump If Not Zero.                        
00401073  C6059120400001      MOV       BYTE PTR [00402091],01 <-If the times match we set a registration flag
                                                                                             <-this is done by moving 01 into our special flag
                                                                                             <-address, this address is later compred to see
                                                                                             <-if the times were correct when compared.            
0040107A  C3                          RET    <-We return to the main code 

As you can see it is much like the TraceMe2, a flag is set if time match and later compared. This is the actual compare:
Important note!! The registration flag i speak of is not at all the same as the Zero Flag!! 
                                      
00401024  E838000000                     CALL      00401061 <-This is the call we traced above                          
00401029  803D9120400001              CMP       BYTE PTR [00402091],01  <-Our flag location is compared to 01           
00401030  7449                               JZ        0040107B  <- A conditional jump, if flag is set the time is right.

I think you should be able to see quite a few ways of cracking this protection, and thats the whole idea of my page 
i think, many people seem to wanna have you belive the a cracker is always chasing that magic byte that controls
the whole flow of execution, thats not the case, ofte you will find that there are several ways to crack a program
and very little magic about it at all.
Another thing i ahve found is that many people when talking about JCCs (conditional jumps) tend to focus on the
jump, i think that most would agree with me that we instead should focus on the condtion.
If a flag needs to be set, we could just as easy just set it instead of patching the jump and by doing so possibly 
avoid having to patch more jumps if the program does additional checking.

At this point i am tempted to post a small piece i wrote on winrar for some one who asked me about the text at the
top of the window that says "Unregsitered". He didnt know how to remove that, and in fact that had to do with
exactly what im about to describe now. But of course  (since i have promised to not use any real life targets on my
page) i cant post this text, but i can however use TraceMe3 to show you the point of it.

Bpx is very useful and very commonly used in cracking tutorials, i have seen fewer examples of Bpr or Bpm which
are in fact also breapoints and very good ones actually. We will now learn to use Bpr, Bpr means 
Break on Memory range and can be used for flag situations.
look here, when we trace the TraceMe3 we can clearly see at which point the flag is written to its location, so we
knowthe actual location of it right? 
Now if we were able to break whenever something is read or written to this memory location we could easily make
sure that it stays good and remains 01 just like its supposed to for the program to work correctly.
We can do such a breakpoint, the address at which the flag is stored is 402091 and the flag is 1 byte in size.
So we run the program, we break on GetLocalTime and press F12 to get back to the programs code, then we type
Bpr 402091 402091 rw Now lets first review waht this means.
Bpr = break on memory range so we have to give softice a range of memory to break on, in this case the range isnt
very large it is in fact only 1 byte in size (the size of our flag) so we set the start of the range to 402091 but we also
have to tell softice where the memory range ends (thats why we type it twice) so we put as teh end range 402091
since it is only 1 byte. then we have to tell softice under which condtions to break, R means read RW means read and
write and RW means that it breaks either way. There are other paramters you can give it, but we wont go into that
now. So the syntax for Bpr is Bpr 'start' 'end' 'condtions'.

We now have this breakpoint set Bpr 402091 402091 rw and when we press F5 we will break at this location:

00401029  803D9120400001      CMP       BYTE PTR [00402091],01      <--See this is where the the flag is compared                                                                  
00401030  7449                       JZ        0040107B      
                        
I say all this for a reason, many times i have been asked about programs that people calim they have almost cracked
by simply finding the JCC after the registration box, say for instance they type in a registration number and press OK
then they break on GetDlgItemTextA and find a JCC below, they toggle the zero flag (r fl z) and the program displays
a "Thank you for registering" box, but when they restart it its not registered anymore, well how do we deal with it?
One approach could be this, instead of jsut toggling the zero flag or noppin/forcing the program to jump to the 
"Thank you for registering" box we could look at the condtion instead of the JCC.
Often enough it is a TEST EAX,EAX or a compare EAX,01 or CMP EAX,whatever, whatever it is it is handled by a CMP
or TEST, now we should ask ourselves where does the content of EAX (or whichever register is used) come from?
Sometimes there is a call above the compare and if the content of EAX isnt explained right before the jump the
answer is likely to be in the preceeding call.

First we need to find out what the result should be, if there is a TEST EAX,EAX it simply checks if EAX = 0 or not
if EAX = 0 the zero flag is set (please note that te zero flags or other flags in the flag register is not at all the 
registration flag, the registration flag is a completely different thing)
If after a TEST EAX,EAX there is a JZ and the program jumps to a "Wrong serial" box it is safe to assume that
EAX at the time should be something other than 0.
Anyway, if you look inside the call before the CMP or TEST or even sometimes above the JCC you can often find
that something is written or read from a memory location to set EAX (or whichever register used in the CMP or TEST)
If something is read lets say it reads 0 from the location we can assume that is we change the value which is read 
into 1 or 58 or whatever is not 0 the program will beave differently.
Sometimes the program will onyl accept a specific value and sometimes any value but 0 will work fine.
Now if we change the value at this address before the JCC we will stil get a  "Thank you for registering" box but we
would have done something more clever than just invert a jump.

I think/hope you have already figured out what we can do now, if we set a bpr on the memory location that sets EAX
to the value we want/dont want we can check the registration flag at startup.
if we set a Bpr address address rw we can see when the program reads or writes to this address, and if we exit the
program with our bpr still left and tehn run it it will break just fine.
Now we type D address (the address of our suspected registration flag) and see what the value is at that location.
Lets say that it is 0, if we now change it to 1 and press F5 there is a chance that it will appear registered.
if its not, we can go back to the registration routine, and trace a little more, maybe we can find more clues on
why this particular memory address had been set to 0 and where the decision is really made, once we find a new
suspicious location we jsut make a new bpr address address rw and restart the program.

Important note on breakpoints on memory ranges and on addresses, you need to put the when the program is running.
a good way to do it is to run the program and just break on just about anything, could be a messagebox or whatever.
then F12 so you get back to the program code, and once inside the running code you set your bpx or bpr or bpm.
Now if you restart the program Sofitce will remmeber in which module (program) the bpx or bpr was set, and it will
work nicely.
You cant set a bpx on something that isnt loaded into memory, thats why you need to set it while the bpr while the
program is running.

Ok im tired again, off to bed.
i will write again later (i hope)