Ready Player One

Thomas Dowling
5 min readMay 17, 2021

I recently signed up to a wargame website 0x0539.net and came across some really interesting challenges, even some way out of my league. However this particular challenge was so interesting that I’ve decided to do a writeup.

Just a disclaimer before continuing, the FLAG of this challenge will not be published only the methodic approach I have taken to solve it. I encourage the reader to attempt this challenge and understand the mechanics of it.

Also, I assume the reader has prior knowledge of Reverse Engineering, Programming, and how to operate a computer.

Without further ado, lets get into this brilliant challenge.

Challenge Information

URL: readyplayerone

Title:

Ready Player One (150 Points)

Description:

Find the Copper, Jade, and Crystal keys to unlock the flag.

The Beginning

When I first approach a challenge, I like to execute it and figure out how it works, Since this challenge is an executable for Windows, that’s what OS I used to solve this challenge.

Upon execution we get prompted a message on the terminal to enter a username, see below for an image.

readyplayerone username input

When you enter some arbitrary username the application exits right away, so this indicates that the username is specific.

We now have to analyze this executable so that we can figure out the correct username to input.

I used IDA Pro 7.5 to analyze this executable, but you can use whichever disassembler you choose or are familiar with.

Once I’ve opened the executable in my disassembler, I like to check the strings of the executable first to see if I can find anything interesting. Below is a picture of some strings IDA found in the executable.

As seen above there are some interesting hashes and some other interesting strings like “> FLAG{%s}\n”, right now I’m just going to focus on finding the correct username to input, so I look at the main function and see what’s going on there, I’ve added pictures below.

As we can see from above there are a few Windows API calls being made, but I’m not worrying about them just yet. Right now I want to find the function responsible for the username input. So the first thing I do is go into sub routine sub_A312E0, I’ve added a picture below, only of the interesting part of this function, which checks the username.

Okay so if you haven’t watched Ready Player One the movie, you wouldn’t really know the meaning of this username, it’s simply the main characters avatar name in the movie “Parzival”, but they are stack strings, which is why they don’t show up in the strings listing in IDA.

So we now have to test this username in the actual executable to see if it is correct, I’ve shown a picture of the output below.

Okay so we now know the correct username to give, now we can access some more functionality. The program now asks for a Copper Key, so I went a head and searched for that “The Copper Key:” string in my string listing in IDA, I clicked the string and saw where it was referenced and in what sub routine it was referenced in. I added a picture below.

So the copper key string is referenced in sub routine sub_A32BF0 and when I clicked into this it brought me directly to where this string was being used, you can see in the picture below.

So now get_s is being called and a buffer named Parameter holds our input value. Then we start to see calls to CreateThread, which is a Windows API function, but we pass our input to a function each time when CreateThread is called. The first function being StartAddress, so I clicked into that, you can see some of the function in the picture below.

Again we see some Windows API calls, but this time they are Cryptographic functions used to create hashes. From analyzing this function I learned that it does the following.

The user input for the copper key gets hashed, once it’s hashed a portion of that hash is then compared to a hardcoded hash, the portion is gotten from an offset and the portion is always 2, you can see it in the picture below.

As you can see this is a loop and it’s getting the portion of the hashed user input from the offset specified which is 6 and it is storing that portion in Buffer. Then something interesting happens, another function is called and if it returns true, an event is set. See the picture below.

This function takes 3 parameters
1: hashed portion
2: length of data
3: hard coded hash

Once we enter into this sub routine we can notice that it is just like our StartAddress function, except this time it is hashing our hashed portion and comparing it to the hardcoded hash that was passed as a parameter. We can take a guess that these functions are cryptographic so you can use some sort of naming convention which indicates that.

To be continued…….

--

--

Thomas Dowling
0 Followers

Reverse Engineer, CTF Player, Exploit Dev and overall nerd