ThugCrowd Spock Chat Challenge

Thugcrowd Matrix Spock Challenge, Mirror:

Yet again, we have another classic ThugCrowd chat challenge, this time, featuring a picture of Spock from Star Trek. This challenge was set to expire in 14 days from the publishing date, but unfortunately the steps to solve it were leaked early which is why I’m publishing this writeup early as well. To begin, the tweet contains the following message:

--- BEGIN ThugCrowd Chat Challenge No. 4 ---

This message will self destruct in 14 days

YmVnaW4gNjY0IHVybApNOicxVDwnLForUl1UPEYlTjxWOUU8QllTOiJdLDFXLFc4Ml1TPSYlUjlGUUU5NzE/PSY1Ujs2RU44NlAqCmAKZW5kCg==

This string appears to have a main characteristic of a base64 encoded string (the padding on the end), so we can throw this into a base64 decode utility, or just use bash. Either way, we can decode it into this:

begin 664 url
M:'1T<',Z+R]T<F%N<V9E<BYS:"],1W,W82]S=&%R9FQE971?=&5R;6EN86P*
`
end

I was unfamiliar with this syntax, so I searched for begin 664 url, which turned out to be a Uuencoded package. To turn this file into something worthwhile, we can use uudecode in Linux to decode and unpack. Decoding provides us with a text file, and getting the contents:

user@box:~/tc_spock_chat$ cat url 
https://transfer.sh/LGs7a/starfleet_terminal

Downloading the file and performing some basic identification analysis:

user@box:~/tc_spock_chat$ file starfleet_terminal 
starfleet_terminal: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), for GNU/Linux 3.2.0, BuildID[sha1]=17f312b0279669021ac1fd51f1aa39c42a773bad, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, no section header


user@box:~/tc_spock_chat$ binwalk starfleet_terminal 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
544           0x220           LZMA compressed data, properties: 0x5C, dictionary size: 0 bytes, uncompressed size: 1543503872 bytes
552           0x228           LZMA compressed data, properties: 0x5C, dictionary size: 0 bytes, uncompressed size: 67108864 bytes
13476         0x34A4          LZMA compressed data, properties: 0x5C, dictionary size: -1056964608 bytes, uncompressed size: 436207580 bytes
13568         0x3500          LZMA compressed data, properties: 0xB8, dictionary size: -1023410176 bytes, uncompressed size: 1442840540 bytes
16160         0x3F20          LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 150994944 bytes

Based on this initial inspection, it’s safe to say that this is an executable file, and since I’m running this challenge in a decently secured sandbox, I don’t have any qualms about executing the binary in bash, but you could also run it in gdb if you wanted to step through it. I didn’t feel like this was necessary, so I chmod +x starfleet_terminal and executed it. One of the interesting things about this binary, is that it floods the screen with newlines, and accepts all input, but doesn’t respond in any way until you try to kill the program with CTRL-C. I ended up with something like this:

user@box:~/tc_spock_chat$ ./starfleet_terminal 
ENTERPRISE TERMINAL:

<snip whitespace>

^C

ESTABLISHING SIGNAL...


ESTABLISHING SIGNAL...


ESTABLISHING SIGNAL...


ESTABLISHING SIGNAL...


ESTABLISHING SIGNAL...
CONNECTION ESTABLISHED
...
 ... INCOMING EMERGENCY BROADCAST
 ...
 ...
 ... ACCEPTING BROADCAST MESSAGE
 ... 




                                        .                                        
                                       .:.                                       
                                      .:::.                                      
                                     .:::::.                                     
                                 ***.:::::::.***                                 
                            *******.:::::::::.*******                            
                          ********.:::::::::::.********                          
                         ********.:::::::::::::.********                         
                         *******.::::::'***`::::.*******                         
                         ******.::::'*********`::.******                         
                          ****.:::'*************`:.****                          
                            *.::'*****************`.*                            
                            .:'  ***************    .                            
                           .                                                     


   ##############################################################################
   ##############################################################################
   ##########################        BROADCAST       ############################
   ##############################################################################
   ##############################################################################
   #**********************************ORIGIN************************************#
   #                                                                            #
   #                              STARFLEET SHIP                                #
   #----------------------------------------------------------------------------#
   #                                                                            #
   #                              USS VENGEANCE                                 #
   #                                                                            #
   #****************************************************************************#
   #                                                                            #
   #                               REGISTRY ID                                  #
   #----------------------------------------------------------------------------#
   #                                                                            #
   #                               NCC-177358                                   #
   #                                                                            #
   #*********************************MESSAGE************************************#
   # MAYDAY                                                                     #
   #                                                                            #
   # MAYDAY                                                                     #
   #                                                                            #
   # WE HAVE BEEN BOARDED BY KAHN, HE IS COMMANDEERING THE SHIP.                #
   #                                                                            #
   # HE HAS KILLED ADMIRAL MARCUS                                               #
   #                                                                            #
   # HE IS NOW TRANSPORTING SEVENTY TWO ADVANCED LONG-RANGE TORPEDOES           #
   #                                                                            #
   # WE BELIEVE HE IS AIMING FOR STARFLEET HEADQUATERS                          #
   #                                                                            #
   # THE ENTERPRISE IS HEAVILY DAMAGED                                          #
   #                                                                            #
   #**********************************ERROR*************************************#

   SIGNAL LOST ....
   ...
   ATTEMTPING TO REESTABLISH  ...........
   .......
   ............
   .............
   UNABLE TO ESTABLISH CONNECTION ............. 
   ....
   ARCHIVING MESSAGE.. 
   .........
   .............. 
   ARCHIVED MESSAGE : 

     /Td6WFoAAATm1rRGAgAhARYAAAB0L+WjAQCeH4sICMA2Rl0AA2N0NjQAHcvRCoIwFADQd79GW0E9 
     NsF5lw1MnfO+6RYzu6tAMvz7qPdz6qAZ5JI6JpPelDPkjgahlqFtvBN7r8WYYIwztjoubrzp24RA 
     UABxCJBfnlhxskzREBRFRcpXNHyxj/Kf3WYkG/TLsh/cTb3IYhDZG1M+dUau14ovzpS+ZvKOBvx5 
     On5UtT1FXxDiLoKWAAAAAABY3YwVRBDWWgABtwGfAQAAZUUbHbHEZ/sCAAAAAARZWg== 

