Write up for UTCTF 2024 - Crypto/numbers go brrr
Challenge
I wrote an amazing encryption service. It is definitely flawless, so I’ll encrypt the flag and give it to you.
#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import time
seed = int(time.time() * 1000) % (10 ** 6)
def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed
def encrypt(message):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(message, AES.block_size))
return ciphertext.hex()
print("Thanks for using our encryption service! To get the encrypted flag, type 1. To encrypt a message, type 2.")
while True:
print("What would you like to do (1 - get encrypted flag, 2 - encrypt a message)?")
user_input = int(input())
if(user_input == 1):
break
print("What is your message?")
message = input()
print("Here is your encrypted message:", encrypt(message.encode()))
flag = open('./src/flag.txt', 'r').read()
print("Here is the encrypted flag:", encrypt(flag.encode()))
Explain
The server generates an AES key with time.time()
, so I can find it. After that, I can decrypt the encrypted flag using the key.
Solve
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import time
from pwn import *
t = time.time()
seed = int(t * 1000) % (10 ** 6)
def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed
def encrypt(message):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(message, AES.block_size))
return ciphertext.hex()
def decrypt(ciphertext_hex):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = bytes.fromhex(ciphertext_hex)
decrypted = cipher.decrypt(ciphertext)
unpadded = unpad(decrypted, AES.block_size)
return unpadded.decode('utf-8')
r = remote("betta.utctf.live", 7356)
r.recvuntil(b"What would you like to do (1 - get encrypted flag, 2 - encrypt a message)?")
r.sendline(b"2")
r.recvuntil(b"What is your message?")
msg = b"Hello world"
r.sendline(msg)
r.recvuntil(b"Here is your encrypted message: ")
enc_msg = str(r.recv()[:32], "utf-8")
exp_enc_msg = encrypt(msg)
i = 0
while exp_enc_msg != enc_msg:
seed = int(t * 1000) % (10 ** 6) + i
i = i + 1
exp_enc_msg = encrypt(msg)
r.sendline(b"1")
r.recvuntil(b"Here is the encrypted flag: ")
enc_flag = str(r.recv()[:-1], "utf-8")
print(decrypt(enc_flag))
❯ python3 utctf_numbers-go-brrr.py
[+] Opening connection to betta.utctf.live on port 7356: Done
utflag{deep_seated_and_recurring_self-doubts}
[*] Closed connection to betta.utctf.live port 7356