#!/usr/bin/env python3 import os, sys, binascii, random from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Util.number import bytes_to_long, long_to_bytes random.seed(os.urandom(16)) k0 = os.urandom(16) k1 = os.urandom(16) s0 = os.urandom(16); S1 = os.urandom(16) m0 = os.urandom(16); M1 = os.urandom(16) with open("/flag.txt","rb") as f: flag = f.read() def hex_input(q): s = input(q).strip() try: return binascii.unhexlify(s) except: print("err"); return None def xex(b16): x = AES.new(k1, AES.MODE_ECB).encrypt(b16) return bytes(a ^ b for a,b in zip(x, b16)) def enc1(iv, msg): return AES.new(k0, AES.MODE_CBC, iv=iv).encrypt(pad(msg,16)) def dec1(iv, c): return unpad(AES.new(k0, AES.MODE_CBC, iv=iv).decrypt(c), 16) def enc2(msg): return AES.new(k1, AES.MODE_CBC, iv=b"\x00"*16).encrypt(pad(msg,16))[-16:] def F(iv, ct): n = len(ct) if n < 96 or (n & 15): return None W = [ct[i:i+16] for i in range(0, n, 16)] m = len(W) digest = enc2(iv) r = ((iv[0]^iv[-1]) & 7) + 2 r %= m if r: W = W[r:] + W[:r] if len(W) < 3: return None A0 = long_to_bytes(bytes_to_long(W[0]) ^ bytes_to_long(m0)) A1 = long_to_bytes(bytes_to_long(W[1]) ^ bytes_to_long(M1)) j = 1 + (digest[0] & 1) del W[j] if len(W) < 2: return None return b"".join((s0, A0, S1, A1, *W[2:])) def O(iv, ct): z = F(iv, ct) if z is None: ok = False else: try: dec1(iv, z) ok = True except: ok = False if random.random() < 0.10: ok = not ok return ok iv = os.urandom(16) MK = enc2(iv + iv) h0 = (flag + b"\x00"*16)[:16] h1 = bytes(a ^ b for a,b in zip(h0, MK)) pt = h1 + flag[16:] ct = enc1(iv, pt) print("iv:", iv.hex()) print("ct:", ct.hex()) print() while True: try: inp = hex_input("inp: ") if inp is None: print("hmmm\n"); continue L = len(inp) if L == 16: y = xex(inp) print("blk:", y.hex()); print() elif L >= 32 and (L % 16) == 0: ivq, ctq = inp[:16], inp[16:] print("ok\n" if O(ivq, ctq) else "zzz\n") else: print("hmmm\n") except EOFError: break