Creative challenge that involved several layers of encoding to reveal a flag. The challenge being the obscurity of the first layer.

We’re given a ZIP containing one file and a clue with some hints that the cipher may be of East German origin. Some googling quickly gives us the name of the cipher “Tapir” which fits as it’s an anagram of “Pirat” from the clue. However it’s not immediately clear how the Tapir cipher relates to the file we have which, appears to be UTF-8 gibberish initially.


A hint is dropped about how “there were 9 planets between 1935-2006” and I’m wondering how planets are related to UTF-8 gibberish and Tapir ciphers. I decide to take the UTF-8 symbols at face value and look into if there’s any correlation there.

I find that indeed, the planets do have symbols. There’s a few Wikipedia pages with some documentation on these very symbols, here for example.

So if we assign integers to these symbols in the range of 1 – 9 based on their index from the Sun we learn two things:

  • Only four planets are represented using four different symbols
    1. Neptune (Trident)
    2. Venus (Female)
    3. Pluto (weird P thing)
    4. Earth (XOR symbol)

I wrote a converter in Python to quickly produce a translation of the planetary symbols into integers:

# -*- coding: utf-8 -*-

import codecs

ciphertext ='README.txt','r','utf-8').read()

planets = { u'♀' : 2, u'⊕' : 3, u'♆' : 8, u'♇' : 9, ' ' : '' }
nextcipher = "".join([str(planets.get(c)) for c in ciphertext])

print nextcipher

Which gives us the following long list of integers:


At which point the relationship to “Tapir” cipher begins to make sense. If we dredge up a Tapir cipher decoder we can see these integers can possibly make sense in that context.


If we split these into groups of two integers and decode with Tapir cipher we get the following output:

.- --.. ..-. .... .-- - - ..-. -- ...- ... 
... -.-. -..- ..--- ..- --. .- -.-- .... 
-.-. -..- ..--- -.. --- --.. ... .-- ....- 
--.. ...-- ... .-.. ..... .-- --. . ..--- 
-.-. --... -. --.. ... -..- . --- .-. .--- 
.--. ..- -...- -...- -...- -...- -...- -...-

Which is immediately recognizable as Morse Code. So we decode further and find the following:


Ok now we’re looking at some Base32? Decoding it it appears we’re on the right track:

  • VJ{Neee!_T00q_Cvengr_lbh_ner:)}

Which, when we ROT13 we get:

  • IW{Arrr!_G00d_Pirate_you_are:)}

Full problem and solution on my GitHub here:

About The Author


  1. What made you think it was Base32 and not Base64?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>