mCHAPTER 4 WALK THROUGH OF AN EASY CRACK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
First of all, I want to go over some of the criteria I used in choosing the
program I used for the walk through. An important factor was the programs
size. I want to keep this manual as small as possible, and I chose the program
that is included in this guide because among other things it is the smallest
one I could find that best illustrated the example of a simple nag screen.
Whether or not the program was one that you would actually find useful was not
a consideration, as you should eventually be able to crack just about any
program you wish if your serious about cracking. If you come across a program
that has you stumped, leave it alone for a while and then try again after
you've cracked something else. You may find that whatever you were having
problems with is now easier to understand.
Before we start I want to go over one other thing. When you load a program
into a debugger, the debugger will load the program and halt at the very first
instruction to be executed within the program. You can also at this point let
the program run normally and then break back into it at a later point.
When you use the second method it will halt the program at the current
instruction and return control to the debugger, but you may not end up in the
program itself. You could have broken into the program while it was in the
middle of executing either a DOS or BIOS interrupt, and the code you are in
belongs to either DOS or BIOS and not the program you are debugging.
You can tell by looking at the addresses of the instructions in the code
window where you are, low segment addresses indicate you are in DOS, and
addresses that start with FXXX indicate a BIOS routine.
If you break into the program while it is in one of these interrupt routines
you will have to trace your way back into the programs code, this will usually
be indicated by an IRET (interrupt return) instruction. When you do get back
to the program code, you will then have to trace your way back to the top of
the call that issued the interrupt you broke into. Then you may also have to
trace back to the top of that call, and to the top of that call, etc etc,
until you reach the top level of the program. After you've done this a few
times you'll begin to recognize when you've gotten back to the main flow of
the program...
On the other hand, when you load a program into the debugger and begin
stepping through the code from the very first instruction to be executed
within the program, you have the best picture on the overall flow of the
program as you are sitting on top of everything.
But some programs don't access the copy protection until they are further
along in the code. In this case, it's best to let the program run normally and
then break into it at a later point. Otherwise, you will have a ton of code to
trace through before the protection routine is accessed, and this can become
quite tedious. Which method you choose will be determined after you've run the
program through a few times and decide how and where you want to break into
it.
One last thing, DOS will always load a program into the same memory range
provided that no other programs are run in the interim. It's important that
you always boot with the same config files and don't run any other memory
resident programs between cracking sessions.
If you load a program into the debugger and start tracing, then quit. And
before The next time you load that same program into the debugger, you boot
with a different config or load a memory resident program that you didn't have
loaded the first time you started cracking that program, the segment addresses
will change and the addresses you wrote down will be useless. This is because
the memory map of your computer will change.
When I boot with my debugging config (when I use my DOS debugger, Windows
manages memory differently and these steps are not needed), the only things I
load are a mouse driver, 4DOS, my debugger and ansi.sys (needed for cracking
bbs doors). This way I'm assured that the program I want to crack gets loaded
into the same memory region every time I run it, providing I don't run any
other memory resident programs before loading the program to be cracked into
the debugger.
Take soft ice as an example, if you load a program into it using LDR.EXE and
begin debugging, then later on you decide to just execute the program and
break into it without first loading it with LDR.EXE, the segment addresses
will change. That's because LDR.EXE is a program and using it will throw the
segment addresses off by one word as opposed to just breaking into an already
running program without first loading it with LDR.EXE.
The program we will crack is budget minder, it is an extremely simple crack
(it took me about 2 minutes to crack it) and is ideal for the lesson on how to
remove nag screens from otherwise fully functional programs. It also deals
with intrasegment calls, so it serves a dual purpose. That's another reason I
chose it for the lesson.
From now on, when I say step, step through, or step over, I want you to use
the SINGLE STEP key. When I say trace, I want you to use the TRACE key once
and only once!!!! The TRACE key is a highly specialized key and is not
intended to be used multiple times like the SINGLE STEP key. If you don't
follow these instructions, your gonna get lost...
OK, once you've run budget minder a few times you will notice that it displays
a nag screen before the main program is executed. You will also notice that
this nag screen is the only type of protection that the program has. It
doesn't contain any features that are disabled, nor does it display an
additional nag screen upon exit.
It's okay to apply a dirty crack to this program as all you want to do is kill
the nag screen, so you have a little more leeway on how to patch it. And if
you want to try different methods of patching it than the ones I give, it
should still work fine.
That was the most important factor in my decision to use this program for the
lesson. I wanted to walk you through a program so you would become comfortable
with it's flow, and I also wanted the program to be easy enough so that once
you became familiar with it, there was enough room for you to experiment and
try out your own methods.
In this case, it's best to load the program into the debugger and start
stepping through it right away. The protection is implemented very close to
the beginning of the program, and this method of loading the program will put
you right on top of everything.
Allowing the program to run and breaking into it later on will not serve any
useful purpose. You'll just end up having to trace your way back to the top.
Besides, the nag screen comes up so fast you'll probably miss it if you try
the second method anyway.
Before you load it into the debugger, run UNP on BUDGET.EXE... AHA! The file
was compressed with EXEPACK. It's now ready to debug as you've removed the
compression envelope. Just for the hell of it, run UNP on it again. I've come
across a few programs that have had multiple compression routines on them. If
it shows up negative, your set to go.
Now load BUDGET.EXE into the debugger, the program will be sitting at the
first instruction to be executed awaiting your next command... Use the SINGLE
STEP key to start stepping through the code and keep an eye on the
instructions as you are stepping through them.
Shortly you will come to a couple of calls, before you step over the first
one, write down it's address. Now step over the first call with the SINGLE
STEP key. Nothing happened, so you have to continue stepping through the code.
But if something did happen when you stepped over this call like the nag
screen being displayed or if you lost control of the program, you could just
reload the program and issue the GO TO command to get back to that point using
the address you wrote down.
Step over the second call, nothing again. Ok, keep stepping through the code
and keep an eye on the instructions. You will encounter a third call about 6
instructions or so after the second call, step over it with the SINGLE STEP
key... Bingo, you have found the call to the nag screen. Hit a key to exit the
nag screen and you will now be sitting in the main program screen.
But you no longer have control of the program. Remember I said you would loose
control if you step over a call loop or interrupt and the program never
returns from it? Hopefully you wrote down the address of that last call before
you executed it. Now you can just quit out of the program and reload it. Then,
once it's reloaded, issue the GO TO command to get back to the call without
having to trace your way back there. So go ahead and do this before reading
on...
Ok, we are all back at the third call. It's address will be CS:0161, remember
that the segment adresses will always be different for every computer, but the
offsets will be the same. So from now on I'll write the addresses in that
manner...
We know that the last time we executed this call, the program never returned
from it. So now we are going to have to trace into it for a closer look. Trace
into the call with the TRACE key, don't use the SINGLE STEP key this time or
you'll loose control again.
You will now be inside the code for that call, start stepping through it again
with the SINGLE STEP key, you will see some calls. Better write down your
address before you step over them.
Step over the first two calls, nothing... Use the RESTORE USER SCREEN key to
toggle the display between the debugger and the program. Still a blank screen,
so nothing important has happened yet. Now toggle the RESTORE USER SCREEN key
to get the debugger screen back and continue stepping through the code.
You will see another call and some more code, just step through them until you
reach the RETF instruction and stop there. Toggle the display with the RESTORE
USER SCREEN key, the screen is still blank...
But we executed all of the code within the call and are ready to return
without anything happening. The nag screen didn't get displayed nor did we
loose control and end up in the main program, How come?
Step over the RETF instruction with the SINGLE STEP key and you'll see why...
The address that we return to is not the next instruction after the original
call. Part of the code within the call we traced into revectored the return
address for the original call and sent us to an entirely different location
within the program.
This is why we lost control when we first stepped over the call, the debugger
was expecting the program to return to the next instruction after the original
call, but it never did...
So the instruction that we returned to was not the original line of code that
was expected, instead we are at another far call. If you haven't gotten lost
you should be at CS:0030 CALL CS:28BC.
Write down the address of the CS:IP and then step over this call with the
SINGLE STEP key, there is that annoying nag screen again. Hit a key to exit
the nag screen and control will be returned to the debugger. This time the
program returned from the call and you are in control again. So you now know
that this call is the one that displays the nag screen and it is the one you
want to kill.
Hit the RUN key and let the program run, now quit out of it from the main
program screen and reload it into the debugger. Use the GO TO command and
supply it the address for the call to the nag screen.
Ok, now lets see if the program will run or not if we don't execute the call
to the nag screen. The call is at CS:0030 and the next instruction after the
call is at address CS:0035... A quick way to jump past this call without
executing it is to just increment the instruction pointer register to the next
instruction.
In this case we want to manipulate the IP register, and we want to set it to
point to the instruction at CS:0035 instead of the instruction it is currently
pointing to at CS:0030. You are going to have to figure out the command on how
to do this with the debugger you are using yourself.
If you are using turbo debugger, place the mouse cursor on the line of code at
CS:0035 and right click the mouse. A window will pop up, then left click on
new IP, or increment IP. If you are using soft ice, type rip=0035 and hit
enter. Any other debugger, I have no clue...
Now that we've moved the IP past the call to the nag screen let's see if the
program is going to run. Hit the RUN key, this time the nag screen doesn't
come up, instead you are brought right into the main program screen.
It looks like getting rid of that call is going to do the trick. Now that we
know the program will run without making that call, it's time to decide on how
to patch the program so the call is never made again.
Think back to the original call we traced into for a minute, that call was the
one that revectored the return address and brought us to the call to the nag
screen. Therefore, it's reasonable to assume that that call is the protection
check, and it might be a good idea to have another look at it.
Before we do that there is one other thing I want to show you, and that's how
to allow the program to make the call to the nag screen and return from the
call without executing any of the code contained within it.
This isn't the method we will use to patch this program, but it's an important
concept to grasp as you'll end up doing it sooner or later on some other
program anyway. Remember that this is a far call and you can't just nop it
out.
Quit the program, reload it, and get to the address of the call to the nag
screen. Last time through we just incremented the IP to bypass it. Now we will
trace into it to see what it is doing.
Hit the TRACE key and trace into the call. Now start stepping through it with
the SINGLE STEP key, don't bother writing any addresses down for now. There
are several dozen calls in this routine along with shitloads of other code.
Toggle the display with the RESTORE USER SCREEN key after you step over a few
of the calls and you will see that the program is in the process of drawing
the nag screen.
Keep stepping through it and you'll see more and more of the screen being
drawn as the code progresses. This is getting boring, so stop stepping through
the code and start scrolling the code window down with the down arrow key and
watch the code. If you are using soft ice, the F6 key toggles the cursor
between the code and command windows, and the cursor must be in the code
window in order to scroll it.
What you are looking for is the RETF instruction as this is the end of the
call. Keep scrolling, I told you this call had a ton of code in it. When you
do find the RETF instruction write down it's address, it is CS:2B0E in case
your having trouble finding it. Ok, you've got the address of the RETF far
instruction written down so now just let the program run, quit out of it,
reload it, and get back to the call for the nag screen.
You should now be sitting at the call to the nag screen, trace into it and
stop. The first instruction of the call is MOV CX,0016 and this is where the
CS:IP should be pointing to. What we want to do now is to jump to the RETF
instruction and bypass all of the code within the call itself. So let's
re-assemble the MOV CX,0016 instruction and replace it with a new one.
First, make sure you are at this instruction, if you've traced passed it your
gonna have to reload the program and get back to it... OK, we are all sitting
at the MOV CX,0016 instruction and it's address is contained in the CS:IP
registers.
Now ASSEMBLE JMP 2B0E (the offset address of the RETF instruction) and specify
the address of the CS:IP. The MOV CX,0016 instruction will be replaced with
JMP 2B0E. And seeing as how both of these instructions are the same length we
didn't have to pad it out with any nop's.
Now hit the RUN key, you are brought into the main program and the nag screen
didn't get displayed! We allowed the program to make the call, but we didn't
allow any of the code within the call to be executed. And as far as the
program is concerned, it made the call and the nag screen was displayed.
Now let's go back and take another look at the call that we suspect is the one
that contains the protection check itself. Reload the program and go to the
original call that revectored the return address, now trace into it. I've
traced into the calls that are contained in here and they are setting up the
addresses for the RETF instruction at the end of this call among other things.
You don't need to trace into them as you might not understand what's going on,
but if you feel up to it, go right ahead.
What I want to concentrate on are the last four lines of code in the call as
they are the ones that finally set up the address to return to. Step through
the code until you are at CS:00A8 and take a look:
CS:00A8 8B04 MOV AX,[SI] DS:SI=0000
CS:00AA 053000 ADD AX,0030
CS:00AD 50 PUSH AX
CS:00AE CB RETF
The first instruction is loading the AX register with the contents of the
memory location that the SI register is pointing to. And you can see by
looking at the memory location that the DS:SI pair is pointing to that it
contains 0000. (this is where the display command and data window come in
handy).
The second instruction is adding 0030 to the contents of the AX register.
The third instruction is placing the contents of the AX register onto the top
of the stack.
The fourth instruction is returning from the call, and where do you think that
the RETF instruction gets the address for the return? Yep, you guessed it, it
gets it off the top of the stack. Funny that the instruction right before it
just placed something there isn't it?
Also funny is that it happens to be the address of the nag screen. Look at
what is being added to the AX register on the second line of code. Boy that
sure looks like the offset address to the nag screen to me.
Remember that the next instruction after the nag screen is CS:0035, now look
at the first line of code. The contents of the memory location it's
referencing contains 0000, and I'll bet that if your copy was registered it
would contain 0005 instead.
Why? because if the first instruction placed 0005 in the AX register, when the
second line of code added 0030 to it, you would end up with 0035 which happens
to be the address of the next line of code after the nag screen.
Then the third instruction would place 0035 on the stack and that is where the
RETF instruction would go to. If this were the case, the nag screen would
never get displayed...
Well, what do you think we should do? We could trace further back in the
program and try to find the instructions that place 0000 in that memory
location and modify them to place 0005 in there instead, but this process is
somewhat involved and I don't want to throw too much at you at once.
Instead, I have an easier solution. Seeing as how the memory location will
always contain 0000, why don't we just change the ADD AX,0030 instruction to
ADD AX,0035? This should get the correct address placed on the stack for the
RETF instruction to bypass the nag screen...
Let's try it and see how it works. SINGLE STEP through the code until the
CS:IP is at the instruction ADD AX,0030. Now, ASSEMBLE the instruction to read
ADD AX,0035 and hit the RUN key. We are placed in the main program screen
without any stinkin' nag screen getting displayed!
Congratulations! you have just cracked your first program :) Try other methods
of patching the program besides the ones I went over. The next chapter will
deal with how to make the changes you've made permanent.
s Guide to Cracking post-3
No comments:
Post a Comment