December is finally here! And what better way to celebrate than with a good old CTF? — contextis.com

Click here for the original web page.

We’re given a clue, and a cipher to decrypt. The clue is a bit strange, it makes sense to begin with 1+1=2, 2+2=4, 4+4=8, but then you reach 8+8=7?

The main thing to take note on is the fact the elf calls it ‘A lossy cipher’, implying data is lost upon encryption and that this cipher may just be a glorified hash or checksum.

And those of you with a keen eye may have noticed that 8+8=16, and that 1+6=7. So our best guess is that because the ciphers are all 1 digit, we could assume that they are the output of this checksum function. Following this line of thought, let’s assume that the inputs of this function are in the range 1 to 26 inclusive (as those can correlate to the letters of the alphabet.).

After these assumptions we could begin to write a script to find out all the input numbers in the range 1–26 inclusive, that will turn into the values in the cipher.

This is the script I came up with, let’s step through it and explain what each part is doing.

Here I have the shebang, an import of the alphabet (to convert numbers to letters) and the cipher as a list of integers.

This is the ‘meat’ of the code so to speak, this function works out what numbers from 1–26 such that when you add the digits of the number it results in whatever number you specify, for example: If you pass in 4, it returns [4, 13, 22].

It works out the first possibility by simply using the number you pass in, since it’s only got one digit so it adds to itself.

The second possibility is that it starts with a 1, so first we check if the number given is 1 or higher, and if so we add it to 10 and minus 1 (+9), so 4 goes to 13.

Then we apply the same logic to if it starts with 2, by checking if it is 2 or higher, adding 20 removing 2 (+18), so 4 goes to 22. However this means a value such as 9 can go to 27, but this is out of range (there’s no letter after z!) so we limit the x values by checking if they are less than or equal to 8.

The last possibility is a special case, as if you plug in 1 (without these two lines) the function returns [1, 10]. However, if you checksum 19, you get 1+9=10, which isn’t 1 digit, so we need to apply the checksum again 1+0=1. This is the only exception to the previous possibilities, as it’s an exception, I just check if it’s equal to 1, and if so add 19 to the list of possibilities.

This next part applies the function pos to every number in the cipher, and then converts it to a letter, so we get a list of lists, where each nested list is a list of possible characters that could be in that position.

Then we print it out so we can look at it.

Running results in this output, and by reading across you may notice that you can form ‘merrychristmasyoufilthyanimal’ by selecting the right letters from each group of letters.

And that’s it, the answer!

MERRYCHRISTMASYOUFILTHYANIMAL