ThugCrowd XOR Chat Challenge

ThugCrowd XOR Chat Challenge, Mirror:

seven days until discord xors itself \x1b\x11\x02\x15\x1d\x1aKN\r\x1bU\x12\r\x06\x06\x1bDJ\n\x1c\x0e@\x11\x0cA\x14@\x11\x1bA\x1dZ\x1b\x11\x01\n 

This chat challenge was interesting for me, as it was my first attempt XOR cipher CTF. As per Wikipedia, the simple XOR cipher is a type of additive cipher. Using a message and a key, you can generate an message by XORing the two, or one with a repeating key.

Initially when learning about XOR ciphers, the main information I found was regarding repeating keys (the contents of which are truncated at the end of the input message), such as this:

Message: MESSAGE TO ENCRYPT
Key: ENCRYPTIONKEY

Since len(Message) > len(Key), the key is repeated (pipe| denotes the start of the repeat):
M  E  S  S  A  G  E     T  O     E  N  C  R  Y  P  T
4d 45 53 53 41 47 45 20 54 4f 20 45 4e 43 52 59 50 54
45 4e 43 52 59 50 54 49 4f 4e 4b 45 59|45 4e 43 52 59
E  N  C  R  Y  P  T  I  O  N  K  E  Y |E  N  C  R  Y 

To XOR the two strings in Python, we can use: hex(int(message, 16) ^ int(key, 16))
Message: 4d 45 53 53 41 47 45 20 54 4f 20 45 4e 43 52 59 50 54
Key:     45 4e 43 52 59 50 54 49 4f 4e 4b 45 59|45 4e 43 52 59
XOR'd:   08 0b 10 01 18 17 11 69 1b 01 6b 00 17 06 1c 1a 02 0d

In order to solve this challenge, I wanted a way to parse and interpret a lot of data at once, since the key wasn’t immediately clear to me, so I decided to use Microsoft Excel to allow me to get a better overview and to be able to quickly play with keys. I ran through a few iterations of formats (all pretty close to the end result), but the final sheet was formatted as follows:

Secret: row contains a repeating secret which I manually entered to try to intelligently bruteforce the result

String: each individual value in the tweet went here, \x1b, \x11, \x02, etc. manually entered 

Hex: the hex representation of the "String" row, =REPLACE(LEFT(CELL,4), 1, 1, "0"), this converts \x1b->0x1b

Hex stripped: stripped 0x from string, to get the plain hex value, this could have been done in one formula but I decided to do it in two, =RIGHT(CELL, 2) converts 0x1b->1b

HexToDec: self explanatory, converts hexadecimal to decimal, =HEX2DEC() 0x1b->27

SecretToDec: converts the current secret character to decimal format, using =CODE() converts "s"->115

XORtoDec: performs a bitwise XOR of two numbers, =BITXOR(CELL1,CELL2) turns 27 XOR 115 -> 104

Result: uses the excel =CHAR() to turn a decimal value into a character, 104->"h"

Using this as my code breaking tool, I was easily able to test keys repeatedly, filling across the columns and seeing the result instantly. The problem I was left with was “what is the key?”. Attached to the tweet is a picture of the well scene from the Ring, so I started off with a few repeating keys, WELL, RING, and SEVEN DAYS. Well being from the picture, Ring being the name of the movie, and seven being a large part of the plot (seven days to die).

Ring and well didn’t turn up anything worthwhile, but seven gave me something interesting, which was https:. This seemed to indicate that the message was actually a URL, so I tried seven as a repeating secret, but that was a dead end as well. My next try was seven days, which again gave me another hint https://thu (thugcrowd.com?), and coincidentally, this is also the start of the tweet: seven days until discord xors itself. I still had some formatting issues and wrong ideas about the layout of the hex message, which you can see below:

Our message seemed to line up well also:

Message: 1b 11 02 15 1d 1a K N \r 1b U 12 \r 06 06 1b D J \n 1c 0e @ 11 0c A 14 @ 11 1b A 1d Z 1b 11 01 \n 
Key:     s  e  v  e  n     d a y  s    u  n  t  i  l    d i  s  c  o r  d    x  o r  s    i  t s  e  l  f  

Okay, so now we have what is probably the key, so going to the website, https://thugcrowd.com/chal/chat.html, gives us a picture of Haunter, and a good remix of Hotline Bling playing in the background, but this doesn’t seem like the answer. Inspecting the source gives us something else to work with, and selecting all shows it is actually a haunted string.

This looks like more hex, so let’s try to make a binary with Bless or HxD and run file to see what we’re working with:

user@box:~/tc_xor$ file haunter 
haunter: Zip archive data, at least v?[0x314] to extract

And binwalk:

user@box:~/tc_xor$ binwalk haunter 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Zip archive data, at least v2.0 to extract, compressed size: 532, uncompressed size: 3108, name: haunt.txt
662           0x296           End of Zip archive, footer length: 22

It’s safe to assume we’re dealing with a zip, so using the standard Linux archive manager, we see there’s one file:

With the contents of:

