There are a lot of moments which I telepathed and synced with the challenge author. If it doesn’t make sense to you, just bear with it.

This is a beginning of a new series of blog posts that I review CTF challenges those are not publicly accessible. Generally I will spend some time to solve the challenge while discussing with the author, and give some feedback of the challenge.

To kick-start, let's look at hoifanrd from Firebird CTF team has shared a challenge he created some days ago.

Some readers may not be familiar of Firebird CTF team. It is formed by students from the Hong Kong University of Science and Technology (HKUST). I was not a student there, but most of my teammates of Black Bauhinia were. Hence, it is natural I got invited to the Discord server. This is their team on CTFtime.

Background

At around 11pm of January 25, I received a direct message from hoifanrd that he is going to make a guessy challenge. I replied "make it" in few minutes. On the next morning, I saw a challenge came alive in the Discord server of the Firebird CTF team.

Did you see a pandora's box?
🔎 What is “tuning”? Tuning has a similar pronunciation to 通靈 in Cantonese and it means mediumship. UCCU hacker from Taiwan used it to describe the guessy challenges that required telepathy between the players and the challenge authors, and is quickly popularized in the CTF teams we knew in Hong Kong.
Shamelessly stolen from the Facebook page of UCCU hacker.

Challenge Summary

This is the challenge description he left in the Discord server:

The journey starts here... P2k9ZmhuM2U5U2pkeDA=

On top of that, he also commented that the challenge would be fun since it involves some abnormal stego and hiding techniques.

Solution

Part I: An obvious base64

Instead of the above base64-encoded string, I started with the challenge description he DMed me (as below). At that time I was not awared of the description he sent to the server is different from what he sent to me.

The journey starts here... ZmhuM2U5U2pkeDA=

Noticing that the string being encoded in base64 is not hard. Decoding it, I have fhn3e9Sjdx0. Knowing that being an osu!-related challenge, I thought this is an username he created in osu!. Turns out it isn't. I honestly had no clues and searched osu fhn3e9Sjdx0 on Google. It returns only one entry - A YouTube video recording the osu! gameplay of firebat92. Well it is very likely to be unrelated. I don't even know the reason it came to my search result, since the second keyword isn't found anywhere. In particular, the video ID is jbTebNnwarg, which is not what I expected.

Well... I was messing around and tried to plug fhn3e9Sjdx0 as the video ID. Video unavailable. However, one thing I learnt is that the video ID of YouTube is 11 characters long... Coincidence? Later I was reminded by hoifanrd that the challenge description I received is not up-to-date. For the updated one, it is ?i=fhn3e9Sjdx0 decoded. I am more convinced that it is a YouTube video. Let's figure out how to convert the i into v?

The first thing I think is Caesar cipher. I bet it wouldn't be Vigenere cipher owing to its short message, and I would definitely question the author's knowledge on computer science if it is Vigenere cipher. I threw the ciphertext to cryptii.com and eventually found ?v=sua3r9Fwqk0...

Oh wow. So it is actually an video on YouTube.

Time elapsed: 10 minutes.

Part II: Figuring out that being a .wav stego...

It is almost impossible to solve the challenge by myself since this part. I am heavily hinted by hoifanrd.

