Post

Flare-On 12 Challenge 1 Writeup - Drill Baby Drill

Bag of Tricks: Python

Challenge 1

This challenge was very simple, we received a pygame Python game exe and the source code. I didn’t bother running the exe and just looked at the code:

1
2
3
4
flagfont = pygame.font.Font("fonts/VT323-Regular.ttf", 32)
flag_text_surface = flagfont.render("nope@nope.nope", False, pygame.Color('black'))
flag_message_text_surface1 = flagfont.render("You win! Drill Baby is reunited with", False, pygame.Color('yellow'))
flag_message_text_surface2 = flagfont.render("all its bears. Welcome to Flare-On 12.", False, pygame.Color('yellow'))

These messages are a nice clue, the flag must be rendered sometime in the regular game loop. Continued the CTRL+F and found this function, that looks like a flag decryptor:

1
2
3
4
5
6
7
def GenerateFlagText(sum):
    key = sum >> 8
    encoded = "\xd0\xc7\xdf\xdb\xd4\xd0\xd4\xdc\xe3\xdb\xd1\xcd\x9f\xb5\xa7\xa7\xa0\xac\xa3\xb4\x88\xaf\xa6\xaa\xbe\xa8\xe3\xa0\xbe\xff\xb1\xbc\xb9"
    plaintext = []
    for i in range(0, len(encoded)):
        plaintext.append(chr(ord(encoded[i]) ^ (key+i)))
    return ''.join(plaintext)

Pretty reasonable, takes in a sum and xors it byte by byte with the flag ciphertext, lets see how this sum is generated:

1
2
3
4
5
6
7
8
9
10
11
if player.hitBear():
    player.drill.retract()
    bear_sum *= player.x
    bear_mode = True

if bear_mode:
    screen.blit(bearimage, (player.rect.x, screen_height - tile_size))
    if current_level == len(LevelNames) - 1 and not victory_mode:
        victory_mode = True
        flag_text = GenerateFlagText(bear_sum)
        print("Your Flag: " + flag_text)

Nice, the sum is just multiplications of the player.x coords, the max X is 800, let’s write a quick script to count to 800 (obviously the sum can be huge, but this is the first challenge)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def GenerateFlagText(sum):
    key = sum
    encoded = "\xd0\xc7\xdf\xdb\xd4\xd0\xd4\xdc\xe3\xdb\xd1\xcd\x9f\xb5\xa7\xa7\xa0\xac\xa3\xb4\x88\xaf\xa6\xaa\xbe\xa8\xe3\xa0\xbe\xff\xb1\xbc\xb9"
    plaintext = []
    for i in range(0, len(encoded)):
        plaintext.append(chr(ord(encoded[i]) ^ (key+i)))
    return ''.join(plaintext)

def brute_force_flag():
    for i in range(800):
        flag = GenerateFlagText(i)

        if "flare" in flag:
            print(flag)
            return

def main():
    brute_force_flag()

if __name__ == '__main__':
    main()

:)

This post is licensed under CC BY 4.0 by the author.