Reverse Engineering Challenge - The Art of Reversing

Reverse Engineering Challenge - The Art of Reversing

Introduction

Hello and welcome back! We are going to be reversing on a Windows box today. This challenge we are going to look at today is called "The Art of Reversing" and it is from the website HackTheBox. If you prefer you can watch my corresponding YouTube video for this challenge here:

The Art of Reversing Video Walkthrough

This challenge provides us with a product key, cathhtkeepaln-wymddd, and we have to figure out how the product key is generated. We are required to find the username/number of activation days that will yield the same product key. This challenge was pretty fun and I hope you enjoy.

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 hackthebox.

Note: You will need a valid HackTheBox account to download the binary.

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

The initial triage is going to be a little different since we are on a Windows box. The idea is the same we want to gain some insight on the binary before we use open this up in a static analysis tool. There's a very nifty tool that will streamline the process for us, detectiteasy (die) I know the acronym is pretty dark but it's a great tool! If you're using my VM you can simply right click on the file and run the analysis as shown below:

DetectItEasy from explorer
DetectItEasy from explorer

Let's run die on our binary.

Output from Detect it Easy
Output from Detect it Easy

Die provides lots of information. We see that this is a 32-bit binary. It's a .NET executable. This is important because it will make our analysis a lot easier (assuming the author didn't add any anti-analysis measures. We also see there's a button for Imports. Let's take a look at what this shows us.

Functions and Libraries used by The Art of Reversing Binary
Functions and Libraries used by The Art of Reversing Binary

On Windows a Dynamic Link Library (DLL) is similar to a shared object on Linux. We see this binary is only importing the mscoree.dll library. Below that we see the functions used from this library. It happens this binary only uses _CorExeMain. Since these do not tell us anything about how this binary functions, let's look at the strings to see what else we can find out. Luckily, DIE can show us the strings as well. We just need to click on the String Tab in the .NET -> Metadata section.

Output of Strings
Output of Strings

There are actually quite a few strings that were interesting but, by far the most interesting is the buttonCreateProductKey_Click. Intuitively, we can assume analyzing the function that is called when pushing this button will allow us to figure out how the product key is being created. Now, with all of our initial triage out of the way, let's open the binary up in a tool called dnSpy.

Static Analysis with dnSpy

It is important to note that this is a 32-bit binary. So we need to open this up in the 32-bit version of dnSpy. On my VM the 32-bit version is dnSpy-x86.exe. Once you open the correct version of dnSpy, press File-> Open and navigate to the binary. If successful, it should look something like this:

Opening the binary in dnSpy
Opening the binary in dnSpy

If you press the arrow of the DotNetTwo tab, it'll open up the DotNetTwo.exe, open that tab and you'll see various tabs that we can inspect.

Expanding the tabs
Expanding the tabs

We are going to spend out time looking at the DotNetTwo. This contains the main function and the other pertinent function we are interested in. If we expand it, we'll see two components: Form1 and Program. Program is only going to contain the main function which doesn't do much aside from call the Form1 function. So, let's analyze Form1.

Form1 Function

We see that this function just calls the InitializeComponent() function. We do see the buttonCreateProductKey_Click function. Let's go ahead and analyze the buttonCreateProductKey_Click function.

Create Product Key Function
Create Product Key Function

We see the function first checks whether the Username or Number of Days textboxes are empty. If either are empty, it throws and error and returns. The function then assigns our Username to the variable text. Since that's not a very useful variable name, let's rename it! You can rename variables by right clicking anywhere in the disassembly menu and pressing the "Edit IL Instructions" option.

dnSpy options
dnSpy options

Once you're in this menu, press the "Locals" tab and this will provide you the option to rename variables. What I hate about this is as you can see there are no variable names.

Edit IL Instructions modifying local variables
Edit IL Instructions modifying local variables

Fortunately, these variables are in order so the first variable at Index 0 corresponds to our text variable. Similarly, the rest of the variables will correspond to the next variable we encounter and so on. With this in mind, let's rename the first variable in the list to username. Press ok and you will see the change reflects in the disassembled code.

Create Product Key Function with text variable modified to username
Create Product Key Function with text variable modified to username

