Decrypting an Encoded Message

Decrypting an Encoded Message

Challenge Overview:

This challenge on HackThisSite is about decoding a message that is "encrypted" using a custom encryption algorithm. The requestor for the challenge asks.

Decrypt a heavily encoded message from a CEO trying to bribe ecological inspectors investigating water pollution issues. Help environmentalists uncover corporations plotting to profit from the destruction of mother nature!

Challenge Details:

Section: Realistic Challenge 6

The following resources were provided:

  1. A string of numbers seperated by periods. It's belived to be encrypted usign the fake EXCryption algorithm. A sample of the encrypted blob is shown below.

The breakdown:

The challenge identifies the algorithm used to “encrypt” the text as XEncryption. They provide you a form that can be used to encrypt text. I ran several specifically chosen combinations through this form. One thing you may notice is that the same input and password produce different outputs every time.

Reading below this line may spoil the challenge. Read below at your own risk.

The first thing that I noticed is that the 3 numbers it produces for each character of plain text are separated by periods and these three groups looked like they may sum up to the same value for any given input. To test this I ran several iterations of different inputs and noticed that sure enough given the same inputs the output always summed to the same value. I then tried just ‘a’ as an input then ‘b’ as an input and then ‘c’ as an input. If given with the same password the sum of the output was incremented by one each time.

My solution:

Warning: Spoiler alert! A solution is given below
My first attempted solution was to then split the input and sum each group of 3. Then build a table with the frequency each value showed up and the min and max values. I was going to look at the frequency each value appeared and compare to know distributions in the English language but decided to try something even easier first which was to assume the lowest value that would be used if this was ASCII would be the new line character which has a decimal value of 10. So I took the minimum value I found and subtracted 10 from it and assumed this was the password sum. I then went back through the blocks and subtracted this value from them and printed the ASCII value of each. This decoded to the correct value for this challenge.

The Source Code:

Notes about this challenge.
    Encryption/Encoding is done using an algorithm called 
    XECryption which after some inspection appears to simply
    combine the ascii values of the plaintext character with 
    the sum of the ascii values of the password characters.
    Because of this the encrypted content should have a common 
    component that contains the sum of the password characters 
    plus the ascii value of the character encoded. If we make 
    the assumption that the plaintext is an email message than 
    we can assume to find A-Z, a-z, 0-9, punctuation and spaces. 
    ASCII values 32-126 possible.
    Possible approach #1
        Sum up each of the 3 value blocks. Analyze the frequency. 
        look for the two most common ones and assume the most common 
        is e and the next is a. Subtract the ascii values for a and e 
        from their blocks and assume that is the password component, 
        subtract that from the remaining blocks and see if we have a 
        plaintext message.
encrypted_content = ( "."
          "." ) 
if __name__ == "__main__":
    min = 1000
    max = 0
    blocks = []
    distribution = {}
    # Break the encrypted text into chunks
    chunks = encrypted_content.split('.')
    # Remove empty entries
    chunks = list(filter(None, chunks))
    # Combine chunks into blocks by summing every 3 and build a distribution table
    for i in range(0, len(chunks), 3):
        val = int(chunks[i]) + int(chunks[i+1]) + int(chunks[i+2])
        if (val < min):
            min = val
        if (val > max):
            max = val
        if val in distribution:
            distribution[val] += 1
            distribution[val] = 1
    # LF & CR should be two lowest numbered values. Subtract 10 (value of LF) from the smallest value. 
    #This should be the sum of the password characters.
    password_sum = min - 10
    plain_text = []
    for c in blocks:
        plain_text.append(chr(c - password_sum))

The challenge that I wrote about here can be found on
Note: You must join the site to see the challenges.

*Note: This post was migrated from my old blog and has an original post date of December 22, 2016.