BLK_BOX Challenge Write-up

George O
George O
Feb 16, 2020 · 8 min read

Around 6 months ago, HMGCC released a challenge and offered a challenge coin to anyone who completed it. I started pretty late on, but managed to get it done in time. This consisted of 7 stages, ranging from reverse engineering to traffic analysis. At the time of writing, you can still have a go yourself here.

Challenge One (Introduction)

Once on the dashboard, I was presented with the following:

I downloaded the image, and spent a while trying every possible steganographic method of finding & extracting data on my site. This unfortunately didn’t lead anywhere. The next day, I went back on the site and accidentally hit CTRL-A, which revealed a hidden symbol on the page, placed just above the photo:

It turns out that all we needed to do was click this hidden “?” to properly start the challenge… :(

The “?” text was a link to “`”:

I downloaded the file provided at that link, and checked its filetype:

file ‘`'

Great — we can now just make the file a .pcapng, and open it in Wireshark.

The pcap file consisted of 1102 packets, with 997 of those being TLS-related (handshakes or data transfer). We can filter out all of these with the “!tls” filter:

The remaining non-TLS packets.

After looking at the hex data for the first packet, we can see the PK zip header being sent:

In order to download all of the data sent in this packet stream, I selected “Follow Packet Stream” in the Wireshark context menu and saved all client packets as raw data.

This left me with a zip file: “”. This zip contained the flag to level up on the leaderboard, and also some files for a webpage.

Challenge Two (Decrypting SSL)

The webpage contained in the zip file from before looks like so:

A quick Google search of Peter Wu reveals his talks on SSL/TLS security. From this, we can work out that the CLIENT_RANDOM can be used to decrypt TLS traffic. You can find Peter Wu’s whole talk on this topic here.

In Wireshark, we can decrypt TLS data in one of three ways; A log file containing client random key values, RSA keys, or a pre-shared key (see the menu below):

By adding the CLIENT_RANDOM to a Pre-Master Secret log file, the TLS traffic can be decrypted (note that I had to put the text onto one space-separated line)!

After doing so, one packet in the pcap became decrypted:

Another zip file! I followed the TSL stream and extracted this file to find another leaderboard code & webpage.

Challenge Three (Polyglot PDF)

The webpage from the previous challenge showed the following:

Opening the linked PDF in Firefox reveals a QR code:

We can parse this QR code in CyberChef to find some text:

Part 2 of 6. fdfdd655df8fec1f200b0f4e

Since polyglot files generally consist of many different files, I used binwalk to scan for and extract all embedded files:

binwalk -Me ch3.pdf

The -M option of binwalk recursively extracts files, which means that all other hidden files were extracted:

We can see that there were also hidden files inside of an embedded jpg file. Each extracted pdf contained another QR code, which all contained another part of the client random. After parsing each QR code from each PDF, I pieced together a full CLIENT_RANDOM:

Part 1 of 6. CLIENT_RANDOM 2cada223acPart 2 of 6. fdfdd655df8fec1f200b0f4ePart 3 of 6. 54b8d36e353ce323c0cf1b1aPart 4 of 6. 7d0664 7c6a4ab59fd52b210Part 5 of 6. b77d14bae0c5aee79f27830fPart 6 of 6. f35f00752931069c7ff4fa49a2ab5292f7ca2bb0f8139da4a84372eFull CLIENT_RANDOM: CLIENT_RANDOM 2cada223acfdfdd655df8fec1f200b0f4e54b8d36e353ce323c0cf1b1a7d0664 7c6a4ab59fd52b210b77d14bae0c5aee79f27830ff35f00752931069c7ff4fa49a2ab5292f7ca2bb0f8139da4a84372e

Adding this to our Premaster Secret log file then allows us to decrypt another zip file packet in the pcap:

Extracting the zip then reveals our next challenge.

Challenge Four (Single-byte XOR)

The next webpage from the zip presented us with the following:

Searching for the suggested title “015776–320080” returns only two results:

As shown, it’s a game for the Atari ST called “XOR”. With this in mind, I used CyberChef to perform a simple single-byte XOR bruteforce on the first file.

Since we’re looking for a .wav file (with the RIFF) header, I added “RIFF” as the crib:

This quickly found the key to be 88. We now just need to XOR the file contents by 0x88 to find the correct file. After downloading the full correctly XOR’d file, we get the correct WAV file. This just played some music :)

