Cracking using gdb

Posted by Marcus - August 24, 2023

Say I have a program, creatively called "Program.exe", that I would like to run. Unfortunately, the program requires a license, oh marmalade. 

Long story short

./Program.exe

gdb --write -q ./Program.exe
set *0x11ca = 0x00b89090
q

./Program.exe

End of post :)

Going deeper

The objective of this post is to show, step by step how to do reverse engineering to crack a program. This is obviously not something you should do on real, licensed, programs, so follow along with my (contrieved) toy example here or try out https://crackmes.one/

Now, there are many good guides on the internet on the subject of reverse engineering but I found this video a nice introduction

The video shows, in some detail, how to use a debugger (gdb) to enable skipping a license check. What it does not explain, however, is how to modify the compiled bytecode and permanently store the crack. This post will detail that. 

The tools

There are paid and free options to choose from. I like free stuff, so this was my setup

I used Windows Subsystem for Linux (WSL) to get a Linux (Ubuntu) terminal up and running while booted into Windows for convenience sake. 

The steps

  • Find out where the license is checked 
  • Find out which instructions are needed to circumvent the check
    • Preferably without changing the total bytesize of the executable, since the file header would then need to be changed.
  • Replace the instructions 

Where is the license check?

I basically single stepped using gdb, looking out for all the calls and especially jumps since these would potentially be candidates for the license function calling and the subsequent checking of the license. The steps for doing that is clearly laid out in the above video but in short, these are the commands (feel free to follow along using the toy example)

Start by opening Program.exe in gdb

gdb ./Program.exe

Then set a breakpoint. There's most probably a main function so start out by setting a breakpoint in the beginning of main, set layout to asm, which will show the current program counter, i.e. where you are in the code and finally run it

b *main
layout asm
run

The breakpoint in main will be hit.

Following that I single-stepped through the code using ni while si can be used to step into a call.

The jump

Program.exe is rather explicit with a call to check_license followed by an interesting jump. Turns out, this is the exact place where the license is checked

I want this check to always pass to the code right below since it references print_license_ok. Thus I want to skip the jne instruction entirely, so I need to replace it with a nop, i.e. basically do nothing. Looking up these opcodes in the list of assembly instructions gives me NOP = 90 and JNE = 75 cb, where cb is the number of bytes to skip ahead.

Cracking it ! 

Now, I used gdb again to get the full disassembly of the function in question, using these commands

gdb --write -q ./Program.exe
disas/r main

Returning to the relevant jump, the opcode is correct, 0x75, followed by 0x16 = 16. Essentially the 0x16 means: jump 16 bytes ahead (relative to current address, i.e. 0x11ca + 0x2 + 0x16 = 0x11e2 where the 0x2 is because the jne takes up two bytes).
The disassembly kindly shows us this ends up at 0x11e2 <main+60> i.e. the section containing a call to print_license_wrong. Yikes, we don't want to go there! 

Thus, we want to continue uncondinationally, without jumping anywhere. For this, we simply need to replace those two bytes with nops. (Two since I try to avoid altering the total size of the bytecode).

set *0x11ca= 0x00b89090

Note that I am setting 32bit (4 bytes) at a time with this command. Thus it is important to keep the 00b8, to avoid changing the line right below the nops. One final thing to notice is the endianness of the hex value to set. In my case, little endian.

Now, doing the disassembly again, we now see 

Which is exactly what we wanted to see: the program is cracked.
Remember to issue the final q command to save the changed bytecode.

Really, that's it?

Well, yes. Testing it out we now get 

./Program.exe

Which is what we wanted. 

Outlook

Obviously this rather contrieved toy example is really simple with nice calls making the original c code and the disassembly almost equally readable (check github).

Nevertheless these methods are known to be effective on real world programs too, using similar concepts and techniques so get cracking!