Skip to content

Instantly share code, notes, and snippets.

Last active November 20, 2017 13:47
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
HXP CTF 2017 - ouchenticated (Crypto 200)
CRC is applied before CTR so CTR is not protected and we can bitflip.
We can fix MAC randomly and save the difference between admin=0 and admin=1.
Since CRC is linear, the same difference will work for any other MAC.
from sock import Sock
def xor(a, b): return "".join([chr(ord(a[i]) ^ ord(b[i % len(b)])) for i in xrange(len(a))])
mac_key = os.urandom(0x10)
c1 = authenc(json.dumps({'admin': 0}))
c2 = authenc(json.dumps({'admin': 1}))
delta = xor(c1, c2)
f = Sock(" 32773")
ct = f.read_line().strip().decode("hex")
ct = xor(ct, delta)
# hxp{CRC:_c0mpL3t3ly_r3duNd4nT_crYpT0gr4pH1c4LLy}
#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util import Counter
import os, binascii, struct, zlib, json
enc_key = os.urandom(0x10)
mac_key = os.urandom(0x10)
def crc(bs):
return 0xffffffff ^ zlib.crc32(bs)
def authenc(m):
s = m + mac_key
s = s + struct.pack('<L', crc(s))
assert not crc(s)
aes =, AES.MODE_CTR, counter =
return aes.encrypt(s)
def authdec(c):
aes =, AES.MODE_CTR, counter =
s = aes.decrypt(c)
assert not crc(s)
assert s[-4-16:-4] == mac_key
return s[:-4-16]
cipher = authenc(json.dumps({'admin': 0}).encode())
cipher = binascii.unhexlify(input().strip())
obj = json.loads(authdec(cipher).decode())
if obj['admin']:
print('The flag is: {}'.format(open('flag.txt').read().strip()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment