Reverse Engineering Challenge - KeyMe Walkthrough

Reverse Engineering Challenge - KeyMe Walkthrough

Introduction

What's going on everybody!? We have another Windows challenge today. This one comes from the website crackmes.one. It's pretty simple but I think it was pretty interesting to say the least. As the name implies, we have to create a working keygen. As with all of my walkthroughs there is a YouTube video dedicated to this challenge. You can check it out below:

KeyMe 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 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 our initial triage by looking at the Readme file provided with the binary.

Readme File for KeyMe challenge
Readme File for KeyMe challenge

There isn't much in the Readme file. There are some rules the author placed on us. We are not allowed to brute force the key, we are not allowed to patch the binary, and we must create a working keygen. We have yet to patch anything and bruteforcing is beneath us right? So, this shouldn't be too difficult. The author signs his name: papanyquiL. Let's go ahead and get some initial information about this binary. Let's run die on this bad boy! If you're using my VM simply right-click on the binary and select detect it easy.

DIE Output on KeyMe binary
DIE Output on KeyMe binary

Similar to the last Windows challenge, we are dealing with a .NET executable. Additionally, this is a 32-bit binary. Let's go ahead and take a look at the Imports this binary uses.

KeyMe Imports
KeyMe Imports

Just like the last challenge, it is only importing mscoree.dll and _CorExeMain. This is not unusual for small binaries to only import this one library. Let's take a look at the strings.

KeyMe Strings
KeyMe Strings

We see some interesting strings: GenerateKey, CreateSerial, and CheckSerial_Click. These will likely lead us down the correct path to understand how to create a keygen. Now that we have something to focus on, let's open this binary up in dnSpy. Remember this is a 32-bit binary, so we will have to launch the 32-bit version of dnSpy.

Static Analysis with dnSpy

Once you open the binary, navigate to Form1 and locate the InitializeComponent() function. It should look like this:

InitializeComponent Function
InitializeComponent Function

Everything looks pretty standard here. Something important to note is our user input will be textbox1 and the password textbox2. But wait a second. Something is a little off! Notice anything interesting? Look at line 114. The text for the Exit button is "&Check". Similarly, the text for the CheckSerial button is "Exit." It looks like papanyquiL was trying to pull a fast one on us! Instead of analyzing the CheckSerial_Click function, let's look at the Exit function!

ExitClick Function
ExitClick Function

It appears we were correct! The Exit_Click_1 function calls the CreateSerial function. Let's take a look at what this function does.

CreateSerial Function
CreateSerial Function

So it appears this function performs some action on the text variable and closes the app. Do you notice anything funky about the for loop? It looks pretty standard but look at the variable text. It's initialized to an empty string. So, the check i < text.Length actually won't do anything. So it just calls the CloseApp function. It appears I led you down the wrong path. Sorry... or did I (cue suspenseful music). Let's take a look at this "CloseApp" function.

CloseApp Function
CloseApp Function

Egad! It appears we've been had! The CloseApp function doesn't close the app at all! It's performing some manipulation on the text string which is initialized to the author's name: papanyquiL! The for loop is going to take our username, and perform a series of replacements. This will be appended to the text variable. So, at the end of this for loop, the text variable will hold "papanyquiL" + our manipulated username. We then see our password (textBox2) is compared to this text variable. So, we need to provide a username/password combination that will yield the correct password. Fortunately, we have all we need to create a proper username/password combination. We can do 1 of two things, use .NET to create a password based on a username we provide by copying the code here. Alternatively, we can use Python. Since I'm not very familiar with .NET I took the Python route. The following Python code will produce a valid username for any username we provide:

# -*- coding: cp1252 -*-
text = "papanyquiL";
username = raw_input("Enter a username: ")
for i in range(0, len(username)):
    text = text + (username + str(1) + str(3)).replace(" ", "").replace("a", "@").replace("b", "1").replace("c", "*").replace("d", "4") \
           .replace("e", "!").replace("f", "#").replace("g", "-").replace("h", "%").replace("i", "£").replace("j", "$").replace("k", "^").replace("l", "'") \
           .replace("m", ".").replace("n", "~").replace("o", "+").replace("p", "=").replace("q", "2").replace("r", "\\").replace("s", "9").replace("t", "/") \
           .replace("u", "6").replace("v", ":").replace("w", "8").replace("x", "]").replace("y", "7").replace("z", "[") + str((len(username) ^ i));

print text

Let's test it out shall we!?

Output of keygen.py script
Output of keygen.py script

Now, run the KeyMe.exe binary and insert "Jaybailey216" as the username and that mess as the password!

Running KeyMe with valid username/password
Running KeyMe with valid username/password

And the verdict is...

Success!
Success!

And we did it!

Conclusion

Alright and that's it for this challenge! I hope you enjoyed reading this and more importantly I hope you learned something today. This was a fairly simple challenge but I do like that the author tried to throw us down a few rabbit holes. 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!

Support your boy Jaybailey216

I truly hope you enjoyed this reading this blog and/or watching the YouTube video! My goal is to always provide quality content. If you want to support me even further, consider becoming a Patron! This is the best way to support me! Regardless if you decide to join or not, I'll see you all next time!

Peace out! ✌

Show Comments