I then performed the same 0x88 XOR function on the second file, and played that. The following could be heard:

Hello. This is black box. Well done on cracking the audio file. If you want the key, do some more digging on this file.

Running a simple strings on the file shows what we’re looking for:

strings -n20 chal4_b.wav

We thus have the new CLIENT_RANDOM:

CLIENT_RANDOM adeb1b6d4c0b4bbae55a03360151a7d6d9d6a0d003778d9eb80030a9779120b4 80f137fa493e133ecaf6b8c6a4fb767715be41be8cc54e6c17ae37f4afc5b78028198b6bc8e2b2d70939ae7221a38f38

Adding this to the Premaster Secret log file decrypts the next zip from the TLS data, which contained the next challenge webpage.

Challenge 5 (Four-byte XOR)

We’re told that it’s a 4 byte XOR key. Unfortunately, CyberChef crashes when trying to perform such intense operations. As such, I scripted my own bruteforce tool:

Instead of bruteforcing one 4-byte key, this script splits the text into 4 pieces; one for each part of the key. Because of this, we can still crack the key in sub-1 second:

CLIENT_RANDOM 6176130068e9f8b5ce78cfa21042bc314dba24fbbdae28a23ef07771ea96c702 8078e8eef5028313b4cba11a58d0bbab4462f6a3643617ec068bba5cc62ba9228488ffebd5fe81a3820c56c59a27b7ea

I can then add this CLIENT_RANDOM to our log, and unlock the next challenge!

Challenge Six (Reverse Engineering)

We are given a zip file called “”, containing a C program with a shared library:

The C program looks as follows:

Since the program does little other than sleep, we can assume that the sleep function is overridden in the chal6 library. In order to correctly run the program with this shared library, we have to load it with LD_PRELOAD like so:

pwdngdb shows us relevant info every step, & so is more useful for this than gdb.

Let’s set a breakpoint at sleep and then step through the program. After stepping through seemingly unimportant stuff for a while, we can see a few interesting things:

  • There seems to be a hash stored at 0x7fffffffdf80: “$1$qiMPPksI$ifK9ZQljxfBAvAy1cN/KQ1”
  • There is a ptrace trap at 0x7ffff7dcbd22, which we’ll need to skip over
  • There’s an intersting cmp at 0x7ffff7dcbd27

We first need to step over the ptrace, which can simply be done with “so”.

The compare function at 0x7ffff7dcbd27 compares rax to -1 (see previous image). We can bypass this check by setting rax to 0 with “set $rax=0”, and then continuing.

After then stepping on for a while longer, we hit the main strcmp call: This will be where our inputted number in the C program is compared against the hash seen earlier:

We can set our own hash to match that of the desired one with the following command:

set {char [35]} 0x555555756450 = "$1$qiMPPksI$ifK9ZQljxfBAvAy1cN/KQ1"

We can now see that the two strings being compared are identical:

We can then keep stepping on until the CLIENT_RANDOM pops up onscreen!

The CLIENT_RANDOM is therefore:

CLIENT_RANDOM b1bfc2a881f5a543bb1a4a06bfa846f8f18ade328996e546bfc42a9c134e783d b9c46e82ac5a3ceb403f220a3e2a1e9fec4347a764491f47a64bfa6240f7eb84e80ece32b3ed46a6dfd6b1aa339af08b

As before, we can add this to the log file, decrypt some more TLS packets, extract a ZIP and view the next challenge.

Challenge 7 (Quiz/Bruteforce)

We’re given a quiz, which we have to correctly answer in order to find the correct leaderboard flag. Whenever we select a true/false value, we are given a couple of the flag characters, i.e:

It looks like we have to fill in all the answers, and then check that the hash is correct by comparing our leaderboard code to the given SHA256 at the bottom of the page. While we could complete the quiz manually, it’s easier to bruteforce the correct answers.

For each of the 12 questions, we are given both a correct character and an incorrect character. I wrote this script to attempt all combinations until the correct SHA-256 hash is reached:

This can then find the correct code in around half a second:

Once the code is added to the leaderboard, the challenge is complete!

After a week or so, my coin arrived :)

Contact me:
Personal Website
Twitter: georgeomnet
Github: Ge0rg3
Discord: George#1234

CTF Writeups

A collection of write-ups for various systems.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store