Root-XMAS 2024 Day 06 - Unwrap The Gift

# summary

an AES challenge where the CTR mode is used and the same key and IV is reused. A simple xor with a known encrypted text gives us the flag.

# recon

Today we have a simple remote interface accessible via nc where Santa gives us an encrypted "wrapped" flag. He also allows us to encrypt another string we want to "wrap"

	nc 163.172.68.42 10006
--------------------------------------------------
  .-""-.
 /,..___\
() {_____}
  (/-@-@-\)
  {`-=^=-'}
  {  `-'  } Oh Oh Oh! Merry Root-Xmas to you!
   {     }
    `---'
--------------------------------------------------
[SANTA]: Hello player, welcome! Here is your gift for this christmas: ae6559387840c188285dd39d13915dafd5ddc4dfc3aced394b81f7d581654bc2b28cdcf6018860b78fac752dee7ea56c95a8f46d937f115bb6f49f189ef48e9c
[SANTA]: Oh, I forgot to tell you, you will only be able to unwrap it on the 25th, come back to me on that date to get the key!
--------------------------------------------------
[SANTA]: While Im at it, do you wish to wrap a present for someone? (Y/N)
	Y
[SANTA]: Enter the message you wish to wrap:
	aaaa
[SANTA]: Here is your wrapped present: 9d49431d440299db7303ebc140c41ef6
[SANTA]: Merry Christmas!

by checking the source code, we see the flag is encrypted in AES, but the key and IV are reused for the session.

class Gift:
    def __init__(self):
        self.key = urandom(16)
        self.iv = urandom(12)
    
    def wrap(self, data):
        cipher = AES.new(self.key, 6, nonce=self.iv)
        data = data.encode()
        return hexlify(cipher.encrypt(pad(data, 16))).decode()

We also see the AES mode used is "6". That's not very clear, I suppose there is an enum with a more descriptive name. Hopefully, with VSCode (or other editors), I can right click on the AES object, "go to definition" and get the AES lib source where i find

MODE_CTR = 6

Then I just typed online "AES ctr CtF challenge" and landed On John Hammonds' AES-CTR Cryptography: Reused Key Weakness - HackTheBox Cyber Apocalypse CtF video.

The gist of it is on AES-CTR , with a reused key and IV, and if we can encrypt our known text, we get the flag if:

  • we XOR the encrypted flag with the encrypted known payload
  • we then XOR the result with the known payload plain-text

    # solution

We could have done it manually, but for the challenge, let's automate the solution with a python script:

from binascii import unhexlify
from pwn import *
import re

def get_encoded(conn, recvuntil :str):
    res = conn.recvuntil(bytes(recvuntil, "utf-8"), drop=True).decode("utf-8")
    return unhexlify(re.findall(r'[a-f0-9]{8,}',res)[0])

conn = remote('163.172.68.42',10006)
payload = "a"*60

flag_crypted = get_encoded(conn, '(Y/N)')
conn.send(bytes(f"Y\n{payload}\n", "utf-8"))
payload_crypted = get_encoded(conn, 'Merry Christmas')

blob = xor(flag_crypted, payload_crypted)
flag = xor(blob, payload)
print(flag)

b'RM{D0NT_WR4P_YOUR_GIFTS_ W1TH_W3AK_CRYPTOGRAPHY:(} \x0f\x0f\x0f\x0f\...\x0fjjjj'

now go do the AES128-CTR challenge on Root-me, it's in the same vibe! (but harder ^^')

Previous day Day 05 - The Friendly SnowmanDay 05 - The Friendly Snowman

Next day Day 07 - Go, Pwn, GownDay 07 - Go, Pwn, Gown