The Cicada 3301 Mystery (Puzzle 2 Solve)
Only 366 days since Puzzle 1 dropped from the mysterious Cicada 3301 when another image was uploaded to 4chan.
Unlike the first puzzle. There was no obvious information attached to this file to give any hints. It was straight to "outguess" to extract whatever information hide in this image.
Another book code journey awaited.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Welcome again. Here is a book code. To find the book, break this riddle: A book whose study is forbidden Once dictated to a beast; To be read once and then destroyed Or you shall have no peace. I:1:6 I:2:15 I:3:26 I:5:4 I:6:15 I:10:26 I:14:136 I:15:68 I:16:42 I:18:17 I:19:14 I:20:58 I:21:10 I:22:8 I:23:6 I:25:17 I:26:33 I:27:30 I:46:32 I:47:53 I:49:209 I:50:10 I:51:115 I:52:39 I:53:4 I:62:43 I:63:8 III:19:84 III:20:10 III:21:11 III:22:3 III:23:58 5 I:1:3 I:2:15 I:3:6 I:14:17 I:30:68 I:60:11 II:49:84 II:50:50 II:64:104 II:76:3 II:76:3 0 I:60:11 Good luck. 3301 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAEBAgAGBQJQ5QoZAAoJEBgfAeV6NQkPf2IQAKWgwI5EC33Hzje+YfeaLf6m sLKjpc2Go98BWGReikDLS4PpkjX962L4Q3TZyzGenjJSUAEcyoHVINbqvK1sMvE5 9lBPmsdBMDPreA8oAZ3cbwtI3QuOFi3tY2qI5sJ7GSfUgiuI6FVVYTU/iXhXbHtL boY4Sql5y7GaZ65cmH0eA6/418d9KL3Qq3qkTcM/tRAHhOZFMZfT42nsbcvZ2sWi YyrAT5C+gs53YhODxEY0T9M2fam5AgUIWrMQa3oTRHSoNAefrDuOE7YtPy40j7kk 5/5RztmAzeEdRd8QS1ktHMezXEhdDP/DEdIJCLT5eA27VnTY4+x1Ag9tsDFuitY4 2kEaVtCrf/36JAAwEcwOg2B/stdjXe10RHFStY0N9wQdReW3yAOBohvtOubicbYY mSCS1Bx91z7uYOo2QwtRaxNs69beSSy+oWBef4uTir8Q6WmgJpmzgmeG7ttEHquj 69CLSOWOm6Yc6qixsZy7ZkYDrSVrPwpAZdEXip7OHST5QE/Rd1M8RWCOODba16Lu URKvgl0/nZumrPQYbB1roxAaCMtlMoIOvwcyldO0iOQ/2iD4Y0L4sTL7ojq2UYwX bCotrhYv1srzBIOh+8vuBhV9ROnf/gab4tJII063EmztkBJ+HLfst0qZFAPHQG22 41kaNgYIYeikTrweFqSK =Ybd6 -----END PGP SIGNATURE-----
This book code followed patterns like the previous story. The hint at the top quickly pointed to The Book of Law by Aleister Crowley.
The code followed (given the example -
I:1:6) - Chapter 1, line 1 and letter 6. Once completed this actually built a now defunct Dropbox address.
This when downloaded was actually a 130mb ISO file. With tools available in 2021 it was easy to virtualize this with a few clicks. So below is an animation of the boot process.
If you watch this a few times you can notice a pause before it writes out 1033 and 3301. At this point in the world of Cicada - you can only assume iterations of 3301 are involved.
This OS ends and continues looping on a message.
@1231507051321 The key is all around you. Good luck. 3301
So investigating the ISO further led to the discovery of a few obvious files:
Outside of the mp3 file, the other files appeared to be gibberish with no known file magic/pattern. Though back to the message from the OS and it didn't take long for researchers to match that
@ sign to the familiar Twitter.
With a bit of scripting - you can dump all the tweets and the picture becomes a bit clearer.
This is commonly seen when exploring files at the hex level. The left side corresponds to the offset and right had the data itself. This output you see above is common when using the
However, the trail was running cold so it was time to look back at the Cicada 3301 OS. Looking back at the audio file (below) we can see this filename is
761.mp3 which is prime, and the song is also 167 seconds long which is also prime. Is anything by chance with Cicada?
I'd take a minute and listen to the song, but if you wanted to run
xxd over this song to dump the headers. You'd see something like:
➜ xxd 761.mp3 | more 00000000: 4944 3303 0000 0000 0144 5458 5858 0000 ID3......DTXXX.. 00000010: 008c 0000 0050 6172 6162 6c65 2031 2c35 .....Parable 1,5 00000020: 3935 2c32 3737 2c36 3431 004c 696b 6520 95,277,641.Like 00000030: 7468 6520 696e 7374 6172 2c20 7475 6e6e the instar, tunn 00000040: 656c 696e 6720 746f 2074 6865 2073 7572 eling to the sur 00000050: 6661 6365 5c6e 5765 206d 7573 7420 7368 face\nWe must sh 00000060: 6564 206f 7572 206f 776e 2063 6972 6375 ed our own circu 00000070: 6d66 6572 656e 6365 733b 5c6e 4669 6e64 mferences;\nFind 00000080: 2074 6865 2064 6976 696e 6974 7920 7769 the divinity wi 00000090: 7468 696e 2061 6e64 2065 6d65 7267 652e thin and emerge. 000000a0: 5449 5432 0000 0015 0000 0054 6865 2049 TIT2.......The I 000000b0: 6e73 7461 7220 456d 6572 6765 6e63 6554 nstar EmergenceT 000000c0: 5045 3100 0000 0500 0000 3333 3031 fffb PE1.......3301..
Though if we look at the metadata that Ubuntu can read (presumably via the ID3 tags) we are missing some of that text.
Thankfully the text is human readable which reads:
The Instar Emergence Parable 1,595,277,641 Like the instar, tunneling to the surface We must shed our own circumferences; Find the divinity within and emerged
This appeared to be a dead end for research. So we had a data file from Twitter, 3 random data files and an audio file. It was a tweet posted a day after all the data dumps from Cicada that hinted that the dumps of data were over.
Now that we knew column size and a hint to basically start at the beginning and skip nothing. So lets get this stream of tweeted data back into a binary format. (Presumably it was only hexadecimal for Twitter consumption)
xxd -c 65 -r 3301_twitter.txt > 3301_twitter.bin
- -c cols | -cols cols
- -r | -revert
For those unaware with
xxd it is quite strict when trying to revert a hex dump. Throwing random commands at this wouldn't be working so getting a succesful revert was promising.
Next up was just brute forcing the binary file with the OS files as the binary file itself appeared to be nothing usable. There were so many logic gates to combine files (AND, OR, XOR, NOR, NAND, etc) that it just took a few iterations to land on XOR.
The breath of relief when the binary Twitter posts XOR`d into the mp3 file resulted in an image!
I'm sure at this point you know what is next. Time to outguess this image to assert the validity and look for clues.
This was slightly alarming - the message was empty, but at least it validated with a signature from Cicada. Maybe the signature was just validating that we indeed decoded the image correctly. It took a bit more investigating, but it turns out that empty space is not truly empty but a mix of tabs and spaces.
We can leverage vim for this. If we open up the file. We can ask vim to replace spaces and tabs with preferred characters.
:set list :set listchars=tab:0x,space:1
Since my vim knowledge isn't the best. This generates a line like:
Which isn't exactly binary, so a quick expression with bash
echo: "$(STRING//x)" and we get:
010000110110111101101101011001010010000001110100011011110010000001100101011011010110100101110111011100000011010001101101011101010111010100110010011010110111010001110111011010110110111001100110001011100110111101101110011010010110111101101110 01010111011001010010000001110011011010000110000101101100011011000010000001100001011101110110000101101001011101000010000001111001011011110111010100100000011101000110100001100101011100100110010100101110 01000111011011110110111101100100001000000110110001110101011000110110101100101110 00110011001100110011000000110001
Then we are just one step away from readable text.
"Come to emiwp4muu2ktwknf.onion" "We shall await you there." "Good luck." "3301"
Without getting too far down this path though - what is the Gematria Primus? Our hunt is taking us to an onion URL, but we just decoded an image that looks like a rune table. Traveling to the onion page resulted in a text representation of a cicada with a hint that web browsers are useless.
It didn't take long to realize the dated telnet protocol was the answer here. The server accepted a bunch of commands, but it appears the lucky "hello" resulted in the output that pushed this puzzle further.
Once again we were given a hex dump of a file. Smaller in size, but still 65 columns so off to
xxd we went.
➜ xxd -c 65 -r offset.msg > output_telnet ➜ file output_telnet output_telnet: ASCII text
This time our journey just resulted in a plain text file. Another message awaited.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Very good. You have done well to come this far. xsxnaksict6egxkq.onion Good luck. 3301 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAEBAgAGBQJQ6S0HAAoJEBgfAeV6NQkP/J0QALDqa3VJy9xLLlgI5jPhRIp4 fxebbNhtELOHYFkD5Z9ztQYGle7lKPM8lkMSnciIY059KIi5NSTV7I97sJboG3wt khHtZgNRw1v2WQ5uurCu5l1w+84/L5Jz2NmElxOBzWr68dlQYt2qfBQxk2zR/fTI TLCEGvFZtlnrNfBk7jsIyJYcXXPgabS47oP9vOEXlB1+Pm0C7uPPBPN7aqkfUPGl o1f2hscJf7Je2DvbZt+6exxYsm57Fp953XANAd/UpFVzT/852Xg63gtZrI+Smf3Z BVcjpCzyH3wS8R0iM+rp02CwJpJzsWGLxeQGmXL2SXBB43zVZAJql5UdXLTGXkbd nPMd3/CbJ+l7rO0YAg5p3Jf4KauX7Zd6Zc2wHKLOvfjQvEWXIY1CMhI68Bj0rZo/ M/fi313FFTPAm6xhKRv/tH/8wVrar2jY7wnE8XxhRsy74AZ5GqA2oHMefTAq3YuW 5PX8s682J4pkDUKHGa4y65vjIp16pmEInMALJGbwz6mtauBQqlS6ARsQfekDn3oZ yosS+gWC3jdIvH5s5WUQGVl7jyz9t4+3Tg5cT9Rn6pX2NVNXSxgzXXB4nI2XrrYa 4kQr5aWB8lssav3ryj5Cg2FHl1+MKO0gYv/UF3QT75MixQMu4M+5wCnNekgfuyO6 Zvybzp4s4SzRjkk9sMM6 =WYVO -----END PGP SIGNATURE-----
The onion resulted in a pretty boring output.
<html> <head><title>3301</title></head> <body> Patience is a virtue. <!-- which means, come back soon. --> </body> </html>
This was a unique onion as a configuration error led to the leaking of some data. A curious researcher attempted to telnet into this instance and caused an error to spew out.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>501 Method Not Implemented</title> </head><body> <h1>Method Not Implemented</h1> <p>abc to /index.html not supported.<br /> </p> <hr> <address>Apache/2.2.22 (Ubuntu) Server at li528-4.members.linode.com Port 81</address> </body></html>
What is interesting to note here is the Linode address. So at least Linode has some billing information on the entity behind Cicada, but I doubt they will share any of that.
So after a period of time. The waiting was over. The page updated with the following message:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 You already have everything you need to continue. Sometimes one must "knock on the sky and listen to the sound." Good luck. 3301 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAEBAgAGBQJQ85gbAAoJEBgfAeV6NQkP6joP/iHzBMvK6YZO24wv24RtstGJ dEMrC9BjtUhrB+F0++sHqWeYuueZ37bDstIoh6EOenRHpECD0QBPTc40aUl2Op1L 4NuUVCUQvfqo/kdWBmSdTP4xGoCtwcXoISfhSM/i+wXqRONSy4z0FrXA3N9yxFaK eqlNk47aZvyWWHcyYACUEar/V4kfGo8j58r2CisnfeNwat6I6ZfL9P370UVJQyG1 a0WV7rF015TLbwAJkwI1jX7GLPWOkRK3lP8qLJJodNvMPSSyUPyPB01ElgBopm+t U9bQb/wIGtGG74ezUvwhtDGtXJLWllZtrZx82mQQWzzn8hReqqX0T35idJlTfxIz aZDNjLCOQJZCngmXEN7iz47w/g67BQ5eoa6iEj7blFwzMwVO7M7pL+L6LZLnuXml Zv1oDNCuENrIo4j8VGLro9pLptiilsUA6xFRS9bfE7qeeBfmS4J8DScOddzLYNVv 5fKd6iaLJoAqJGkcKnAWPl5VViDhYRL0z1N80zpjm1cWtPBIS2odLMZT80VfMYQI 8XXaEmRqoP8/9EImapqeSk+qcrUkT1+2opKRTOf7754ptjvJq31jQJgeY2gKGtp1 jPXZiu9Pp3QQ5cRKIWIIdOFvcrVtIZ/P3OYhT0p4Z+L13fScUbr/kxI6KcZmY/1D Szqzyr8SW7zRz1ypGffc =UPkJ -----END PGP SIGNATURE-----
Immediately I recognize this phrase from Tron, but I don't think that will help much. A "port knock" exists, but that isn't right. A "ping" on a server is an echo from an ICMP packet, so this was pointing at pinging the server and listening to the reply.
Normally though the payload response to a ping is the same as you send. Basically why it "echos" it back. Cicada's server was responding to pings with not one response, but two. This could be called many things from a damaged packet, invalid packet or out-of-band communication so it was clear this was intentional.
In today's age most ISPs are probably filtering these or even blocking them, so this part of the challenge was probably difficult for some.
It took some pings in order to correlate the data message sequences on these extra responses. Combining all those data payloads led to a file that looked like just a blob of data.
This output was hex, but missing the offsets that
xxd normally uses. We could try using
-p which is a plain text format since this appears to be the pattern going on with this puzzle.
➜ xxd -p -r pinged > pinged.out ➜ file pinged.out pinged.out: gzip compressed data, was "message.txt.asc", last modified: Thu Jan 10 17:07:15 2013, from Unix
Sure enough that worked and we now had a compressed data file. So it was time to undo the compression.
➜ gunzip pinged.out gzip: pinged.out: unknown suffix -- ignored ➜ mv pinged.out pinged.out.gz ➜ gunzip pinged.out.gz ➜ file pinged.out pinged.out: ASCII text
gunzip can't take files without extensions. I thought it read magic bytes, but must rely on the file extension. A quick rename to include the listed
gz compression and we can easily undo it.
We had another message.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Well done. You have come far. pklmx2eeh6fjt7zf.onion Good luck. 3301 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAEBAgAGBQJQ7vVDAAoJEBgfAeV6NQkP9x4P/31A5LPzIhkii8sBjuVxIcOn 4KFQO+uVVsR53zImSqlhq6iVAE9+Ko7vIqjD2whTIUFVYZNBq/92wEZJuCSonovH HqYZTQihIS9d+QDuwUNvXr4ilrRmITKMrWw3D23rpWs6ZlnehuUDVI8unbN9Zi3h 3hvok3/+/FofLia9Kvbo+FIDi7T9NNRpqepgXd/6dQIP4kn63kKCP20QMdRf2fXF ZLx5ADS14OvaNFNUAHTJ1qdkPYcdTiNDJkxqk1s82y2doGoEP0ChBUJxlyMiUVXn 1iLOwm2KNrf6If64KxEoetOraWqg9P6l3BjGVPCkrotB608SSs2Lihsa4B0ifI33 ABlpvSDIgpBu/zIO/WFYOfnnrtdvDpVP/Wy+pgqZJ/wOUuhJZhzi5vppjVCm/q9H C/aXQxa+XXe7his4f9tuIBD1wIYAtnE8M0uDCsfiZjBaZNMnOO7/hOwnNQSBAMcr KqL5yHSnpI50CtoA+6ycWZURBkrt1rt4eNxsCqQ1XWed/hWbqb6SlJJemJOPbbmt V5D7iDUO+r2OIUEZTfCSjdzrXcJ8FLtqCGVaLJhCdsyirRHmURwkYLw/B8TpcJQz qbY6oeDxDosIbE6uhDNV2RVKmpWqLDMhLGHVjkDjJpodE5L3ObbylWuRnHfFqfKH 1mubvMAGo03rxxlY+9XG =6Sgs -----END PGP SIGNATURE-----
This onion was familiar (when it opened) and included a list of lat/lng locations. They corresponded to:
- Dallas, Texas - USA
- Okinawa - Japan
- Moscow - Russia
- Little Rock, Arkansas - USA
- Annapolis, Maryland - USA*
- Portland, Oregon - USA
- Columbus, Georgia - USA
* = never recovered - bruteforced
Running into the world and the poster(s) were recovered one by one.
The posters had a phone number and an access code. Presumably to stop random bystanders from calling and accessing. The automated voice on the other end did not respond to the access code LM (56 on the keypad)
So finally the weird rune table had a purpose. Plugging in L (73) and M (71) resulted in 7371 as the code and entry was allowed. The automated voice dumped out some verbal data which for Little Rock was:
Dataset:13 Offset:13831 Data:5edb5e8029dd2182560da925ec6cd3e1257efc0b8328b4
This was (hopefully you see the pattern now) another data blob to be XORed with another data file. The line saying "Dataset: 13" must be referring to the file from the ISO -
560.13. While offset
13821 resulting in the location to reference in the file.
Assuming we are grabbing the same length of the string. We should count the characters of the above data blob from the phone call. Open it up and vim says 46 characters. Knowing that the
-l parameter for
xxd works on octets we can assume the default of 2. So we should do 23 octets of data at offset 13831 (
➜ xxd -p -seek 0x3607 -l 23 560.13 6ab768f540ad4ff1226fce429b06aa970b119262ec46be
Now a quick utility to XOR hex data, but output in plain ASCII. We can leverage GNU tools in PHP to do this with a quick and dirty script.
<?php $xor1 = gmp_init("5edb5e8029dd2182560da925ec6cd3e1257efc0b8328b4", 16); $xor2 = gmp_init("6ab768f540ad4ff1226fce429b06aa970b119262ec46be", 16); $xor = gmp_xor($xor1, $xor2); echo pack("H*", gmp_strval($xor, 16));
We basically create both values in base16 (hex) and run a XOR between them. With that value we cast back to base16 (hex) and run that through pack to dump out the string representation.
➜ php xor.php 4l6uipnstbggwjyv.onion
All that work and off to another onion we went. The page dumped out another blob of data that most should recognize as the formatting for SSSS.
SSSS is Shamir's Secret Sharing Scheme which is a clever way of distributing a secret value with a group of people. They each get a chunk of the secret and only x chunks are needed to remake it. This has a great benefit that no single party can access the secret without the help of others.
It became apparent quickly that this was a 10 split secret so 5 chunks would be needed to decode into the next clue. So we can install
ssss and gain access to the
ssss-combine tool. We can pluck the values from all the other cities unique onion codes to collect at least 5.
➜ ssss-combine -t 5 Enter 5 shares separated by newlines: Share [1/5]: 05-fcd82965b6632ea25d80edc3e58baafb4b2938895cbd Share [2/5]: 07-f3adb3aacb0b4336fa28178bc1e5edce940c16ce5caa Share [3/5]: 09-82a98a7fe06014f783b752506cf6cd1fabaa3d8b3750 Share [4/5]: 03-7678a5f6b72042d839151b34b02ffe161cf997fed484 Share [5/5]: 02-41cc481a51fe77f91600f593c1db2ce9babd2626ea6e Resulting secret: p7amjopgric7dfdi.onion
Just like that we decoded to once again another onion. This appeared to be the end with a strange time based quiz. You had 5 minutes to complete nearly 20 questions and a snippet of those are below.
For those that answered the test in a way that Cicada liked and provided an email. This is where the verified journey ends. It was rumored that the tests continued in private asking participants to design a low level TCP server that Cicada would test on February 3, 2013.
With that, puzzle 2 is over. Check back for Puzzle 3.