Instantly share code, notes, and snippets.

@hellman /1_solve.py
Last active Nov 20, 2017

Embed
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("35.198.105.111 32773")
ct = f.read_line().strip().decode("hex")
ct = xor(ct, delta)
f.send_line(ct.encode("hex"))
f.interact()
# 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))
print(repr(s))
assert not crc(s)
aes = AES.new(enc_key, AES.MODE_CTR, counter = Counter.new(128))
return aes.encrypt(s)
def authdec(c):
aes = AES.new(enc_key, AES.MODE_CTR, counter = Counter.new(128))
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())
print(binascii.hexlify(cipher).decode())
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