The Humble Bundle Challange 2 was created by IamLupo and published October 6th 2014. You can download it here. The crackme was written in C/C++ and runs on Windows. It has a difficulty rating of “4 – Needs special knowledge”. The description says

Hey boys and girls,

In this challange there is a file “crackme.zip.enc” you have to crack this to win the challange.

There are multiple things you need to find/do. Use the internet and script your own function to decrypt the “crackme.zip.enc”.

One important hint you need to crack this challange is that this challange originally started at 16 September 2014 – 07:20 AM.

Good Luck!

Finding Master Keys</h3>

I`m using Python to decrypt the challenge, you can find the script with all steps on on my GitHub page

From the name of the encrypted file crackme.zip.enc we can guess that the ciphertext is a ZIP file. We know that the first four Bytes of a ZIP file are always 50 4B 03 05 according to the ZIP format specification. Let’s see how the encryption routine turns this known plaintext into ciphertext:

for(unsigned int i = 0; i < 16; i++) {
data[i] ^= generate_key[i];
}

The encryption is a simple synchronous stream cipher with a blocksize of 16 bytes. For instance, for the first four bytes of the ciphertext we have:

The generate_key is modified after each block of 16 bytes by calling GenerateKey. The result is based on a master_key. How do we get this master key? The steps that lead to the generate_key of the first block are:

This function does a lot of shuffling around and it would be tedious to write a routine that reverses the function. Fortunately, the function operates one character at a time: the value generate_key[i] depends only on the initial value of generate_key[i] and master_key[i] - the other elements of generate_key and master_key have no influence on generate_key[i]. Also, the transformation is the same for all elements of generate_key. Let’s rewrite the function as:

To reverse TransformByte we only need to calculate the result for all 256 potential values of the master key character given the initial generate_key then compare the result to the desired generate_key result and see if they match. Of course we can easily reverse multiple iterations of GenerateKey too. The following PotentialMasterKeys generates all master keys for a given plaintext-ciphertext-pair and the nr of iteration (the number of times GenerateKey was called to generate the generate_key used to encrypt the plaintext):

At this point I’m taking an educated guess by assuming the ZIP has been compressed using the same settings used to compress the challenge folder. The challenge zip folder has bytes 0x14 0x00 as the version (meaning Version 2.0). Using the same code as before gives:

Bytes 6-7: General Purpose Bit Flag

The next two bytes of a ZIP file are the general purpose bit flag. Again I’m assuming the ZIP was created with the same tool and setting as Humble_Bundle_Challange_2.zip. If it was, then the general Purpose bit flags are all zero: 0x00 0x00 - most ZIP files don’t have any flags set, so making this assumption isn’t far fetched:

So we know byte 6 of the masterkey for sure, for byte 7 we have two choices.

Bytes 32-39 - File Name (from second character on)

So far we managed to get candidates for the first 8 bytes of the master key. The problem is, we are already at 1280 combinations. Before moving on to the second half of the master key, let’s try to narrow down the number of combinations we got so far. The first 8 bytes of the master key can be used to generate the next generate_key, which in turn can be used to decrypt bytes 16:23. These bytes fall into the CRC-32 field, the compressed size field and the uncompressed size field of the ZIP header. While we could definitely rule out some master keys resulting in implausible sizes, let’s move on the next block at bytes 32:39 where we find an even better header value:

Offset
30 n File name

Since the file name is probably longer than 2 character it should span to the bytes 32+. Let’s decrypt bytes 32 to 37 for all 1280 master key combinations and see which result looks like it is part of a filename. I make the assumption that the filename has an extension, and all characters are ASCII. Therefore we have two valid plaintext types:

The plaintext contains the “.” character and all characters up to “.” plus one extra character (for the extension) are ASCII.

The plaintext does not contain the “.” character. This would mean the extension comes after byte 37 and all decrypted characters are part of the filename and must be ASCII.

The following routine checks those two cases:

def is_part_of_ascii_filename(s):
""" two cases:
- there is a dot in s -> all chars upto to dot plus one (extension)
are ASCII chars
- there is no dot in s -> all chars must be ASCII
"""
if not '.' in s:
dot_index = len(s)
else:
dot_index = s.index('.')
return all(32 <= ord(c) <= 126 for c in s[:dot_index+2])

The next code snippet iterates over all master key combinations, decrypts the ciphertext and then checks if the result is valid according to is_part_of_ascii_filename:

Bytes 12-13: File Last Modification Date

Bytes 12 and 13 represent the file last modification date. The crackme gives the hint One important hint you need to crack this challange is that this challange originally started at 16 September 2014 - 07:20 AM., so we can assume that the ZIP content was created Sept. 16th 2014. The MS-DOS time for this date - in little endian order - is 30 45:

Bytes 28-29: Extra field length (m)

The previous section left us with 4 master key combinations. We can eliminate 3 of those by looking at the next block: Bytes 28 and 29 represent the length of the extra field. Given the four master key combinations from the previous section we get these potential values of the extra field:

The Humble_Bundle_Challange_2.zip doesn’t have an extra field and the length is set to zero. Setting the master key bytes 12 and 13 to 57 07 also results in an extra field length of 0. Although 240 also seems like a valid extra field length, it would be a huge coincidence that one of our four potential master key combos gives a master key length of 0 by chance. This fixes the master key bytes 12 an 13 to:

Still, many combinations remain for bytes 8 and 9. The next section allows us to filter the potential candidates.

Bytes 22-25: Uncompressed Size

The previous section gave many combinations for bytes 8 and 9 of the master key. We can reduce the number a little by looking at the next block, i.e., bytes 24 and 25. These two are the two most significant bytes of the four byte value uncompressed size. Let’s calculate the sizes that result from the master key combinations:

For now I’m not considering compression 98: PPMd version I, Rev 1 and compression 18 IBM TERSE (new) - these seems like a rare choice. If in the end we don’t have a master key that successfully decrypts the ZIP we can still come back and loosen the assumptions. For now, the choices for bytes 8 and 9 of the master key are:

213, 66
87, 66
91, 66
99, 66
170, 66

Or in Hex and using the set notation:

{d5, 57, 5b, 63, aa} 42

Bytes 26-27: File Name Length (n)

So far we have information for all masterkey positions except bytes 10 and 11. Those two master key bytes affect byte 10,11 of the ciphertext, which represents the file last modification time. The crackme says when the challenge started, but we can't assume the ZIP was created at exactly that time. So let's have a look at the next block. Bytes 26 and 27 represent the file name length (n). We already know the filename is probably README.TXT which has a length of 10 Bytes, or in little endian hex 0x0A 0x00. This gives the following combinations for the master key bytes 10 and 11:

Good! The time stamp is valid and before 07:20. We now got information about all master key bytes and can start to brute force the combinations

Testing Potential Master Keys

Summary of What we Know about the Master Key

For the first half of the master key we have the following two combinations:

7f 17 1b 12 54 {08,10} 56 3f

For bytes 8 and 9 we have 5 choices:

{d5, 57, 5b, 63, aa} 42

For bytes 10 and 11 we know:

3a 19

Bytes 12 and 13 are:

57 07

And the last two bytes 14 and 15 are one of the following 16 combinations:

{20,50,56,70} {39,8f,af,f9}

So in total we got 2*5*4*4 = 160 different master keys.

Brute Forcing all 160 Combinations

Which one of the 160 combinations is the correct one? I used a small (and very slow) Python script to decrypt the crackme.zip.enc for all master keys and checked with ziplib if the resulting file was a valid ZIP:

If you read this you cracked the challange! :D
Great job! And have fun with the humble bundle book!
Link: https://www.humblebundle.com/?gift=&lt;censored>
Youtube: https://www.youtube.com/watch?v=dE-sN5MUUKs&#038;hd=1