home icon Kha Research Blog
GithubTwitter

Flare on 2020 - Level 1

This challenge is a python that have compiled to windows program. The organizer also gives us a source code of this program. Let's dive into the code by static analysis. We have the following functions

 +buy_click : function
 +cat_clicked : function
 +decode_flag : function <--
 +game_screen : function
 +main : function
 +password_check : function <--
 +password_fail_screen : function
 +password_screen : function
 +victory_screen : function
▼ variables
    buying
    current_autoclickers
    current_coins

It looks like the program has several functions that may be of interest to us. In particular, the password_check and decode_flag functions stand out as potentially important.

To start, let's take a closer look at the password_check function. This function is likely responsible for verifying the user's password, so it will be important to understand how it works and what it does. We can examine the code line by line to see what it does and how it operates.

Next, let's move on to the decode_flag function. This function is probably responsible for decoding the flag that we need to find in order to solve the challenge. By analyzing the code in this function, we can learn more about how the flag is encoded and what we need to do to decode it.

The password_check function

Since the program requires user to enter a password with a protect screen, the developer implements this feature by 2 functions:

  • password_screen shows the input text.
  • password_check checks the password as follows
def password_check(input):
    altered_key = "hiptu"
    key = "".join([chr(ord(x) - 1) for x in altered_key])
    return input == key

The solution is trivial, they key is "ghost" by running the code in python interpreter

print("".join([chr(ord(x) - 1) for x in "hiptu"]))

The decode_flag function

I discovered that the victory_screen function calls the decode_flag function by using the "find references" feature from the Language Server Protocol (LSP). The game_screen function calculates the token value using the following logic:

target_amount = (2 ** 36) + (2 ** 35)
if current_coins > (target_amount - 2 ** 20):
    while current_coins >= (target_amount + 2 ** 20):
        current_coins -= 2 ** 20
    victory_screen(int(current_coins / 10 ** 8))
    return

In order to display the victory screen and see the flag, the current_coins variable must have a value greater than (target_amount - 2 ** 20). To achieve this, we can use the following code:

target_amount = (2 ** 36) + (2 ** 35) + 1  # +1 to jump inside the while loop.
current_coins = target_amount - 2 ** 20
while current_coins >= (target_amount + 2 ** 20):
    current_coins -= 2 ** 20
token = int(current_coins / 10 ** 8)

With the token value calculated, we can now call the decode_flag function to decode the flag and print it to the screen:

print(decode_flag(token))
idle_with_kitty@flare-on.com