rgbCTF-2020

CTF Writeup - https://ctf.rgbsec.xyz/

Home Other writeups of rgbCTF-2020
14 July 2020

N-AES

by raghul-rajasekar

What if I encrypt something with AES multiple times? nc challenge.rgbsec.xyz 34567

Files:

Solution

The important functions to focus on are:

def rand_block(key_seed=urandom(1)):
    seed(key_seed)
    return bytes([randint(0, 255) for _ in range(BLOCK_SIZE)])

def gen_chall(text):
    text = pad(text, BLOCK_SIZE)
    for i in range(128):
        text = AES.new(rand_block(), AES.MODE_ECB).encrypt(text)

    return b64encode(text)

In gen_chall (which encrypts the flag), the key for each iteration is generated using rand_block with the default argument. This default argument is the value returned by urandom(1), which is a single random byte. Thus, the key used for each iteration is the same, with the seed being set being one of 256 possible byte values. Thus, it suffices to just use brute-force by trying out all 256 possible seeds and decrypting the ciphertext 128 times:

from pwn import remote
from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from os import urandom
from random import seed, randint

BLOCK_SIZE = 16

def rand_block(key_seed=urandom(1)): 
    seed(key_seed) 
    return bytes([randint(0, 255) for _ in range(BLOCK_SIZE)])

def decrypt(ciphertext, byte):
    plaintext = b64decode(ciphertext) 
    for i in range(128): 
        plaintext = AES.new(rand_block(byte), AES.MODE_ECB).decrypt(plaintext) 
        return b64encode(unpad(plaintext, BLOCK_SIZE))

p = remote('challenge.rgbsec.xyz', 34567) 
c = p.read() 
c = c.split()[0] 
print(c) 
for i in range(256): 
    print(i) 
    try: 
        decoded = decrypt(c, bytes([i])) 
        print(decoded) 
        if b64decode(b64decode(decoded)):	# Check if the proposed value of challenge is actually a Base64 encoding
            ans = decoded 
    except Exception: 
        continue 
p.write(b'3\n' + ans + b'\n') 
print(p.read()) 

Note: The decrypt function in the above snippet is slightly different from the one in n_aes.py. Since rand_block uses bytes as the default seed, we can’t use the original decrypt function as it iterates over the bytes object, thus using integers for the seed, which is not what we want.

Flag

rgbCTF{i_d0nt_7hink_7his_d03s_wh47_y0u_7hink_i7_d03s}
tags: