We’ll start with downloading and compiling the challenge, then we’ll start solving it. Our first solution will be a buffer overflow vulnerability intentionally coded into the challenge, then we’ll hunt down and execute a secret function to solve the challenge, and finally we’ll execute the program instruction to instruction until we can read the solution straight out of the computers memory! Now that we know what we’ll be doing, let’s get started!
Downloading and Compiling the Challenge
First, we need to download and compile the code of our challenge. Let’s download the challenge code from pastebin using the curl command:
We’ve written the code to a file named crackme.c. Now that we have our code, we need to compile it. We’ll be using the GCC (GNU Compiler Collection) to compile our code. Pay close attention to the flags used when compiling our code, as they are important to the challenge functioning properly:
You may get a warning out of the compiler but don’t fret, the code will still work (this warning is related to the buffer overflow vulnerability, which is intentional). Let’s test our executable just to make sure it works:
Now that we have our code compiled and working, we can start cracking this challenge! We’ll start with the buffer overflow vulnerability.
Cracking the Challenge
Solution 1: Buffer Overflow
Buffer overflows are very common vulnerabilities. A “buffer” is simply an area of memory designated for storing data to be processed or used in processing. If we can fill a buffer with more data than it can handle, we “overflow” it, and can then store data in areas of memory where we shouldn’t be able to. This can lead to code execution, which is how a lot of buffer overflow exploits work. But, in our case, we’ll be overflowing a buffer simply to change the value of the data being held in another.
Let’s perform this attack, and then we’ll take a look at the code that makes this possible:
We can see here that by entering a large amount of text, we can successfully login even when this is obviously not the correct password. Now that we’ve exploited our buffer overflow, let’s take a look at the code that made this happen:
We can see here that we make a character array that holds 30 characters. So, if we input more than 30 characters, that will overflow this buffer, which will change the value of the “valid” integer. This integer is then evaluated later in the program and, since the overflow changed it to a non-zero number, it equates to true and logs in without a problem. Next up, we’ll be hunting for a hidden function in our program!
Solution 2: Using the Hidden Function
If you read the code of our challenge, you’ll that there is a function named “secret.” This function is never used, yet it still exists. If we can force this function to execute somehow, we could get the password we need. Well we have just the tools to do that! First, we need to use a tool called objdump (object dump) to disassemble our executable into assembly. Then we’ll be able to see where our secret function is:
Now that we have our new assembly code in a text file, we can sift through it until we find our secret function. It should be just above the main function, and looks something like this:
Now, don’t panic, this looks way more complicated than it is. The only part of this assembly we need to pay attention to is the string of characters next to the word “secret.” Specifically, we need to remember the last 7 characters, as this is the entry address for this function. Now that we have this 7 character string, let’s start our program in GDB and do some magic:
No need to pay attention to this large chunk of text, it’s mostly just information about GDB. But here’s the important part: when GDB starts up, we need to use the start command in order to start our program. Now, remember that 7 character string? This is where we’ll be using it. If we can change where the instruction pointer is pointing, we can force it to execu