ENTERPRISE TERMINAL:

In this awesome looking output, we have an archived message near the bottom, which again appears to be base64 encoded, so we can decode it and see what type of file it is:

user@box:~/tc_spock_chat$ base64 -d <<< /Td6WFoAAATm1rRGAgAhARYAAAB0L+WjAQCeH4sICMA2Rl0AA2N0NjQAHcvRCoIwFADQd79GW0E9NsF5lw1MnfO+6RYzu6tAMvz7qPdz6qAZ5JI6JpPelDPkjgahlqFtvBN7r8WYYIwztjoubrzp24RAUABxCJBfnlhxskzREBRFRcpXNHyxj/Kf3WYkG/TLsh/cTb3IYhDZG1M+dUau14ovzpS+ZvKOBvx5On5UtT1FXxDiLoKWAAAAAABY3YwVRBDWWgABtwGfAQAAZUUbHbHEZ/sCAAAAAARZWg==>archived_message.file

user@box:~/tc_spock_chat$ file archived_message.file
archived_message: XZ compressed data

I wasn’t familiar with .xz compression beforehand, so I kept going with basic analysis:

user@box:~/tc_spock_chat$ binwalk archived_message.file

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             xz compressed data
27            0x1B            gzip compressed data, has original file name: "ct64", from Unix, last modified: 2019-08-04 01:37:04

And the gzip really gave it away (I suppose compressed data wasn’t obvious enough for me). We can use unxz to unpack the binary:

user@box:~/tc_spock_chat$ unxz archived_message.file 
unxz: archived_message.file: Filename has an unknown suffix, skipping

Rename the file to .xz and try again…

user@box:~/tc_spock_chat$ mv archived_message.file archived_message.xz
user@box:~/tc_spock_chat$ unxz archived_message.xz

This expands the gzip file, which we can extract with gunzip:

user@box:~/tc_spock_chat$ gunzip archived_message 
gzip: archived_message: unknown suffix -- ignored

And the filetype again…

user@box:~/tc_spock_chat$ mv archived_message  archived_message.gz
user@box:~/tc_spock_chat$ gunzip archived_message.gz 

