Flare-On 6 CTF (2019) | Joachim De Zutter
In 2019, I solved all 12 challenges of the sixth FLARE-On reverse engineering CTF within 6 weeks and won a medal. There were 5790 contestants and 308 winners (~5.32%). I ended at the 132nd place according to the list of winners.

The official solutions can be found at https://www.fireeye.com/blog/threat-research/2019/09/2019-flare-on-challenge-solutions.html

I solved challenge 3 (FlareBear) using bytecode viewer to decompile the DEX file inside the APK file.

To solve challenge 5 (demo) I used a debugger to swap the pointer to the 3D object that was visible with the pointer to the 3D object that was invisible.

Here's a Python script I wrote to bruteforce the nuclear launch code (5C0G7TY2LWI2YXMB) in challenge 7 (Wopr):

import sys
import random

equations = [[2,3,4,8,11,14],
 [0,1,8,11,13,14],
 [0,1,2,4,5,8,9,10,13,14,15],
 [5,6,8,9,10,12,15],
 [1,6,7,8,12,13,14,15],
 [0,4,7,8,9,10,12,13,14,15],
 [1,3,7,9,10,11,12,13,15],
 [0,1,2,3,4,8,10,11,14],
 [1,2,3,5,9,10,11,12],
 [6,7,8,10,11,12,15],
 [0,3,4,7,8,10,11,12,13,14,15],
 [0,2,4,6,13],
 [0,3,6,7,10,12,15],
 [2,3,4,5,6,7,11,12,13,14],
 [1,2,3,5,7,11,13,14,15],
 [1,3,5,9,10,11,13,15]]

results = [ 0x73, 0x1D, 0x20, 0x44, 0x6A, 0x6C, 0x59, 0x4C, 0x15, 0x47, 0x4E, 0x33, 0x4B, 0x01, 0x37, 0x66 ]

x = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  ]

def changebits(eqn, mask):
	global x
	for idx in range(0, len(x)):
		x[idx] ^= random.randrange(256) & mask

def calc(eqn):
	global x
	res = 0
	for idx in range(0, len(equations[eqn])):
		res ^= x[equations[eqn][idx]]
	return res

def solved():	
	for eqn in range(0, len(equations)):
		if calc(eqn) != results[eqn]:
			return False
	return True

while not solved():
	eqn=random.randrange(16)
	while calc(eqn) != results[eqn]:
		changebits(eqn, calc(eqn) ^ results[eqn])
	for idx in range(0, 16):
		if x[idx] >= 0x20 and x[idx] < 0x7F:
			sys.stdout.write(chr(x[idx]))
		else:
			sys.stdout.write(".")
	sys.stdout.write("\r")
sys.stdout.write("\n")

Here's a movie clip from WarGames (1983) where Joshua is searching for the nuclear launch codes:



To win the snake NES game in challenge 8, I manipulated the game logic using the 6502 debugger of the FCEUX emulator.

Here's the C code I wrote (much faster than Python!) to perform a known-plaintext attack to find the key of the XTEA cipher in challenge 10 (MugatuWare):

#include <stdint.h>
#include <stdio.h>

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t key[4]) {
	unsigned int i;
	uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
	for(i = 0; i < num_rounds; i++) {
		v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0)  ^ (sum + key[(sum >> 11) & 3]);
		sum -= delta;
		v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1)  ^ (sum + key[sum & 3]);
	}
	v[0] = v0;
	v[1] = v1;
}

int main(int argc, char ** argv) {
	uint32_t v[2];
	uint32_t key[] = { 0x31,0x73,0x35,0xB1 };
	FILE *in;
	FILE *out;
	uint32_t num;
	for (key[0] = 0; key[0] < 0x100; key[0]++) {
		printf("%02X??????\n",  key[0]);
		for (key[1] = 0; key[1] < 0x100; key[1]++) {
			for (key[2] = 0; key[2] < 0x100; key[2]++) {
				for (key[3] = 0; key[3] < 0x100; key[3]++) {
					//v[0] = 0x4EE2F5C8; // informant file with key 0,0,0,0
					//v[1] = 0x6B97F416;
					v[0] = 0x50B08E24; // key to crack: 31 73 35 B1
					v[1] = 0x6F68B2E8;
					decipher(0x20, v, key);
					if ((v[0] == 0x38464947) && ((v[1] & 0xF0) == 0x30)) {
						printf("Found key:\n");
						printf("%02X%02X%02X%02X\n", key[0], key[1], key[2], key[3]);
						printf("%08X %08X", v[0], v[1]);
						return 0;
					}
				}
			}
		}
	}
	/*
	printf("%08X %08X", v[0], v[1]);
	in = fopen("best.gif.Mugatu", "rb");
	out = fopen("best.gif", "wb");
	while(!feof(in)) {
		num = fread(&v[0],1,4,in);
		if (num < 4)  {
			fwrite(&v[0],num,1,out);
			break;
		}
		num = fread(&v[1],1,4,in);
		if (num < 4)  {
			fwrite(&v[0],4,1,out);
			fwrite(&v[1],num,1,out);
			break;
		}
		decipher(0x20, v, key);
		fwrite(&v[0],1,4,out);
		fwrite(&v[1],1,4,out);
	}
	fclose(in);
	fclose(out);
	*/
}

Most of the flag of challenge 12 (help) could be found without bruteforcing the password of the KeePass database using John the Ripper or hashcat, simply by performing a unicode string search in the memory dump:

$ strings -el help.dmp | grep "@flare-on.com"

h3_br34dcrumbs@flare-on.com
mbs@flare-on.com