Endless Christmas X-MAS CTF Writeup

Posted on Sat 22 December 2018 in binary reverse, IT, security

This is a writeup for the Endless Christmas challenge, md5 hash 866c92038d6e9fc47db4424f71f6167a (download binary). It appeared in the X-MAS CTF, and it's a Reverse challenge.

Using afl with Radare we can see there are calls to write and execve, both happening in main, a sign that this program creates (and maybe executes?) something else.

radare

Putting a breakpoint just before the execve happens will reveal what file is being loaded (looking into the rax register).

radare

I went down 60 rabbit holes disassembling this binary further, but the best thing we can do at this point is change point of view, step out of Radare, and launch the binary by itself - it certainly doesn't seem to be doing anything nasty up to this point.

It takes some time before any output is shown, so this may be a sign that some decoding happens. The program creates a good number of other binaries which all look identical, albeit different from the original one (as their size shows), but that are actually different upon closer inspection with their md5 hashes.

radare

So of course, let's look at what's inside them.

radare

Opening one at random, we see that function names are different and more self-explanatory, but still not so helpful. Also, there are signs that this may be a scam, as sym.encode_85 is never called (discover it by running axt sym.encode_85). So it looks like it could be decoding the huge string the program stores (obtainable with a simple call to strings) in base 85, but trying to manually decode it doesn't yield much results. So far so bad. Uhm. Remember that all files are different, but they all look the same, and there is no immediate clue pointing at which should be the interesting one.

This is again a time in which you need to take a deep breath and consider stepping out of what you are currently doing. Launching the original binary with ltrace reveals that several calls to execve are made, and hints us at the fact that maybe only the last executed binary is interesting.

radare

But how to discover its filename, since ltrace only shows pointers? Let's run it with strace and find the relevant line amidst all the noise... There it is, right at the top of the window!

radare

radare

Bingo! This file has no decode/encode_85 functions and similar, but only a big main. This main now really contains the behavior that we observe in the program, asking for a flag and all.

However, we soon realize that this is a scam again - there is no way to get to the successful "MERRY CHRISTMAS!" message. One significant hint is that the buffer that is read from input is never really used in any purposeful way. What the program does is scan a string of his own char by char, xor each char with 0xd, and then check if al is the same as dl. This is never the case, and can never be, and in fact if we try to debug that routine, we see that the program always exits after the first iteration.

radare

But we already have all that we need! Remember that the program xored each char of its string with 0xd - maybe that is the solution? Let's write a small program to reproduce this behavior:

#include <stdio.h>
#include <string.h>

int main(){
  int i;
  char str[] = "U @L^vi>n=i>R9;9<cR9ciR9;9<cR9ciR9;9<cR9ciR9;9<cR9ciRka9;p";
  char output[200];

  for (i=0; i<strlen(str); i++)
    output[i] = str[i] ^ 13; //13 = 0xd

  output[i] = '\0';
  printf("\n %s \n\n", output);

  return 0;
}

And booom! We get the flag!

terminal