And now we’re left with another text file with a string:

user@box:~/tc_spock_chat$ cat archived_message 
TmV3IHJlY3J1aXQsIHdlbGNvbWUgdG8gVGh1Z0ZsZWV0LiBUaW1lIGlmIG9mIHRoZSBlc3NlbmNl
LCByZXBvcnQgdG8gd2hlcmVpc3RoZS5jaGF0IGFuZCBjYXJyeSBvdXQgT3JkZXIgMjAwNS4K

Again, this looks like base64:

user@box:~/tc_spock_chat$ base64 -d archived_message
New recruit, welcome to ThugFleet. Time if of the essence, report to whereisthe.chat and carry out Order 2005.

Unfortunately, due to the challenge being leaked, whereisthe.chat now redirects to the main ThugCrowd website, so I’ll have to omit some graphics regarding the next section. Visiting whereisthe.chat, the user is given a QR code which can be decoded with a number of different utilities. I chose zbarimg, which can decode an input QR code to the plaintext result:

user@box:~/tc_spock_chat$ zbarimg whereisthe.chat.png 
QR-Code:otpauth://totp/StarThug:[email protected]?issuer=OperationSelfDestruct&algorithm=SHA1&digits=6&period=30&secret=GE4TELRRGY4C4MJSFY4TSLRT&port=42069
scanned 1 barcode symbols from 1 images in 0.03 seconds

This result immediately looks like a time-based one-time password, indicated by otpauth, totp, digits, period - you can read more about this on the Google Authenticator Key URI Format GitHub page. The interesting things about this otpauth url are the port on the end, 42069, and the secret, which as seen in the GitHub page, is a base32 encoded key, with no padding required (the padding in this case was an arbitrary number appended to the requester’s IP address):

user@box:~/tc_spock_chat$ base32 -d <<< GE4TELRRGY4C4MJSFY4TSLRT
192.168.12.99.3

There doesn’t seem to be anything fishy with this, so I loaded the QR code into WinAuth to generate my OTP. The more pressing matter however is the port at the end of the otpauth string, and to which host it’s used to connect. We probably don’t have that port open on our own machine (unless the archived message opened it, but it didn’t), so I tried to connect to the QR code issuing website, since that’s the only other server we’ve been given so far:

user@box:~/tc_spock_chat$ nc whereisthe.chat 42069
DESTRUCT SEQUENCE
    ONE      
  CODE:768290
ABORTING
DESTRUCT SEQUENCE
    ONE      
  CODE:768 290 
ABORTING
DESTRUCT SEQUENCE
    ONE      
  CODE:803 923
ABORTING
DESTRUCT SEQUENCE
    ONE      
  CODE:803923
ABORTING

As seen above, I tried entering my OTP code a few different ways, but I couldn’t get the destruct sequence to start. A little bit of searching on Memory Alpha turned up a page about Order 2005. Unfortunately I skipped TOS and went straight into TNG/Voyager… Anyway, let’s give this a shot (still keeping our OTP code in mind):

user@box:~/tc_spock_chat$ nc whereisthe.chat 42069


DESTRUCT SEQUENCE
    ONE      
  CODE:11A
DESTRUCT SEQUENCE
    TWO      
  CODE:11A2B
DESTRUCT SEQUENCE
   THREE    
  CODE:1B2B3


DESTRUCT SEQUENCE
 COMPLETED    
   AND ENGAGED   


  AWAITING     
 FINAL CODE    
  FOR 30-SECOND   
    COUNTDOWN    

  CODE:724137
ENCRYPTED MESSAGE FROM THUGFLEET
               .
              .:.
             .:::.
            .:::::.
        ***.:::::::.***
   *******.:::::::::.*******
 ********.:::::::::::.********
********.:::::::::::::.********
*******.::::::'***`::::.*******
******.::::'*********`::.******
 ****.:::'*************`:.****
   *.::'*****************`.*
   .:'  ***************    .
  .
