Writeup: FlareOn 2020: 001 - Fidler
1. TLDR
2. Dane wejściowe
Plik z zadaniem znajduje się tutaj. Hasło: flare.
Przedmiotem zadania jest program napisany w pythonie. Dostępne pliki to:
controls.py
fidler.py
fonts/arial.ttf
fonts/courbd.ttf
img/btndown.png
img/btnup.png
img/clock.png
img/coin.png
img/fbi.png
img/kittyelaine.png
Message.txt
fidler.exe
Ze względu na fakt, że implementacja logiki programu znajduje się w pliku fidler.py
, wystarczy ograniczyć się do analizy tego pliku.
3. Dostęp do programu
Dostęp do programu jest chroniony: po uruchomieniu użytkownik widzi ekran, na którym jest proszony o hasło.
Program został napisany w pythonie, jego kod jest od razu dostępny.
Za weryfikację hasła odpowiada funkcja password_check()
:
def password_check(input):
altered_key = 'hiptu'
key = ''.join([chr(ord(x) - 1) for x in altered_key])
return input == key
W celu pozyskania hasła wystarczy więc wykonać skrypt:
altered_key = 'hiptu'
key = ''.join([chr(ord(x) - 1) for x in altered_key])
print(key)
W ten sposób na standardowym wyjściu można otrzymać wypisane hasło, które pozwala uzyskać dostęp do programu:
ghost
4. Analiza kodu
Po wpisaniu hasła dostępowego ukazuje się właściwe okno aplikacji:
Za odczytanie i prezentację flagi odpowiadają funkcje:
- 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])
- victory_screen:
def victory_screen(token):
...
flag_content_label.change_text(decode_flag(token))
...
- game_screen:
def game_screen():
...
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
...
5. Odczytanie flagi
W celu odczytania flagi należy zatem wykonać kod:
#! /usr/bin/python3
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])
def victory_screen(token):
print(decode_flag(token))
def main():
target_amount = (2**36) + (2**35)
current_coins = (target_amount - 2**20) + 1
while current_coins >= (target_amount + 2**20):
current_coins -= 2**20
victory_screen(int(current_coins / 10**8))
if __name__ == "__main__":
main()
W ten sposób na standardowym wyjściu zostaje wypisana flaga:
idle_with_kitty@flare-on.com