Target : ThoughtSpeed
Purpose : This is the second lesson in using self modifying code, a bit more difficult than the first essay.
Approach : This program is a demo, with an annoying 10 second nag/splash screen when you start it up, and one when you
exit the program. We will be removing these.
Tools : SoftICE, W32Dasm, Hiew & ProcDump.
As with the last program, this is not going to be an easy 10 second crack. Its going to take you a while, but your time will be well spent, because you will be able to use this technique to patch many programs that normally would have required you to make a loader.
So lets start up the program to get a good idea on what we're up against. Might as well grab a beer while you are waiting on the splash screen to die, cause it takes forever. OK, as we run through the program we notice that there are no feature restrictions or nags while running the program, this is good. So now we go and exit the program and ack, another nag asking us if we'd like to register or press OK to exit.
The first thing we are gonna do is kill that annoying splash screen. So lets start this program up in SoftICE's symbol loader and start doing some tracing to see if we can find where that nag is created. As you are tracing, you will come upon a call at 4E546E and as you step over the call, you will be kicked out of SoftICE for about a second, and you will see the creation of the nag. This is where we want to go, so we set a breakpoint on that call by typing:
When SoftICE breaks on that location, you should follow the call with F8 and start your tracing again with F10. You don't have to trace for long before you step over the right call at 44CA93. So Ctrl+D out of SoftICE and exit the program and start it again with the symbol loader. make sure you clear all your breakpoints by typing:
Now you can set your new breakpoint at 44CA93. When it breaks, follow that call with F8. As soon as you follow that call you will come upon these lines of code:
:004498D0 PUSH EBX
:004498D1 PUSH ESI
:004498D2 MOV EBX, EDX
:004498D4 MOV ESI, EAX
:004498D6 TEST BYTE PTR [ESI+000002C0], 01
:004498DD JE 004498F6
:004498DF TEST BL, BL
:004498E1 JE 004498EC
:004498E3 OR BYTE PTR [ESI+000002C0], 02
:004498EA JMP 0044990F
Hmmm very interesting, the JE at 4498DD has the zero flag set,
so it will jump to the code where the nag is created. Lets invert
the zero flag by typing:
r fl z
Now start tracing with F10 and we pass the JE at 4498E1 without jumping, and we hit the JMP at 4498EA and we press F10 one more time and we see a RET at address 449911. YES! so we Ctrl+D out of SoftICE and the program loads without the delay of the first nag/splash screen. Now we know exactly where we need to patch to kill the first nag. But we can't simply use a direct patch because this piece of code is used by the program many times, so it will mess up. We need some self modifying code.
Now probably the hardest part of cracking this program comes
into effect. Finding a spot to add our self modifying code. So
lets do a text search for:
ADD [EAX], AL (opcode 0000)
We are gonna need a fairly large amount of useless space like this to add our code. It isn't long before we find what we're looking for at around address 406EE5. This is where we will add our code. The first thing we need to do is make the program jump to this location back at the JE we want to change. So we go back to address 4498DD and right down the opcodes for the next couple of lines. 741784DB7409808E will be sufficent enough for our purposes. So lets change the JE at 4498DD to a JMP 406EE5 (opcodes E903D6FBFF).
Also, to keep things neat, we should put a NOP at 4498E2. Now we can add our self modifying code. First we need to have the program replace the bytes we just changed, back to its original state. We can do this as follows:
MOV DWORD PTR [4498DD], 0DB841774 <-- Remember to
list the bytes in reverse.
The opcodes for this line are: C705DD984400741784DB
But we aren't done yet. That is only about half of the code we replaced, so we need to add another line:
MOV DWORD PTR [4498E1], 08E800974
The opcodes for this line are: C705E19844007409808E
Now we just need the program to jump back into its normal routine. There really are several places we could jump to, but I'm gonna go ahead and choose JMP 44990F (read the pasted code above) The opcodes for this jump are E9112A0400.
Now we have our first nag screen patched, so lets run the program
and see how it works. Ah, but we forgot to change the code section's
characteristics to allow both reading and writting. So lets load
the program up in ProcDump's PE editor and change its characteristics
from: 60000020 to C0000040.
Lets run the program now, no longer is there a long delay in the program loading up, even though the nag still flashes for less than a second, the program is loading instantly. GREAT!!! the first nag is dead. But, for some reason, it will only run once (at least on the two computers I've patched it on). After that when we try and run the program nothing happens? It just doesn't load up at all. Could this be a checksum of some kind? I could spend an hour speculating on this, but I won't, I'll just tell you how to fix it.
Load the program in the Symbol Loader and start tracing with F10 untill you come across a JNE at adress 4E5445. If your memory is good enough, you'd remember that this jump was never executed before, but if your memory is poor, like mine. You should notice that the JNE is wanting to jump to a piece of code far below where the program's nag was created and below where the program itself loaded up. All we need to do is NOP that JNE out and the program will load up like normal everytime. Now we need to focus our attention on the second nag, which I'm sorry to say, is going to be a bit more difficult.
So far in this essay and in the last, all that I've explained is how to use self modifying code for nags at the beginning of the program. But if the nag is at the end of the program, and as with the other nags, the program uses the same code to create/destroy that nag as it does with every single other dialog in the program? The solution isn't too difficult, we just need to put a comparison of some kind in our added code to make sure we patch the right dialog.
The first thing we need to do is figure out where in the program
the last nag is being created. This isn't too hard of a task.
Run the program, then after it loads up, Ctrl+D into SoftICE and
Now Ctrl+D out of SoftICE and hit exit on the program. You'll be popped back into SoftICE inside user32.dll, we don't wanna be here so we press F11 to break again. This time we break in the programs code at address 44C69B. Lets trace a little bit by pressing F10. After a little while we come across a JE at adress 44CC91. Lets invert the zero flag to see what happens. The program exits without you having to click OK on the nag. This is what needs to be patched. But as with the code above, if we patch it, it'll mess up the rest of the program. So lets load the program again, and again set a breakpoint on showwindow. Once again exit the program. Once we break on our programs code. Make note of the value in the register EBX. The value is 4D1D14. This is VERY important for when we add our self modifying code, basically what we will be doing is at the jmp you just broke on, we'll change it to jump to a piece of worthless code (where we'll add our new code) then we'll add a CMP EBX, 4D1D14 and a JNE back to the normal routine of the code. We will have this there in case the program is using that particular piece of code for other dialog's. If they are the same, and the program doesn't jump, then it will go into its patching routines and that, theoretically should kill the nag.
Probably the hardest part now is figuring out where to add our new code. I'll save you the time and hassle of searching by telling you to add it at address 47600B. Now we need to make the program jump to that location while the nag is being created. Remember when we broke on showwindow? we landed right on a JMP. This is a perfect place to put our jump. Just be sure to write down the memory address it was originally jumping to, which is 44C7A5. Now change that JMP to a new JMP 47600B. The opcodes for that JMP are E96B990200.
Now we need to add our new code starting at 47600B. Remember
I said we are going to need to put a comparison in to make sure
we patch at the right time. And that the comparison was:
CMP EBX, 4D1D14
So we add that line at address 47600B. The opcodes for that line are 81FB141D4D. Now we need the program to jump if they are not equal and we want it to jump back into its normal routine. So we'll add a JNE 44C7A5 at address 476011. The opcodes for this are 0F858E67FDFF. That will make the program return to its normal routine, without any patching, if it is not exiting. But if it is exiting, we want it to patch itself. Remember the JE that we inverted at 44CC91? Well we need that to be patched so it never jumps we can do that by simply changing the 740F to a 7400. But remember, directly patching will mess it up, so we need to add self modifying code to patch it for us. So right under that JNE that we just added, we need to add this line:
MOV BYTE PTR [44CC92], 00
The opcodes for this line are: C60592CC440000
Now the program will patch itself when it gets to that line and we just need it to jump back to its normal routine. So we add a JMP 44C7A5. The opcodes for this jump are E98267FDFF. YES!!! The program is now fully cracked and ready to be fully evaluated.
Well there are a great many programs that have nags that we can kill with this technique. Hopefully everything was explained clearly enough for you to understand how to use it & don't forget, if you like this software, please support the author by purchasing a legal copy. If you don't, they might stop making programs for us to crack, and that would be no good.
Greets (so many friends, please don't get mad if I left you out) :-
AB4DS, Torn@do, Kwai_Lo, Killer_3k, CrackZ, N0-B0dy, Azir, Darkie, Data_, Bud-, all the guys in #cracking4newbies, #shock, and #hlm2k.
Essay by Kathras.