jrKJt72MnauFjJ3uvJydi4bt5u+7l7S3lpmzqbuMnaW97afthYiOuLuYt7OWl53uurGvrIWMmriN7ee4u5jnuLyys6m7nOqvvYyd772mnbW8som3u5iKuIaI67iGiJG1veyJqruc67iJmLezvbadrr3ts6qWnJG2veyVsZCyt6m7mKevvbKKqoayp6+9tuqxhaadt72yjri7l7OohYyet4aHie++nJ2qvO2vsoW0jbCLtKeQke67rJCKlqiJmo6mkIeds5CKjZC7ma+Ou++JkYqO4uI=

Now this looks like something we would expect, a Thugcrypted message from ThugFleet. Again, this appears to be a base64 encoded string, so let’s do some basic checking:

user@box:~/tc_spock_chat$ base64 -d <<< jrKJt72MnauFjJ3uvJydi4bt5u+7l7S3lpmzqbuMnaW97afthYiOuLuYt7OWl53uurGvrIWMmriN7ee4u5jnuLyys6m7nOqvvYyd772mnbW8som3u5iKuIaI67iGiJG1veyJqruc67iJmLezvbadrr3ts6qWnJG2veyVsZCyt6m7mKevvbKKqoayp6+9tuqxhaadt72yjri7l7OohYyet4aHie++nJ2qvO2vsoW0jbCLtKeQke67rJCKlqiJmo6mkIeds5CKjZC7ma+Ou++JkYqO4uI=
����������������ﻗ�������������텈�����������������縻�縼�����꯽��ヲ������������븆����쉪��븉����������������앱������������������걅������������������ワ����������������������������������������

user@box:~/tc_spock_chat$ base64 -d <<< jrKJt72MnauFjJ3uvJydi4bt5u+7l7S3lpmzqbuMnaW97afthYiOuLuYt7OWl53uurGvrIWMmriN7ee4u5jnuLyys6m7nOqvvYyd772mnbW8som3u5iKuIaI67iGiJG1veyJqruc67iJmLezvbadrr3ts6qWnJG2veyVsZCyt6m7mKevvbKKqoayp6+9tuqxhaadt72yjri7l7OohYyet4aHie++nJ2qvO2vsoW0jbCLtKeQke67rJCKlqiJmo6mkIeds5CKjZC7ma+Ou++JkYqO4uI=> encrypted_message

user@box:~/tc_spock_chat$ file encrypted_message 
encrypted_message: Non-ISO extended-ASCII text, with NEL line terminators

user@box:~/tc_spock_chat$ binwalk encrypted_message 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------

Now is where the real fun begins. There are a few different methods to solve this, but the most important thing we need to do is to identify what type of file we are actually working with. Unbeknownst to me at the time, there exists a pretty cool tool called CyberChef which trivializes this challenge, with the magic operator. If this is the tool you would decide to use, the proper way of going about this would be to use the following recipe:

Input = jrKJt72MnauFjJ3uvJydi4bt5u+7l7S3lpmzqbuMnaW97afthYiOuLuYt7OWl53uurGvrIWMmriN7ee4u5jnuLyys6m7nOqvvYyd772mnbW8som3u5iKuIaI67iGiJG1veyJqruc67iJmLezvbadrr3ts6qWnJG2veyVsZCyt6m7mKevvbKKqoayp6+9tuqxhaadt72yjri7l7OohYyet4aHie++nJ2qvO2vsoW0jbCLtKeQke67rJCKlqiJmo6mkIeds5CKjZC7ma+Ou++JkYqO4uI=

From Base64
"Magic" (scroll through until you find something that looks legitimate, and click on one of the results and finish from there)

This will give you an auth code and connection information to join the ThugCrowd Matrix chat. If you’re interested in another way to solve this, please continue reading.


Speaking with one of my more savvy friends about this, I originally thought this was some type of private key or other type of secret which contained the answer - however, I wasn’t able to get anywhere by formatting it multiple ways and trying to use openssl to decode the message. The decoded base64 output didn’t really give me any major pointers, but one of the things he pointed out to me was that I should take a look at the bytes in the hex dump:

