Writeup: FlareOn 2021: 002 - known

Task description

1. TLDR

Known graph

2. Dane wejściowe

Plik z zadaniem znajduje się tutaj. Hasło: flare.

Dostępne pliki to:

  UnlockYourFiles.exe
  Files/capa.png.encrypted           
  Files/cicero.txt.encrypted         
  Files/commandovm.gif.encrypted     
  Files/critical_data.txt.encrypted  
  Files/flarevm.jpg.encrypted        
  Files/latin_alphabet.txt.encrypted 

3. Dostęp do programu

W pliku znajdujemy string zakodowany base64 będący wskazówką:

$ echo KD4wXzApPiBJdCdzIGRhbmdlcm91cyB0byBh
ZGQrcm9yIGFsb25lISBUYWtlIHRoaXMgPCgwXzA8KQo= | base64 -d
(>0_0)> It's dangerous to add+ror alone! Take this <(0_0<)

4. Analiza kodu

Znajdujemy funkcję odpowiedzialną za odszyfrowanie paczki 8 bajtów:

xor asm

Algorytm deszyfrujący został zaimplementowany w następujący sposób:

p[i] = rol(key[i] ^ c[i], i) - i

Przekształcenie pozwala otrzymać algorytm szyfrujący:

c[i] =  ror(p[i] + i, i) ^ key[i]

Należy zatem odzyskać 8-bajtowy klucz

5. Odczytanie flagi

Z nazw plików wiadomo, że jeden z zaszyfrowanych plików zawiera alfabet łaciński. Możemy zatem znaleźć klucz szukając takiego, który odpowiadał znanemu szyfrogramowi.

Zaimplementowałem zatem funkcję szyfrującą:


def enrypt(plaintext, key):
    max_bits = 8
    ror = lambda val, r_bits, max_bits: \
        ((val & (2**max_bits-1)) >> r_bits%max_bits) | \
        (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
    i = 0
    ciphertext = []
    for (p,k) in zip(plaintext, key):
        c = ror(ord(p) + (i%8), (i%8), max_bits) ^ k
        ciphertext.append(c)
        i = i+1
    return ciphertext

Następnie napisałem kod znajdujący kolejne bajty klucza:

def read_first_qword_buffer(filename):
    buffer = None
    with open(filename, 'rb') as f:
        buffer = f.read(8)
    return buffer

encrypted_file_header = read_first_qword_buffer('Files/latin_alphabet.txt.encrypted')

key = []
ciphertext = None

for i in range(0,8):
    for key_char_candidate in range(0,256):
        key_candidate = key + [key_char_candidate]
        ciphertext = enrypt('ABCDEFGH', key_candidate)
        if all(a==b for (a,b) in zip(ciphertext, encrypted_file_header)):
            key = key_candidate
            break

print(''.join([chr(k) for k in key ]))

W wyniku działania skryptu zostały odzyskany klucz:

No1Trust

Po uruchomieniu programu UnlockYourFiles.exe i podaniu klucza odzyskano zaszyfrowane pliki:

  Files/capa.png           
  Files/cicero.txt         
  Files/commandovm.gif     
  Files/critical_data.txt  
  Files/flarevm.jpg        
  Files/latin_alphabet.txt 

W pliku critical_data.txt znajdowała się flaga:

(>0_0)> You_Have_Awakened_Me_Too_Soon_EXE@flare-on.com <(0_0<)