Description:
There is no description for the challenge. The zip file includes three resources:
challenge.txt – gives us the encryption scheme – AES 256 CBC mode, iv, and ciphertext to decrypt
aes.py – simple example of how to use Crypto.Cipher to encrypt/decrypt in Python
key.png – presumably a representation of the key
What seems to be the challenge is to derive the key from key.png and decipher the ciphertext from challenge.txt
We explored many different ideas as to how the key is derived. Looking up the image in stega tools showed nothing interesting. Pretty quickly we reached the conclusion that there is an upper part and a lower part to each symbol. The top can be one of four characters, the bottom can be one of five characters. Interestingly, the symbols can be sequenced using the number of lines per symbol. A special curved character could signify the zero character (when both parts are empty). The three pixelated symbols are unknown, we probably need to bruteforce them once more information is known.
In total there are 59 symbols. Each one can be one of 20 values, resulting in 20^59 possible combinations (5.764608e+76). This was suspiciously close to half of the representation space of 256bit keys – 1.157921e+77. Since the bottom has 5 possible “digits” and the top has 4, we can look at the symbols as two-digit base5 numbers with the top character being more significant (if we look at it the other way round we get values above 20). Now we can represent the symbol array as 59 base20 digits, which we did here:
DIGITS = [19, 3, 10, 15, 2, -6, 16, 16, 18, 12, 19, 6, 19, 12, 8, -6, 5, 8, 17, 18, 18, 5, 9, 3, 11, 10, 1, 10, 10, 0, 10, -6, 0, 8, 18, 10, 0, 15, 18, 5, 18, 14, 19, 1, 1, 0, 4, 6, 15, 4, 11, 16, 10, 8, 14, 5, 13, 16, 9]
Now we took a leap of faith and assumed the key is zero-extended, meaning the key is prepended with a 0 bit. Therefore we just need to plug in the calculated key as is. The only thing left is to loop over the pixelated symbols and look for a plaintext which includes HackTM.
from Crypto.Cipher import AES
DIGITS = [19, 3, 10, 15, 2, -6, 16, 16, 18, 12, 19, 6, 19, 12, 8, -6, 5, 8, 17, 18, 18, 5, 9, 3, 11, 10, 1, 10, 10, 0, 10, -6, 0, 8, 18, 10, 0, 15, 18, 5, 18, 14, 19, 1, 1, 0, 4, 6, 15, 4, 11, 16, 10, 8, 14, 5, 13, 16, 9]
cipher = '059fd04bca4152a5938262220f822ed6997f9b4d9334db02ea1223c231d4c73bfbac61e7f4bf1c48001dca2fe3a75c975b0284486398c019259f4fee7dda8fec'.decode("hex")
iv = '42042042042042042042042042042042'.decode('hex')
def get_key_from_digits(digits):
key = 0
for i in range(len(digits)):
key += digits[len(digits) - 1 - i] * (20 ** i)
key = hex(key)
key = key[2:-1]
return key
def decrypt(cipher, key):
key = key.decode('hex')
aes = AES.new(key,AES.MODE_CBC, iv)
return aes.decrypt(cipher)
for i in range(20):
for j in range(20):
for k in range(20):
digits = DIGITS
digits[5], digits[15], digits[31] = i,j,k
if 'HackTM' in decrypt(cipher, get_key_from_digits(digits)):
print decrypt(cipher, get_key_from_digits(digits))
After under a second, the output is:
HackTM{can_1_h@ve_y0ur_numb3r_5yst3m_??}000000000000000000000000
留言