user@box:~/tc_spock_chat$ base64 -d <<< jrKJt72MnauFjJ3uvJydi4bt5u+7l7S3lpmzqbuMnaW97afthYiOuLuYt7OWl53uurGvrIWMmriN7ee4u5jnuLyys6m7nOqvvYyd772mnbW8som3u5iKuIaI67iGiJG1veyJqruc67iJmLezvbadrr3ts6qWnJG2veyVsZCyt6m7mKevvbKKqoayp6+9tuqxhaadt72yjri7l7OohYyet4aHie++nJ2qvO2vsoW0jbCLtKeQke67rJCKlqiJmo6mkIeds5CKjZC7ma+Ou++JkYqO4uI= | xxd
00000000: 8eb2 89b7 bd8c 9dab 858c 9dee bc9c 9d8b  ................
00000010: 86ed e6ef bb97 b4b7 9699 b3a9 bb8c 9da5  ................
00000020: bded a7ed 8588 8eb8 bb98 b7b3 9697 9dee  ................
00000030: bab1 afac 858c 9ab8 8ded e7b8 bb98 e7b8  ................
00000040: bcb2 b3a9 bb9c eaaf bd8c 9def bda6 9db5  ................
00000050: bcb2 89b7 bb98 8ab8 8688 ebb8 8688 91b5  ................
00000060: bdec 89aa bb9c ebb8 8998 b7b3 bdb6 9dae  ................
00000070: bded b3aa 969c 91b6 bdec 95b1 90b2 b7a9  ................
00000080: bb98 a7af bdb2 8aaa 86b2 a7af bdb6 eab1  ................
00000090: 85a6 9db7 bdb2 8eb8 bb97 b3a8 858c 9eb7  ................
000000a0: 8687 89ef be9c 9daa bced afb2 85b4 8db0  ................
000000b0: 8bb4 a790 91ee bbac 908a 96a8 899a 8ea6  ................
000000c0: 9087 9db3 908a 8d90 bb99 af8e bbef 8991  ................
000000d0: 8a8e e2e2                                ....

He made the observation that the bytes were somewhat uniform, and that they were all just right outside of the printable ASCII hexadecimal range (0x20-0x7F):

  2 3 4 5 6 7   