hoifanrd played two beatmaps in the video. They are

  1. Hyakka Ryouran Hanafubuki [Iceluin's Hard] mapped by Hojo Karen (0:00-3:47), and
  2. Koyoi Tsuki no Yakata Nite (Cover) [Hard] mapped by hoifanrd (3:55-7:43).

Knowing that being a stego challenge, it must be the second beatmap that the secret is hidden. At first, I wanted to see if something inside the video. I was soon stopped by hoifanrd and pointed that I am not on the right track. Well, since we can download the beatmap from osu.ppy.sh, let's download the beatmap and analyse. It is an .osz file that can be opened like zip file.

I suspect that there is only one file with the secret hidden. I could immediately eliminate five files because they are modified earlier than Jan 25, the day he told me that he had an idea. I quickly looked into the three .osu files and didn't find anything fishy. After all, it is very likely to be a .wav stego.

Of course, I would not have the above conclusion unless hoifanrd confirms that. He also informed me that there should be a passphrase

Okay, so what I have to do is to find both the passphrase and the correct tool hiding the secret bits.

Time elapsed: 75 minutes (+ 65 minutes).

Part III: Finding the passphrase

After a long break (i.e. my working hours), I am back to the challenge. Without the passphrase, I am unable to tell if the tool is correct. Hence I decided to find the passphrase first. Knowing that there are two beatmaps in the video those serve their own purpose, I was focusing on the first gameplay. If the second gameplay contains the secret, then the key must be hidden in the first one.

Well... I made no progress for an hour and at some point of time I decided to stream on the Discord server. Eventually hoifanrd thinks I am too weak and decided to give me some hints:

It should be something that is easy to aware... notice the cursor

After a short while, I noticed a cursor having a heartbeat behaviour on 2:46, the cursor was not pumping on the other timestamps. It must be morse code.

However there is no significant time difference between a dash and a dot. What can we do to distinguish dashes from dots? Well, if you met some conditions, then the replay will be recorded and uploaded to osu.ppy.sh (as an .osr file). The first gameplay satisfies such conditions and is available online. There are multiple approaches to read an .osr file, since I am lazy to install osu! for that, I found a Python package on Github called osrparse. Doing some math, I identified the time interval of the heartbeat and extracted the key pressed during the interval.

The above figure marks the keys pressed during the interval:

  • A blue dot is the place he pressed M1,
  • a red dot is the place he pressed M2, and
  • a green dot is the place he pressed M1 and M2.

After all, we have .​-- . .​-.. --- ...- . ... .​- --, which decodes into WELOVESAM.

Who’s Sam? Sam is a well-loved trainer of their team. He once made a guessy forensics challenge and pretended that it was made by another trainer in the team. The Firebird members made the below picture to express their love to Sam…

Time elapsed: 200 minutes (+ 135 minutes).

Part IV: The final bits

The only thing remaining is to find the correct tool to extract the secret hidden in the .wav file. Since steghide is the most common one amongst them, I am able to extract the secret with the following command.

steghide extract -sf audio.wav -p WELOVESAM

I have extracted the message below. Well, I quickly realized that is nonogram.


7 2 2 1 1 7
1 1 2 1 1 1
1 3 1 1 6 2 1 3 1
1 3 1 2 1 3 1 1 3 1
1 3 1 4 3 2 1 3
1
1 1 1 1 1 1 2 1 1
7 1 1 1 1 1 1 1 7
1 1 2 2 1
4 1 1 4 1 2 3 1
1 2 2 1 3 2
1
1 1 1 1 3 2 1
1 1 5 4 2
1 5 1 1 2 1 3
1 1 5 1 2 1 1 1 1
3 1 3 1 1 2 1 1 3
2 1
1 1 2 3 4 1
1 3 1 1 1 3 5
1 1 1 2 2 1 2 1
1 6 3 1 3
3 4 1 4 1 1 1
1 1 2 1 3 8
3
1 1 3 5 1 2
7 1 3 1 3 1 2 1
1 1 1 2 1 2
1 3 1 1 1 6
1 3 1 2 2 3 2 1 2 1
1 3
1 4 1 2 1 1 1
1 1 4 2 1 1 2 1
7 3 1 1 1 3 1 1

7 1 1 1 7
1 1 2 2 1 1 1 1 1
1
3 1 1 1 1 1 1 3 1
1 3 1 1 4 3 1 3 1
1 3 1 1 1 1 1 2 1 3 1
1 1 1 2 1 1 1 1
7 1
1 1 1 1 1 1 7
3 1 3
1 3 1 2 2 1 2 1 4
1 3 1 1 3 2 1 4
1 1 3 3 1 3
3 1 3 1 1 1
1 3
1 2 1 2 6 2 1
1 1 1 2 1 1 1 1 3 1
1 1 5 2 1 1 2 2
3 1 1 3 1 1 1
4 5 2 2 1
2 1 1
1 1 1 1 1 2 3 1
1 1 1 1 2 4 4 2
1 1 2 1 1 4 4 1 2
1 1 2 4 3 5 1 1
1 2 1
1 1 2 1
7 1 2 1 1 1 1
1 1 1 2 1 1 2 1
1 3 1 3 3 1 6 2
1 3 1 3 1 2 1 1 2 1
1 3
1 1 1 1 1 3 1
1 1 4 3 4 2
7 2 1 2 1 3 1 2

I like playing puzzle...

Unfortunately, hoifanrd noticed that the message isn't correct owing to some issues regarding to line breaks. I have received an updated message from him:


7 2 2 1 1 7
1 1 2 1 1 1
1 3 1 1 6 2 1 3 1
1 3 1 2 1 3 1 1 3 1
1 3 1 4 3 2 1 3 1
1 1 1 1 1 1 2 1 1
7 1 1 1 1 1 1 1 7
1 1 2 2 1
4 1 1 4 1 2 3 1
1 2 2 1 3 2
1 1 1 1 1 3 2 1
1 1 5 4 2
1 5 1 1 2 1 3
1 1 5 1 2 1 1 1 1
3 1 3 1 1 2 1 1 3
2 1 1 1 2 3 4 1
1 3 1 1 1 3 5
1 1 1 2 2 1 2 1
1 6 3 1 3
3 4 1 4 1 1 1
1 1 2 1 3 8 3
1 1 3 5 1 2
7 1 3 1 3 1 2 1
1 1 1 2 1 2
1 3 1 1 1 6
1 3 1 2 2 3 2 1 2 1
1 3 1 4 1 2 1 1 1
1 1 4 2 1 1 2 1
7 3 1 1 1 3 1 1

7 1 1 1 7
1 1 2 2 1 1 1 1 1
1 3 1 1 1 1 1 1 3 1
1 3 1 1 4 3 1 3 1
1 3 1 1 1 1 1 2 1 3 1
1 1 1 2 1 1 1 1
7 1 1 1 1 1 1 1 7
3 1 3
1 3 1 2 2 1 2 1 4
1 3 1 1 3 2 1 4
1 1 3 3 1 3
3 1 3 1 1 1 1 3
1 2 1 2 6 2 1
1 1 1 2 1 1 1 1 3 1
1 1 5 2 1 1 2 2
3 1 1 3 1 1 1
4 5 2 2 1 2 1 1
1 1 1 1 1 2 3 1
1 1 1 1 2 4 4 2
1 1 2 1 1 4 4 1 2
1 1 2 4 3 5 1 1
1 2 1 1 1 2 1
7 1 2 1 1 1 1
1 1 1 2 1 1 2 1
1 3 1 3 3 1 6 2
1 3 1 3 1 2 1 1 2 1
1 3 1 1 1 1 1 3 1
1 1 4 3 4 2
7 2 1 2 1 3 1 2

I like playing puzzle...

I have imported the nonogram to an online nonogram solver. The solver occasionally stop working owing to unknown reasons (maybe the solution is not unique), so I decided to guess the shaded bits. Luckily I am streaming this, so that the ones who are watching can also deal with it while I am stuck.

Crowd-sourcing nonogram. Credit to TWY.

Shortly after, we have enough information for the QR code to be scanned correctly: flag{W3_l0v3_S4m_4nd_p1z_dun_1ov3_m3}. Sam is blushed.

Time elapsed: 220 minutes (+ 20 minutes).

My Feedback

In short, there are a few steps to get it through.

  1. Decode with base64 and decrypt with Caesar cipher for the video link
  2. Find the file that conceals the secret something
  3. Find the passphrase to open the secret
  4. Find the steganographic tool to open the secret
  5. Solve the puzzle from the secret for the flag

The challenge is not difficult itself, but I am very sure that I am unable to solve it on my own. Parts 1 and 5 are okay. I would think part 4 is guessy if it is not steghide. However, parts 2 and 3 are the toughest parts. They are the most guessy, but at the same time I learnt something interesting.

To solve parts 2 and 3, you need to know what hoifanrd thinks (or wait until he gives hints). There are two beatmaps, and the reason why it got to be two is:

  1. The replay will be uploaded only if the gameplay is one of the top 1000 games in a given ranked beatmap. The first beatmap (Hyakka Ryouran Hanafubuki) satisfies the condition, hence you are able to download the replay from osu.ppy.sh.
  2. Needless to say, you can hide steganographically the .wav file in your own beatmaps.

Apart from this, you do need good eyesight to solve the challenge. Otherwise it will be impossible to notice the morse code during the break time... It is good to learn parsing .osr files and liked the idea of hiding something in such a way.