Ekoparty CTF 2015 - Writeups

The evening after the hacklu CTF I had the urge to hack on some other challenges. Ctftime.org listed the ekoparty CTF 2015 as the first entry and there was one day left. In this blogpost I’m going to write up my solutions for the following challenges:

  • Slogans ( Trv 50)
  • SSL Attack (Trv 90)
  • Blocking truck (Trv 100)
  • Pass Check (Web 50)
  • XOR Crypter (Cry 200)
  • Press it (Misc 100)

And some notes on other services I’ve tackled.

I wish I had more spare time for this CTF. Some challenges seemed promising. Here’s what I’ve managed to solve:


The task was to find the slogans for the past ekopartys 2008 & 2009.

As the slogan is prominently shown on the website, my first idea was to use the wayback machine to view the older websites. Unfortunately, 2008 wasn’t recorded, so I decided to ask the allmighty Google. I fed it with the following google dork:

intext:ekoparty intext:2008 intext:slogan

Sceenshot of google dork

The first result was a blogpost which contained the slogans of both 2008 and 2009:

Sceenshot of ekoparty slogans 2008 and 2009

The accepted flag was: EKO{Vi root y entre_What if r00t was one of us?}

SSL Attack

The task was to find the name of one of the SSL attacks presented at ekoparty.

Again, a bit google magic (intext:ekoparty intext:ssl) listed websites containing some well known candidates as BREACH, CRIME and BEAST. The latter one was the correct solution.

BEAST SSL attack presented at ekoparty


Blocking truck

The description stated that there’s a blue truck in front of the entrance. The correct flag is the url on the truck.

At first I thought that I couldn’t solve the challenge as I’m not at the venue, but sitting in front of my laptop in Berlin. As I didn’t believe that they would create a task which could only be solved by local teams, I decided to open the contact page and paste the address into google maps. Voila! You can use streetview to view the blue truck:

Streetview of blue truck at ekoparty

The domain was a bit blurry, but typing desimonehnos.com.ar into google lead to the correct website. The task stated that the flag is the url to contact the company. I needed some tries to figure out that the url to the landing page was enough.

Flag: EKO{http://www.desimonehnos.com.ar} or EKO{www.desimonehnos.com.ar} (can’t remember it anymore..)

Pass check

This was the first web challenge. It looked funny and made funny sounds when entering characters ;)

Screenshof of pass check input box

The sound and the blinking numbers were nice, but didn’t have anything to do with the solution. I started up BurpSuite to capture the ajax call. After trying some easy guesses, I replaced the password=test with password[]=test and the application was so kind to display the flag.

Screenshof of pass check input box

Flag: EKO{strcmp_not_s0_s4fe}

The function strcmp isn’t good at comparing things that aren’t strings. An interesting list can be found on php.net.

XOR Crypter

This task provided the following string CjBPewYGc2gdD3RpMRNfdDcQX3UGGmhpBxZhYhFlfQA= and some python code.

The string is obviously base64 encoded, but decoding it didn’t seem the be helpful (0O{sh1_t7_uhiabe}), so I had to have a look on the sourcecode. The encryption algorithm first pads the data to be a multiple of 4. After that it’s split into chunks of 4 bytes. Every block is xored with a 16-right-shifted version of itself. I looked up the operator priority and >> comes before ^. The final operation is to pack every block and base64 encode the result.

The main issue here was the use of XOR in combination with the right-shift. Here’s a simulation of happens:

# 1001 >> 2 (9 shifted by 2 adds zeros to the beginning and the result is 0010 = 2)
# 0010 ^ 1001 (2 xored 9 is 1011 = 11; This is the result of our encryption.)

# 1011 >> 2 (11 shifted by 2 is 0010 = 2)
# 0010 ^ 1011 (11 xored with 2 is 1001 = 9)
# 1001

Note that a N-right-shift caused the first N bits of the xored block to be the same as the input block. The reversibility of XOR ((Y ^ U) ^ U = Y) helps us to recover the remaining part of the block. The other operations (base64-encoding, (un)-packing) have to be applied in reversed order. Here’s a link to my dirty-hacky-python-code (I’ve added some print/debug statements…)

Screenshof of XOR crypter output

Flag: EKO{unshifting_the_unshiftable}

Press it

In my opinion this was the most interesting challenge which I’ve successfully solved. The task was to extract the flag from the following file.

I first thought that these are just some random hex numbers, but then recognized the format again. I saw it when I executed /usr/bin/showkey when trying to solve the dr.bob hacklu 2015 challenge. I opened tty2 on my machine and ran showkey -s and it printed similar hex numbers when I hit my keyboard.

I started googling for a program or tool which would automatically decode the scancodes to ascii characters, but to no avail. (Or at least not running on linux and I didn’t want to install wine)

Reading through the showkey manpage I learned that those codes are called scancodes which are unique per key. There are always two scancodes per key: One when it’s pressed and one when it’s released.

The last fact is important, because I first tried to decode the characters only with the ‘pressed’ codes and that turned out to look weird (Pastebin). All the ? or empty codes are mostly key releases. Additionally, I had to learn the hard way that scancode-combinations are also possible on some keyboards. E.g. 0xe0 0x38 is Left-Alt. Microsoft has a good document with scancode mappings.

After going through all scancodes a second time I had the following result in my notepad: This is it. EKO{ibm_model_m}

Flag: EKO{ibm_model_m}

Other challenges/notes

As always, I had a look on other challenges and tried to solve them, but eventually got stuck somewhere. I’m a bit disappointed that I didn’t manage to solve Mr Anderson (I don’t know the film, but googling the solution shouldn’t be that hard?), Custom ACL (I’ve spent a great portion of the time with this one. Probably only one tiny step missing).

Mr Anderson (Trv 80)

  • Mr Anderson and last serie point to Mr.Robot
  • Can’t figure out the favority music artist part. Tested some artists of the last episode’s soundtracks. No luck
  • Not enough motivation to brute force all possible artists.

Custom ACL (Web 100)

  • Discovered sourcecode of admin.php at admin.phps (Pastebin)
  • Tried to spoof REMOTE_ADDR with X-Forwarded-For & co until learning that it really only is the IP of the TCP-connection.
  • Running nmap against the IP range results in one host with some interesting ports (Pastebin)
  • Trying to use it as a proxy always fails with the message 501 method "GET/POST/Whatever" not supported
  • Noticing the Server: pve-api-daemon/3.0-header, but can’t figure out how to (ab)use the proxmox daemon for the solution.
  • Not enough time to further analyse it.

Crazy JSON (Web 300)

  • evaluator.js missing on the server: suspicious
  • HTTP Response contains interesting JSON (Pastebin)
  • new Ajsone() call. Google points to a github repository with demo input/evaluation area.
  • Xor (^) isn’t implemented. Implementing it.
  • Password has to be 32 characters long, but further evaluations/execution lead to an error inf loop?.
  • No time to further investige it. Nevertheless interesting :)

SVG Viewer (Web 400)

  • Uploading SVG with XXE testvector -> Entity declaration detected error
  • Idea of using an own external DTD to bypass this check. Doesn’t really work as expected. Running out of time -> context switch to another challenge

Olive (Misc 50)

  • Mostly VNC traffic / Http traffic doesn’t look interesting
  • Extracting VNC traffic to file. Seems like a RFB (remote frame buffer)
  • Looking for a tool to replay it. Neither rfbproxy nor vncreplay work well with the dumped data.
  • Running out of ideas on how to replay/view/decode the RFB

Again, thanks for this awesome CTF :)