shift or die

security. photography. foobar.

mrmcd CTF writeup: Once Upon A Time

I recently participated in the MRMCD CTF, which had a challenge called “Once Upon A Time”. The hint for the binary was that it will simply print the flag … but some patience might be required.

Since I am way less binary reverse-engineering ninja than might appear from the scoreboard, I threw the binary into the Snowman decompiler.

Here, I could recognize the following structure quickly:

v4 = 0;
do {
	v5 = 1;
	while (v5) {
		++v5;
	}
	--v4;
} while (v4 != 77);
fun_640("%d done\n", 0, 64, "%d done\n", 0, 64);

v6 = 0;
do {
	v7 = 1;
	while (v7) {
		++v7;
	}
	--v6;
} while (v6 != 82);
fun_640("%d done\n", 1, 64, "%d done\n", 1, 64);

[...]

So the challenge hint was technically correct, the inner while loop would run until the (int64) v5 would overflow and become 0, while the outer loop would terminate eventually when v4 was decreased from 2**64 to 77.

At this point, one could have patched the decrements into increments and vice-versa, but that seemed quite tedious.

If you squint closely though, you can notice that the desired values for v4 and v6 correspond to the ASCII characters M and R, the usual start of a flag. During the CTF I just proceeded to manually convert them and concatenated them, but for the sake of (useless?) automation here’s a one-liner to get the flag:

$ grep '} while (v' once_upon_a_time.c | cut -d'=' -f2 | cut -d ')' -f1 | python -c 'import sys; chars = sys.stdin.readlines(); print("".join([chr(int(c, 0)) for c in chars]))'
MRMCD{so_sorry_for_the_delay}