After it grabs the username, it grabs the number of days. Let's rename num to numDays. Then, we see some values get initialized. Let's just keep these values in mind for now. We see the username length gets checked. If we enter a username less than 3, it will yell at us and exit. Similarly, the number of days variable is also checked. If we enter a number less than or equal 15 or greater than 3650, it yells at us and exits. We don't need to worry about the Application.DoEvents(); function. It simply checks whether there are any messages that need to be processed. We can also ignore the next line 196 as this does not do anything important as far as our analysis is concerned. After that we see another function is called nPr. This has nothing to do with the radio station! The function is passed the length of our username twice as parameters. Keep this in mind. Let's click on this function to see what it's doing.

nPr function
nPr function

This function calls yet another function and returns. Note the parameters for this function. Recall that n and r are both username.Length. So, the function FcDv has the parameters username.Length and username.Length - username.Length or 0. With this in mind, let's move on to see what this function is doing.

FcDv Function
FcDv Function

This function is simply calculating the factorial of username.Length. And who said you'll never use Math in real life! Let's go back to our createProductKey function and rename the variable to username_length_factorial. Really rolls off the tongue right?

Update Create Product Key Function
Update Create Product Key Function

Line 198, sets a variable called nToStop to username_length_factorial / 2. On line 199, the variable word is set to username but depicted as an array. For example, if we typed a username "Jaybailey216", word would contain an array of characters: ["J", "a", "y", "b", "a", "i", "l", "e", "y", "2", "1", "6"]. Let's rename word to username_as_array.  We then see our username is passed to a function called GetPer. Let's take a look at this function shall we?

GetPer function
GetPer function

GetPer calls another GetPer function with different parameters. The GetPer functions with three parameters is a recursive function. GetPer calls a function called do on lines 58 and 60. Notice our username is passed by reference to these functions. Let's take a look at what this Do function is doing to our username.

Do Function
Do Function

Fortunately, this function is simple. If a and b are the same, then it returns. Otherwise, it swaps a and b. Because this is a simple swap, we don't really need to worry about all the recursive craziness. We now know that GetPer will return a jumbled up version of our username. To uncover the actual username we simply have to unscramble it. Before moving on, it's important to note that our scrambled username gets stored in a variable ssOut on line 49 in the GetPer function. Now let's go back to the createProductKey function.

Revisiting Create Product Key Function
Revisiting Create Product Key Function

After the GetPer function finishes scrambling our username, a function ToR (not to be confused with TOR) is called with our numDays variable as input. This will likely lead us to the last piece of the puzzle.

ToR function
ToR function

We are hit with yet another recursive function. This function is pretty straightforward. All it is doing is turning our numDays variable to roman numeral representation. With this in mind, let's go back to the createProductKey function again and rename the text variable to numDays_Roman_Numerals. I know I'm mixing camel case with underscores, deal with it!

Modified Create Product Key Function
Modified Create Product Key Function

Now, the last step! Our numDays_Roman_Numerals variable is passed to another function, DoR.

DoR Function
DoR Function

Luckily, this function is small and simple! It takes our Roman Numerals variable, turns it into an array, reverses it, and iterates over the array. It adds 1 to each element in the array. This is essentially getting the next letter in the alphabet. So, if our number was XIX, it would be changed to YJY. Then the array is changed to all lowercase letters so the string yjy would be returned in this hypothetical. Alright, we now have all we need to figure out the username/number of activation days that will give us the product key: cathhtkeepaln-wymddd. We know the username is simply scrambled. Unscrambling the username gives us the username "hacktheplanet". Now what about the number of activation days? All we have to do is reverse the string and subtract 1 from each letter to get the proper roman numberal. So wymddd, dddmyw (recall we reversed it in the DoR function. Then subtracting 1 gives us: ccclxv. We can get the value by adding up roman numerals values. C = 100, L = 50, X = 10, V = 5. So we have 100 + 100 + 100 + 50 + 10 + 5 which gives us 365! So the username/number of activation days is "hacktheplanet-365". Cute 😂.

Conclusion

Alright, that's all there is to it for this challenge. I do hope you enjoyed reading it and I hope you learned something as well! If you have any questions feel free to reach out to me on Twitter, Instagram, or Discord jaybailey216#6540. If you have a challenge you would like me to try, let me know and I'll give it a shot! I'll see you all next time!

Peace out! ✌🏾

Show Comments