hxp CTF 2017 Writeup

この大会は2017/11/17 21:00(JST)~2017/11/19 21:00(JST)に開催されました。
今回もチームで参戦。結果は959点で963チーム中24位でした。
自分で解けた問題をWriteupとして書いておきます。

helloworld (TRO 1)

$ nc 35.205.206.137 31337
hello?
world
hxp{w3lc0m3_70_7h3_hxpctf2017}
hxp{w3lc0m3_70_7h3_hxpctf2017}

ouchenticated (CRY 100)

概要は以下の通り。

平文:{"admin": 0}[MAC-KEY16バイト][本体28バイトのCRC]
暗号文が16進数で表示される。

{"admin": 1}でCRCも正しく計算して送信する必要がある。CTRモードなので、以下のような暗号イメージ。

[平文1ブロック目] ^ [鍵1] = [暗号1ブロック目]
[平文2ブロック目] ^ [鍵2] = [暗号2ブロック目]

最初の1ブロック目は暗号1ブロック目の11文字目だけ、0でなく1になるようXORを計算するだけ。2ブロック目はCRCが入っていて、論理的には難しいので、いろいろテストしてみた。
その結果、暗号2ブロック目の最後の4バイトはadminの値が0のときと1のときとで、XORの値が固定('e1b652ef')であることがわかった。以上を踏まえてコードにすると、次のようになる。

#!/usr/bin/env python
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('35.198.105.111', 32773))

b16_c = s.recv(1024).strip()
print b16_c
c = b16_c.decode('hex')

c_ans = c[:10]
c_ans += chr(ord(c[10]) ^ ord('0') ^ ord('1'))
c_ans += c[11:28]

# determined by test
key = 'e1b652ef'

b16_crc = '%x' % (int(c[28:].encode('hex'), 16) ^ int(key, 16))
c_ans += b16_crc.decode('hex')

ans = c_ans.encode('hex')
print ans
s.sendall(ans + '\n')
data = s.recv(1024)
print data
hxp{CRC:_c0mpL3t3ly_r3duNd4nT_crYpT0gr4pH1c4LLy}