Reverse Engineering Challenge - Racecars

Reverse Engineering Challenge - Racecars

Introduction

Hey! Once again we have another reverse engineering challenge. This one is called racecars from the website crackmes.one. The author doesn't provide any hints or constraints regarding the challenge so it seems anything is fair game! This challenge isn't terribly difficult so we should be fine with some basic static analysis. If you want, you can check out the video tutorial on my channel.

Racecars Video Walkthrough

Optional Materials to Follow Along

If you want to follow along feel free to download the VM I provide. You can find instructions on importing the VM here. If you don't want to use my VM that's fine, my feelings won't be shattered. But you will at least need the binary. You can download the binary here. The binary comes in a password protected zip file. The password is: crackmes.one.

You'll also need a disassembler. I recommend IDA or Ghidra. With all of that out of the way, let's get reversing!

Initial Triage

Let's start out by running file on the binary.

File output
File output

Would you look at that! Not only is this binary not stripped but there are debug symbols! Sweet! Let's go ahead and look at the symbols!

nm output
nm output

Nothing really stands out here. Let's go ahead and take a look at the strings.

Strings output
Strings output

Again we don't get much information from the strings. We do see some output from the program. So, we don't have much information about this binary so let's go ahead and open this up in IDA.

Static Analysis in IDA

Main function pt. 1
Main function pt. 1

The great thing about having debug symbols is we don't have to worry about renaming any variables because they'll already have names. So, this allows us to get a feel for what the author was trying to achieve and the purpose of a given variable. We see that the program starts by grabbing the length of argv[0]. It then subtracts 1 from the length and stores that in the end variable. This is equivalent to end = strlen(argv[0]) - 1. It then stores the end in the start variable. So, at this point start also equals strlen(argv[0]) - 1. Then it performs an unconditional jump to loc_1185. So, let's take a look and see what's going on!

Analyzing loc_1185
Analyzing loc_1185

This section of code is rather simple. It's trying to locate the "/" character is argv[0]. Remember argv[0] contains the full path to our executable. We usually run executables with ./executable_name but that is expanded to the full path of our file. So, in this case, argv[0] contains: "/home/kali/reverse_engineering/crackmes/racecars/racecars". This block of code will subtract 1 from start until it reaches a "/" character. When that happens we jump to loc_11E8. So, let's keep in mind that once this loop finishes, start will have have the value of strlen(argv[0]) - 7. Let us continue!

The rest of the main function
The rest of the main function

The above is the rest of the main function! Seems we are getting close already! So, after the loop finishes the code jumps to loc_11E8. First, it loads start in the EAX register and compares end and start. Surely, at this point, start will be less than end so it jumps up to loc_11A2. Then, it indexes argv[0] with start and stores it in the EDX register. So, EDX holds, argv[0][start]. Crazy I know! Then, it indexes argv[0] with end and stores that in the EAX register. So, EAX holds, argv[0][end]. You might already have an idea of what the author is doing here. At address 0x00011C6, the binary then compares DL with AL. If they aren't equal the program prints out the error message and quits. Otherwise, it subtracts 1 from end and adds 1 to start. This continues until start and end are equal to each other. If that ever happens then we get the success message. So, what do we need to do? It's simple, rename the file so that it's a palindrome! That is, the name is spelled the same forward and backward. Interestingly enough, racecar is a palindrome! Let's rename the binary to racecar and run it!

Success
Success

And that's it! Pretty simple challenge if you ask me! If you want to see my decompiled output here you go!

end = strlen(argv[0]) - 1;
start = end;
while(argv[0][start -1] != 0x2F)
{
	start--;
}
while(start < end)
{
	if(argv[0][start] != argv[0][end])
    {
    	printf("Gimme what I want!");
        exit(1);
    }
    start++;
    end--;
}
printf("That's exactly what I wanted!");

And that's all there is to it! Pretty simple challenge if you ask me!

Conclusion

Alright another challenge down! I hope you all enjoyed this and learned something from this tutorial. If you have any questions feel free to hit me up on Twitter, Instagram, or Discord: jaybailey216#6540. If you have a challenge you want me to try next, let me know and I'll give it a shot! I'll see you all next time!

Peace out! ✌🏾

Show Comments