Reverse Code Engineering
Saturday, October 28, 2006
As I spent the whole holiday sick at home, and I got no chance whatsoever to go outside (except for the last couple of days maybe), I had enough time to finish off all the work and the things I was planning to do on my computer. Many projects from the old days, each in a separate folder, were waiting on my desktop for me to have enough time to resume digging into.
Out of boredom, I decided to dig up something I barely got into previously: Reverse Code Engineering; the art of breaking into executable files and modifying their machine code to obtain different execution behavior.
If you have ever installed or used unlicensed computer software before then you, probably, have used reverse-engineered programs at some point; the illegal ones of them ... Cracks!
Software Cracks are modified software executables that have been reverse-engineered by crackers to deactivate product registration, activation, limitations, and nagging screen routines. The cracked or “patched” program works as good as a full/registered version. It has been altered at the machine language level to do so.
Long before, I made a very basic, yet interesting, experiment in this regard. I coded and compiled a simple C++ program, then started analyzing and messing with its machine code using disassemblers and hex editors. The first program was actually something like this:

These four lines of C++ were compiled into some hundred lines of assembly. I used a disassembler to trace down the string “Password Correct” and look up the instructions that reference the memory location it was being held in.
I came up with the following machine code and assembly listing:

The CMP instruction was comparing a certain value in memory with 7Bh (which is equal to 123 in decimal). The second JNE (Jump if Not Equal) instruction made the program branch at that point to one of two paths, depending on the result of the previous comparison.
Using a hex editor, I replaced 75 (op-code for JNE) with 74 (op-code for JE) which is the opposite instruction. The program (now cracked :P) started to output “Password Correct” for any user-entered password EXCEPT 123 :D
That was the very first experiment, and I was really glad it worked!
In the previous days, I made more tests and came out with much complicated tricks. Instead of reversing IF statements, I tried jumping (using the JMP instruction) to the code right inside the IF statement, trying to bypass the evaluation of the condition, and it worked! :D
My friend Zeid had an interesting argument over jumping and bypassing sections of code. He said that jumping can’t always be the solution because sometimes you skip code that is essential for the proper execution of the program. That was definitely correct, but I actually found a way to do the jump safely!
The “dangerous” jump was tried on the following program:

My target was to make this program call the function secret() with x=17 immediately at startup, i.e. not to even request user input. I wanted to wipe out the user-input section and remove the limitation of x having to be less than 5.
What I did was overwriting the cout and cin assembly code sections with NOP (No Operation) instructions (a cool way I came up with to “comment-out” those sections :P) then replace some of those NOPs with the following assembly instructions:

Carefully tried that, and yup … it WORKED! :D
That was a “dangerous” code jump of my side, but I did good I guess! :P
Coding my own assembly into that EXE and observing how it worked was one of the most enjoyable things I’ve ever done in my life!
Next am trying to crack, e7m … “Reverse Engineer” some old DOS shareware, wait for the results ;)
Out of boredom, I decided to dig up something I barely got into previously: Reverse Code Engineering; the art of breaking into executable files and modifying their machine code to obtain different execution behavior.
If you have ever installed or used unlicensed computer software before then you, probably, have used reverse-engineered programs at some point; the illegal ones of them ... Cracks!
Software Cracks are modified software executables that have been reverse-engineered by crackers to deactivate product registration, activation, limitations, and nagging screen routines. The cracked or “patched” program works as good as a full/registered version. It has been altered at the machine language level to do so.
Long before, I made a very basic, yet interesting, experiment in this regard. I coded and compiled a simple C++ program, then started analyzing and messing with its machine code using disassemblers and hex editors. The first program was actually something like this:

These four lines of C++ were compiled into some hundred lines of assembly. I used a disassembler to trace down the string “Password Correct” and look up the instructions that reference the memory location it was being held in.
I came up with the following machine code and assembly listing:

The CMP instruction was comparing a certain value in memory with 7Bh (which is equal to 123 in decimal). The second JNE (Jump if Not Equal) instruction made the program branch at that point to one of two paths, depending on the result of the previous comparison.
Using a hex editor, I replaced 75 (op-code for JNE) with 74 (op-code for JE) which is the opposite instruction. The program (now cracked :P) started to output “Password Correct” for any user-entered password EXCEPT 123 :D
That was the very first experiment, and I was really glad it worked!
In the previous days, I made more tests and came out with much complicated tricks. Instead of reversing IF statements, I tried jumping (using the JMP instruction) to the code right inside the IF statement, trying to bypass the evaluation of the condition, and it worked! :D
My friend Zeid had an interesting argument over jumping and bypassing sections of code. He said that jumping can’t always be the solution because sometimes you skip code that is essential for the proper execution of the program. That was definitely correct, but I actually found a way to do the jump safely!
The “dangerous” jump was tried on the following program:

My target was to make this program call the function secret() with x=17 immediately at startup, i.e. not to even request user input. I wanted to wipe out the user-input section and remove the limitation of x having to be less than 5.
What I did was overwriting the cout and cin assembly code sections with NOP (No Operation) instructions (a cool way I came up with to “comment-out” those sections :P) then replace some of those NOPs with the following assembly instructions:

Carefully tried that, and yup … it WORKED! :D
That was a “dangerous” code jump of my side, but I did good I guess! :P
Coding my own assembly into that EXE and observing how it worked was one of the most enjoyable things I’ve ever done in my life!
Next am trying to crack, e7m … “Reverse Engineer” some old DOS shareware, wait for the results ;)

