The first challenge in the "Crypto"-category of the GuidePoint CTF August 2021, is called "Twisting seA".
We are asked to decipher the data provided:
617a316a5a6d526a4d44466c4f54526d5a4463794f4445354d5455354f444d77593255344e54646d597a45354d437870505446684f57526c5a6a6b344e57457a4d7a49334e6a59784d6d49314d6a4532596a5a6a5a6a4e6b4d5755344c4449774f5446685a444d325a444d324d574d344f475131597a4d794d444a6c4d7a5a6b4f546331595441314e4455314e5464694e4455775a44566d5a47466d5954466b4e6a49774e7a6c6d4d5749324e6a677a59544a6b4e574e6c595459335a5759774f47557a4d6d4533595445314f4755315932526b4d7a67304f44557a5a413d3d
Okay, the data seems alphanumeric - could it be HEX? We also is asked to "decipher" and being in the crypto-category I would suspect to be required to use some kind of cryptographic algoritm for getting the flag. Even the name of the challenge is suggesting this to us - twisting "seA" in reverse is "Aes". Arh - that is interesting.
But for us to make any sense of the data is regards to AES - we would need a key, an initialization vector and the cipher to decrypt.
I started to see if any sense could be maked out of the data by de-encoding the HEX with binascii.unhexlify()
, and sure thing - we now have a beautiful base64-encoded string, even padded and every thing.
az1jZmRjMDFlOTRmZDcyODE5MTU5ODMwY2U4NTdmYzE5MCxpPTFhOWRlZjk4NWEzMzI3NjYxMmI1MjE2YjZjZjNkMWU4LDIwOTFhZDM2ZDM2MWM4OGQ1YzMyMDJlMzZkOTc1YTA1NDU1NTdiNDUwZDVmZGFmYTFkNjIwNzlmMWI2NjgzYTJkNWNlYTY3ZWYwOGUzMmE3YTE1OGU1Y2RkMzg0ODUzZA==
Using base64.b64decode()
to decode the string and we are left with a comma-separated string with what seems to be the three components for the AES-deciphering.
k=cfdc01e94fd72819159830ce857fc190,i=1a9def985a33276612b5216b6cf3d1e8,2091ad36d361c88d5c3202e36d975a0545557b450d5fdafa1d62079f1b6683a2d5cea67ef08e32a7a158e5cdd384853d
Providing the decoding in python makes our string in binary - just to sanitise the input for the next step, make sure the string is formatted correctly by applying .decode()
. Splitting the string in the three components and cleaning up the "k=" and "i=" to have the raw values stored in variables, ready for the AES-deciphering.
In python I use the Crypto
-library to firstly create an AES-cipher object - here it's important to de-HEX the key and carve the IV for excess padding. The provided IV has a length longer than the required 16 bytes. Using this cipher-object, we can use the .decrypt()
-function to decrypt the ciphertext - make sure to provide the correct encoding, as the text seems to be HEX-formatted. Further we can remove excess padding from the decrypted string by using Crypto.Util.Padding.unpad()
.
And would you look at that - printing the result (and pretified the output to "normal" utf-8 encoding) gives us the flag for this challenge.
Below is the full python-code created for this challenge.
#!/usr/bin/env python3
import base64
from binascii import unhexlify
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
data ="617a316a5a6d526a4d44466c4f54526d5a4463794f4445354d5455354f444d77593255344e54646d597a45354d437870505446684f57526c5a6a6b344e57457a4d7a49334e6a59784d6d49314d6a4532596a5a6a5a6a4e6b4d5755344c4449774f5446685a444d325a444d324d574d344f475131597a4d794d444a6c4d7a5a6b4f546331595441314e4455314e5464694e4455775a44566d5a47466d5954466b4e6a49774e7a6c6d4d5749324e6a677a59544a6b4e574e6c595459335a5759774f47557a4d6d4533595445314f4755315932526b4d7a67304f44557a5a413d3d"
decoded = base64.b64decode(unhexlify(data))
decoded = decoded.decode()
k, i, v = decoded.split(',')
# Cleanup the values
k = k[2:]
i = i[2:]
cipher = AES.new(unhexlify(k), AES.MODE_CBC, i[:AES.block_size])
decrypted = unpad(cipher.decrypt(unhexlify(v)), AES.block_size)
print(decrypted.decode())
And with that, the challenge has been conquered and 200 points is safely in the bag.
FLAG
GPSCTF{208E5f02Dc1EEe20DE59F8dfcA2bd06e}