Cryptography
- Super Secure Encryption - 100
Super Secure Encryption
The challenge provides an encoded message and the script that was used to generate it. The script is as follows, with some lines of note highlighted:
from Crypto.Cipher import AES
from Crypto.Util import Counter
import os
k = os.urandom(16) # Is it too short?
def encrypt(plaintext):
cipher = AES.new(k, AES.MODE_CTR, counter=Counter.new(128)) # I was told, CTR can't be broken!
ciphertext = cipher.encrypt(plaintext)
return ciphertext.hex()
msg = b'This is just a test message and can totally be ignored.' # Just checking functionality
encrypted_msg = encrypt(msg)
with open('flag.txt', 'r') as f:
flag = f.readline().strip().encode()
encrypted_flag = encrypt(flag)
with open('msg.txt', 'w+') as o:
o.write(f"{encrypted_msg}\n")
o.write(f"{encrypted_flag}")The script uses AES-128-CTR to encrypt a static string and the flag, using the same key to encrypt both. It then writes them each to the output file, separated by a newline.
AES-CTR in this configuration is vulnerable, as we have the following operations:
Per the properties of XOR, and the knowledge that is the same for each operation performed in a single execution of the challenge script, the following is true:
Additionally,
Combining the two resultant equations:
Remember, is the desired value, and the challenge provides all of , , and .
Performing this chained XOR of the three known values, to determine the flag, can be accomplished in, e.g., CyberChef, or with a basic Python script (using pwntools):
from pwn import xor
ENC_MSG = "d71f4a...38c2a3"
ENC_FLAG = "c23466...6859a3"
MSG = b"This is just a test message and can totally be ignored."
enc_xor = xor(bytes.fromhex(ENC_MSG), bytes.fromhex(ENC_FLAG))
flag = xor(enc_xor, MSG)
print(flag)$ py crack-sse.py
b'ACECTF{redacted}(\xf5j \xee7_\\~\x8a\x9d\x13\xa8X\x88\x18'