Here’s our solution script.
#!/usr/local/bin/python
from random import choice
import encrypt
import decrypt
from pwn import *
r = remote('anaken21sec2.chal.cyberjousting.com', 1347)
flag_ct = r.recvline().decode().rstrip()
# r.interactive()
# exit(0)
# key = encrypt.getRandomKey()
# print(f'{key = }')
#
# flag = open("flag.txt").read().strip().split("byuctf{")[1].split("}")[0]
# flag = [letter.lower() for letter in flag if letter.isalpha()]
# print(''.join(flag))
# flag_ct = encrypt.encrypt(flag, key)
#
# print(decrypt.decrypt(flag_ct, key))
# exit(0)
QUERY_COUNT = 0
def query(plaintext) -> str:
# global QUERY_COUNT
# QUERY_COUNT += 1
# if QUERY_COUNT > 20:
# return ''
# plaintext = [letter.lower() for letter in plaintext if letter.isalpha()]
# return encrypt.encrypt(plaintext, key)
r.sendlineafter(b"What to encrypt:\n", plaintext)
return r.recvline().decode().strip()
def random_letters(n):
letters = 'abcdefghijklmnopqrstuvwxyz'
result = ''
for _ in range(n):
result += choice(letters)
return result
pt1 = ''.join([random_letters(12) * 11 for _ in range(4)])
ct1 = query(pt1)
print(f'{ct1=}')
blocks = [[ct1[j:j+12] for j in range(i, i+12*4, 12) ] for i in range(0, 11*12*4, 12*4)]
for block in blocks:
print(*block)
permutation = []
for y in range(11):
for x in range(4):
base = {blocks[i][x][0] for i in range(11)}
if blocks[y][x][1] not in base:
permutation.append(y)
break
else:
continue
break
for i in range(10):
for y in range(11):
for x in range(4):
target = blocks[permutation[-1]][x][0]
got = blocks[y][x][1]
if target != got:
break
else:
permutation.append(y)
break
print(f'{permutation=}')
pt2 = random_letters(12)
ct2 = query(pt2)
from itertools import combinations
from tqdm import tqdm
for ls in tqdm(combinations('abcdefghijklmnopqrstuvwxy', 11), total=4457400):
key = ''.join([ls[p] for p in permutation])
if encrypt.encrypt(pt2, key) == ct2:
print("YES")
print(key)
break
print(decrypt.decrypt(flag_ct, key))