can you login to this secret_login program

cbe1369d57cd131d6d5b1787d02511c6.zip

Let’s look at the file information first.

Let’s run the program once to see what it does.

It has register and login features.

After decompiling it, I noticed the following code at the beginning of the main function:

Here we see that there is a global variable xv and if there is an argument for the binary, the value of xv is set. Otherwise, xv gets initialized to zero. Notice that it is a simple string to integer convertion loop, which means we can simply enter a number as an argument and xv will be initialized to that number.

Next, compute function is called. It probably computes some stuff and initializes some variables. Therefore, we should analyze it.

The compute function starts with the following snippet:

Here, we see string s is getting copied to v18, but each byte of s is increased by (xv – 5). Looking at the xreferences, we see that string s is initialized in __static_initialization_and_destruction_0 function.

Here is the decompilation of it:

We can clearly see that string s is getting initialized to “jmm%qiYl^”. Also, there is a map container initialized and stored at global variable mp.

Let’s get back to the compute function. Here is the end of its decompilation:

Things are getting interesting. After modifying and copying string s to v18, it converts it to a std::string and store it at v13. Then, it creates a std::pair as (v13, 5) and inserts this pair into the map which is previously initialized. The key for the insertion is “admin”. Thus, this map is obviously mapping usernames to their related information pair.

Since the code is long and a little bit ugly due to being c++, I won’t paste the whole code here. Instead, I will briefly talk about the flow of execution and only paste the important code snippets.

When we select the login option and enter an username, the function login is called with a single parameter which is the username we provided. It calls map’s find function to check whether the user exists. If so, it calls login function with the provided username. Then, we have two options:

  1. Login with password
  2. Retrive password with secret

Let’s look at the login with password branch first.

Here is the decompiled snippet:

It retrives the pair for the username and compares its first value to the password we entered. Now, we know that the first value in the pair is the password. The password is different for each value of xv variable, but easy to calculate.

The password for the argumentless execution is ‘ehh ldTgY’, but the binary won’t accept it. Since it reads the password using std::cin, it will read it as ‘ehh’ due to the space character. We can attach a debugger and change the password afterwards if we really want, but for now, let’s see what happens after the correct password is entered.

It simply creates and prints a string such as:

However, it adds the value of xv variable to all characters except for the password. We can actually solve it right now, but let’s take a quick look at the password recovery option.

When we select the password recovery with secret option, the function login_k is called with our username.

Here is the full decompilation of it:

It first xors the digits from 1 to 9 with 0x64 and xors the results with each other as well. Finally, it xors the secret key we provided with 0x64 and again xors the result with the previously calculated result. Then, it retrieves the pair for the specific username and compares the calculated value with the second value of the pair. If they are equal, it prints the password of the user to pass.txt file.

Since we know the admin’s key is 5, we can calculate the secret value for him.

So, we just found that the secret key for the admin is 4. Let’s run the program and test it.

See? Exactly the same password. Now, we have two ways of finding the correct xv value. First, we can brute force it. Second, we can calculate it since we know the flag format. According to the flag format, the value of xv must be 11. We can use python to calculate the flag quickly, but let’s use the program itself and retrieve the flag from it.

First, we need to get the correct password.

Now, we have the password. Let’s get the flag!

The flag is cbmctf{pss+wo_rd_rev3rs3d}.