Challenge 01

1 - Fidler

Welcome to the Seventh Flare-On Challenge!

This is a simple game. Win it by any means necessary and the victory screen will reveal the flag. Enter the flag here on this site to score and move on to the next level.

This challenge is written in Python and is distributed as a runnable EXE and matching source code for your convenience. You can run the source code directly on any Python platform with PyGame if you would prefer.

Như tiêu đề, với bài này, ta được cung cấp file .exe và file source code .py.

Chạy file exe:

Chương trình yêu cầu nhập password, ta mở source code ra:

Ta dễ dàng lấy được password là “ghost”, nhập vào, ta sẽ chuyển sang màn hình tiếp theo:

Ta phải click vào con mèo 100 tỷ lần để lấy được flag, hoặc ta có thể xem chương trình tạo flag như nào để có thể lấy được nó.

Ta có thể mở source code của game này ra để đọc, đó chính là file “fidler.py”, lướt qua nhìn tên các hàm thì có một hàm liên quan tới “flag”, đó là hàm decode_flag:

def decode_flag(frob):
    last_value = frob
    encoded_flag = [1135, 1038, 1126, 1028, 1117, 1071, 1094, 1077, 1121, 1087, 1110, 1092, 1072, 1095, 1090, 1027,
                    1127, 1040, 1137, 1030, 1127, 1099, 1062, 1101, 1123, 1027, 1136, 1054]
    decoded_flag = []

    for i in range(len(encoded_flag)):
        c = encoded_flag[i]
        val = (c - ((i%2)*1 + (i%3)*2)) ^ last_value
        decoded_flag.append(val)
        last_value = c
    return ''.join([chr(x) for x in decoded_flag])

Sau đó select chữ "decode_flag" trong notepad++, thì nó sẽ tự select tất cả các chỗ khác có chứa "decode_flag"

Ta có thể thấy 1 reference khác của "decode_flag" ở hàm victory_screen, ta lại tiếp tục select chữ "victory_screen" để tìm reference:

Ta lại tiếp tục làm như trên với hàm game_screen:

Vậy là ta đã biết hàm game_screen được gọi như nào, tuy nhiên điều đó cũng không quá quan trọng vì ta sẽ chỉ quan tâm tới hàm decode_flag.

Chỉ có duy nhất 1 chỗ gọi hàm decode_flag, đó là chỗ này:

# ... truncated 
while not done:
    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
# truncated ...

Dễ thấy current_coin phải lớn hơn hoặc bằng 2**36+2**35 và bé hơn 2**36+2**35+2**20 thì dòng victory_screen(int(current_coins / 10**8)) mới được gọi.

Khi đó ta viết lại đoạn code ở trên với frob=int((2**36+2**35)/10**8)

print (decode_flag(int((2**36+2**35)/10**8)))

Chạy thử:

idle_with_kitty@flare-on.com

[+] Source code dùng để giải cho tất cả các bài nằm ở đây