Hack The Box: Impossible Password Reverse Engineering Challenge

David Mentgen
TestingOnProd
Published in
6 min readNov 2, 2021

This week I’m going to be completing the impossible password reverse engineering challenge from Hack The Box. This challenge is ranked easy, so I’m fairly confident we’ll be able to knock this one out pretty quickly.

What I’ll be using

For this challenge, I’ll be using the following:

  • Linux VM — Any VM that will give you access to a terminal w/ GDB should suffice. I’m personally using Kali Linux 2021.2 in virtualbox on my Windows 10 Machine.
  • GNU Debugger (GDB) — This came with my kali linux vm.
  • GEF (optional) — This is an addon that I use with GDB that you’ll see in my screenshots. It’s really nice to have, but not required. Information on GEF can be found here.
  • Ghidra (optional) — I like to use Ghidra to help orient myself when I’m stepping through assembly. It’s part of my workflow, but definitely not required for this challenge. Information on Ghidra can be found here.

Step 1: Download Challenge Files

Visit the challenge on Hack The Box: https://app.hackthebox.eu/challenges/impossible-password

Once you’re there, download the challenge files and store them in your working directory:

When unzipping the binary into your working directory, the password is hackthebox

Step 2: Poke the file

Now that I have the file in my working directory, I’m just going to start by running it in my linux vm and see what happens.

It seems it’s doing something, but it’s too early to tell exactly what’s going on. Let’s go ahead and boot this thing up into Ghidra and see if we can’t figure out what’s happening under the hood.

Step 3: Open the file in Ghidra and find the executed code

Let’s go ahead and open up the binary in Ghidra with all of the default settings:

After importing the file, let’s open it up and go ahead and click “yes” with the default settings when prompted to analyze the binary:

In the functions view, let’s head over the entry by double clicking it:

Once there, we’ll see some code populating our decompiler. It should look something like this. Let’s navigate over to what looks like will probably be our starting function by double clicking it:

Step 4: Analyze the binary in Ghidra

Now that we’ve entered this function, we should start seeing some interesting things. Let’s take a look at some interesting items that are now populating our decompiler:

Let’s break down what’s probably happening here in this decompiler with some educated guesses.

  • Line 52: Print the start of the line *
  • Line 53: Probably reading in the user input into variable local_28
  • Line 54: Prints out [local_28] in square brackets with a new line character. We also experienced this behavior when we ran the binary earlier
  • Line 55: This is just a strcmp() from C. So this will compare local_28 and local_10. If they are equivalent, local_14 will equal 0.
  • Lines 56–59: Checks the string comparison result. If they are not equal, then the program will exit.

Analyzing the lines above seem to follow everything that we’ve experienced so far when we first executed this binary. Based on all of this, it would seem that our key is located in local_10 which we can see defined right at the top of my screenshot on line 31 as SuperSeKretKey.

According to the decompiler, if the user enters the correct key the program will proceed forward and then output ** for a second key. Let's test this hypothesis by executing the program again and entering the key we just found:

Step 5: Finding The Second Key location in Ghidra

Let’s take a look back at the decompiler in Ghidra and focus in on the section of code that we’re now at

  • Line 60: Print out **. This is exactly where we left off in the previous execution.
  • Line 61: This looks like it’s taking user input and storing it in local_28 again.
  • Line 62: Looks like some function is called and storing a string into __s2.
  • Line 63: This is doing a string comparison between the user input, local_28, and the previously mentioned __s2 variable.

Line 63 leads me to believe that __s2 probably will contain our second key, so let’s take a look into function FUN_0040078d by double clicking it in the decompiler.

Because this is an easy level challenge, I’m sure we can probably cheese this without actually analyzing this too deeply. Let’s backup to our previous location in Ghidra and try grab the address of our strcmp for the second key.

Step 6: Dynamic Analysis with GDB

Inside our linux VM, let’s boot this binary up in GDB

Using the address we just grabbed for our string comparison location, let’s go ahead and add a breakpoint there.

If you’re using GEF, you’re GDB should look something similar to what’s on my screen as shown above. If you’ll notice here, we can see the last two assembly calls moved some values before the string comparison

Let’s take a look at what’s in register rsi and rdi with the following

Looking at this, I would have to guess that the register rsi probably contains the second key and rdi contains the user input. Let’s see if we can cheese this challenge by just setting the registers equal to each other and then continuing code execution.

Well, I’ll be damned. It actually worked. The flag has been censored because I encourage you to actually try this out for yourself!

Conclusion

As the challenge difficulty suggests, this was an easy reverse engineering problem. I’m not sure if my solution to this problem was what was intended, but it works and for CTF challenges like this that’s all that really matters.

Originally published at http://testingonprod.com on November 2, 2021.

--

--