4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQ
CuKUguKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCAgICAgIOKW
iOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKUggrilILilojiloji
lojilojilojilojilojilojilojilojilojiloggICDilojilojilojilojilojilogg4paI4paI
4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4pSCCuKUguKWiOKWiOKWiOKWiOKW
iOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCDiloggIOKWiCAgIOKWiCDilojilojilojilojiloji
lojilojilojilojilojilojilojilojilIIK4pSC4paI4paI4paI4paI4paI4paI4paI4paI4paI
4paI4paI4paI4paIICDilojilogg4paI4paI4paIICDilojilojilojilojilojilojilojiloji
lojilojilojilojilojilIIK4pSC4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI
ICDilojilojilojilojilojilojilojiloggIOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKW
iOKWiOKWiOKUggrilILilojilojilojilojilojilojilojilojilojilojilogg4paIIOKWiOKW
kuKWiOKWiOKWiOKWiOKWkuKWiCDilogg4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI
4pSCCuKUguKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCDilojilojilojilogg4paS
4paSIOKWiOKWiOKWiOKWiCDilojilojilojilojilojilojilojilojilojilojilojilIIK4pSC
4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paIIOKWiOKWkuKWiOKWiCDilojilogg4paI
4paI4paS4paIIOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKUggrilILilojiloji
lojilojilojilojilojilojilojilojilojiloggIOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCAg
4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4pSCCuKUguKWiOKWiOKWiOKWiOKW
iOKWiOKWiOKWiOKWiOKWiOKWiCAg4paIIOKWiOKWiOKWkuKWkuKWiOKWiCDiloggIOKWiOKWiOKW
iOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKUggrilILilojilojilojilojilojilojilojiloji
lojilogg4paI4paIIOKWiCAgICAgIOKWiCDilojilogg4paI4paI4paI4paI4paI4paI4paI4paI
4paI4paI4pSCCuKUguKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCDilojilogg4paI4paI
ICAgIOKWiOKWiCDilojilogg4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4pSCCuKUguKW
iOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCAgIOKWiOKWiCDilpLilpIg4paI4paIICAg
4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4pSCCuKUguKWiOKWiOKWiOKWiOKWiOKW
iOKWiOKWiOKWiOKWiOKWiOKWiCDilojilojiloggICAg4paI4paI4paIIOKWiOKWiOKWiOKWiOKW
iOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKUggrilILilojilojilojilojilojilojilojilojiloji
lojilojilojiloggICAgICAgICAg4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI
4paI4pSCCuKUguKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCAgICAg4paI4paI
ICAgICDilojilojilojilojilojilojilojilojilojilojilojilojilIIK4pSCICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSCCuKUgllvdSBjYW4gY2hvb3NlIHdoZXJlIHlv
dSB3YW50IHRvIGdvIeKUggrilIIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDi
lIIK4pSCICAgICBXaWxsIHlvdSBlbnRlciB0aGUgTWF0cml4PyAgICAg4pSCCuKUgiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKUggrilIIgIEkzZGxiR052YldVNmFHOTBiR2x1
WlM1aWJHbHVMbWRuICDilIIK4pSCICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
4pSCCuKUgiAgICAgT3IgY29udGludWUgd2l0aCBEaXNjb3JkPyAgICAgIOKUggrilIIgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIIK4pSCYUhSMGNITTZMeTlrYVhOamIzSmtM
bWRuTHpWU1JGTkVWbUU94pSCCuKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKU
gOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKU
gOKUgOKUgOKUgOKUgOKUgOKUmAo=

Which to me seems like a base64 encoded string. A couple indicators are the repeated CAgI, and the terminating =. Let’s see what it says:

user@box:~/tc_xor$ base64 -d haunt.txt 
┌────────────────────────────────────┐
│███████████████      ███████████████│
│████████████   ██████ ██████████████│
│█████████████ █  █   █ █████████████│
│█████████████  ██ ███  █████████████│
│████████████  ████████  ████████████│
│███████████ █ █▒████▒█ █ ███████████│
│███████████ ████ ▒▒ ████ ███████████│
│███████████ █▒██ ██ ██▒█ ███████████│
│████████████  ████████  ████████████│
│███████████  █ ██▒▒██ █  ███████████│
│██████████ ██ █      █ ██ ██████████│
│██████████ ██ ██    ██ ██ ██████████│
│███████████   ██ ▒▒ ██   ███████████│
│████████████ ███    ███ ████████████│
│█████████████          █████████████│
│████████████     ██     ████████████│
│                                    │
│You can choose where you want to go!│
│                                    │
│     Will you enter the Matrix?     │
│                                    │
│  I3dlbGNvbWU6aG90bGluZS5ibGluLmdn  │
│                                    │
│     Or continue with Discord?      │
│                                    │
│aHR0cHM6Ly9kaXNjb3JkLmdnLzVSRFNEVmE=│
└────────────────────────────────────┘

More base64:

user@box:~/tc_xor$ base64 -d <<< I3dlbGNvbWU6aG90bGluZS5ibGluLmdn
#welcome:hotline.blin.gg
user@box:~/tc_xor$ base64 -d <<< aHR0cHM6Ly9kaXNjb3JkLmdnLzVSRFNEVmE=
https://discord.gg/5RDSDVa