Writeup: FlareOn 2022: 003 - Magic 8 Ball

Task description

1. TLDR

TLDR graph

2. Input data

The challenge file is here. Password: flare.

The subject of the task was a PE file with accompanying files:

Magic8Ball.exe
SDL2.dll
SDL2_image.dll
SDL2_ttf.dll
assets/
libjpeg-9.dll
libpng16-16.dll
libtiff-5.dll
libwebp-7.dll
zlib1.dll

./assets:
DroidSans.ttf
LICENSE.txt
NotoSans_Regular.ttf
OFL.txt
OpenSans_regular.ttf
ball_paint.png

The file names suggested that the program was produced using SDL (Simple DirectMedia Layer) technology.

3. Initial analysis

I verified the file type Magic8Ball.exe:

$ file Magic8Ball.exe
Magic8Ball.exe: PE32 executable (GUI) Intel 80386, for MS Windows

The program, when launched, presented a window as below:

main window

I then loaded the program into the IDA environment

4. Code analysis

My attention was drawn to one piece of code that was responsible for verifying the order of pressed keys:

key

The expected order of pressed keys is recorded below:

LLURULDUL

Then there was a call to the function responsible for reading the flag:

call_get_flag

Before this was even to happen, the correctness of the question given was verified:

gimme flag pls?

5. Reading the flag

After entering the question gimme flag pls? and entering the key sequence LURULDUL[ENTER] a flag was presented:

flag

U_cRackeD_th1$_maG1cBaLL_!!_@flare-on.com

6. Alternative version

Looking deeper into the function responsible for reading the flag, one could learn about the charateristic loops for the [RC4] (https://en.wikipedia.org/wiki/RC4#Key-scheduling_algorithm_(KSA)) algorithm.. The ciphertext was the values added to the stack:

ciphertext

The key was the expected sequence of keys pressed

LLURULDUL

So I wrote a script to decrypt the flag:

from malduck import rc4

encrypted = [b"\x33\x12\x2A\x35",
    b"\xB2\x64\x57\x87", 
    b"\x34\xA6\xEF\x00", 
    b"\x3E\xDE\xE0\x01", 
    b"\x40\xEC\x21\x01", 
    b"\xB0\x69\x1D\x26", 
    b"\x7B\xB2\x69\xB0", 
    b"\x06\xEB\x22\x56", 
    b"\xCB\x5D\xF2\xBE", 
    b"\x51\x2B\x0F\x79",
    b"\x00\x00\x00\x55"]
 
ciphertext = b''.join([dword[::-1] for dword in encrypted])[0:41]

key = b'LLURULDUL'
plaintext = rc4(key, ciphertext)

print(plaintext)

A flag is presented upon startup:

b'U_cRackeD_th1$_maG1cBaLL_!!_@flare-on.com'