-------------  
0:   0 @ P ` p   
1: ! 1 A Q a q  
2: " 2 B R b r  
3: # 3 C S c s  
4: $ 4 D T d t
5: % 5 E U e u  
6: & 6 F V f v 
7: ' 7 G W g w  
8: ( 8 H X h x 
9: ) 9 I Y i y
A: * : J Z j z
B: + ; K [ k {
C: , < L \ l |
D: - = M ] m }
E: . > N ^ n ~
F: / ? O _ o DEL

I didn’t notice this at the time, and I probably wouldn’t have been able to figure this out without that tip, but I like to believe the ThugCrowd challenges are all about spreading knowledge and helping everyone to improve. I decided this one might be a bit much to finish in Microsoft Excel, so I started looking up some more command-line ways of processing XOR’d strings. I had previously used xortool, but I don’t think it’s the best method to use if you’re looking to understand the solution, so I kept searching, and eventually found a set of crypto challenges on cryptopals which helped me write my own tool to decode this message.

I worked through the first few challenges to get an idea as to how I was going to approach challenge 3, and the code below was what I wrote to decode this message (it expands upon the Cryptopals challenge by adding a base64 decode) - this requires langdetect to do some basic result parsing. It’s not great, but it ended up getting the job done!

The methodology behind the development of this was to initially decode the message as a base64->hex->xor(single byte), but I needed to add a .decode('hex') while developing to get a readable result. Most of the results were garbled text, but a small amount looked like base64, which is where the second set of b64decode comes from.

import base64, binascii, string
from textwrap import wrap
from langdetect import detect
def try_base64 (input):
    try: 
        result = base64.b64decode(input)
    except:
        result = False
        pass 
    if (result):
        return True

# take our input string and convert it to hexadecimal 
input_string = 'jrKJt72MnauFjJ3uvJydi4bt5u+7l7S3lpmzqbuMnaW97afthYiOuLuYt7OWl53uurGvrIWMmriN7ee4u5jnuLyys6m7nOqvvYyd772mnbW8som3u5iKuIaI67iGiJG1veyJqruc67iJmLezvbadrr3ts6qWnJG2veyVsZCyt6m7mKevvbKKqoayp6+9tuqxhaadt72yjri7l7OohYyet4aHie++nJ2qvO2vsoW0jbCLtKeQke67rJCKlqiJmo6mkIeds5CKjZC7ma+Ou++JkYqO4uI='
string_hex = base64.b64decode(input_string).encode('hex')

hex_range = [hex(x) for x in range(256)]

result_list = []
string_split = wrap(string_hex, 2)
for i in hex_range:
    i = i[2:]
    temp_values = []
    for value in string_split:
        # xor and add to list as hex
        # print('xoring {} and {}'.format(int(i, 16), int(value,16)))
        xor_value = int(i, 16) ^ int(value, 16)
        # print('appending {}'.format(hex(xor_value)))
        temp_values.append(hex(xor_value)[2:].zfill(2))

    new_result = (''.join(temp_values[0:len(temp_values)]))
    # print('appending {}'.format(new_result))
    result_list.append(new_result)

valid_results = []
printable = set(string.printable)
for result in result_list:
    # convert to base64 and see if its decodeable
    try: 
        b64string = result.decode('hex').encode('base64')
    except:
        pass

    if(try_base64(b64string)): 
        # try to decode the string and check if it's valid 
        test_string = base64.b64decode(b64string)
        if(try_base64(test_string)):
            test_string = base64.b64decode(test_string)

        # check language
        try:
            test_lang = detect(test_string)
            # should we assume that the answer has a space as well?
            # using langdetect to check for a string which matches 'en', and has a space
            # we also do a simple comparison to throw out all non-printable characters, and check input->output length
            if ((test_lang == 'en') and (' ' in test_string) ):
                # looks ok, try to remove non printable chars and check if its the same 
                printable_chars = filter(lambda x: x in printable, test_string)
                print('processing: {}'.format(test_string))
                if(len(printable_chars) == len(test_string)):
                    # strings match 
                    valid_results.append(test_string)
        except: 
            pass

valid_results

running this file:

user@box:~/tc_spock_chat$ python testfile.py 
processing: 7
/            05$<5$W%$2?T_V.
5$TT<17!
/.$<5#4T^!^

%S5$V$

      0!3?1R?1(
               U0%R0!
$T
/%(U)
     !
      3?
        <$
          7.
<5'?>0V%$T
)(W)3/0#7)>$
)34) 7V0(37[[
processing: B~E{q@QgI@Q"pPQGJ!*#w[x{ZUew@Qiq!k!IDBtwT{Z[Q"v}c`I@VtA!+twT+tp~ewP&cq@Q#qjQyp~E{wTFtJD'tJD]yq EfwP'tET{qzQbq!fZP]zq Y}\~{ewTkcq~FfJ~kcqz&}IjQ{q~Btw[dI@R{JKE#rPQfp!c~IxA|Gxk\]"w`\FZdEVBj\KQ\FA\wUcBw#E]FB..
processing: @|GysBSeKBS rRSEH#(!uYzyXW}guBSks#i#KF@vuVy}XYS tabKBTvC#)vuV)vr|}guR$asBS!shS{r|GyuVDvHF%vHF_{s"GduR%vGVy}sxS`s#}dXR_xs"[^|yguVias|DdH|iasx$KhSys|@vuY}fKBPyHIG!pRSdr#a|KzC~Ezi^_ ub^DXfGT@h^IS}^DC^uWa@u!G_D@,,
processing: A}FxrCRdJCR!sSRDI") tX{xYV|ftCRjr"h"JGAwtWx|YXR!u~`cJCUwB"(wtW(ws}|ftS%`rCR riRzs}FxtWEwIG$wIG^zr#FetS$wFWx|ryRar"|eYS^yr#Z~_}xftWh`r}EeI}h`ry%~JiRxr}AwtX|gJCQxIHF qSRes"`}J{BD{h_^!tc_EYgFUAi_HR|_EB_tV`At F^EA--
processing: Beam me up Scotty! You solved the puzzle! Go to riot.im to create an account. Then join #borg:hotline.blin.gg and type !auth nsjffDhNLN7Wl9B0TD29pe9DNtZPwEMQ

I had some erroneous results in the output, but I was able to get the correct message in the end. I’m currently working through the Cryptopals challenges, and I would highly recommend them - they build on top of each other and are very good for learning (for me at least!). Thank you for reading, and thanks to the ThugCrowd community for making this awesome challenge!