この大会は2023/2/18 23:00(JST)~2023/2/20 11:00(JST)に開催されました。
今回もチームで参戦。結果は132点で150チーム中116位でした。
自分で解けた問題をWriteupとして書いておきます。
Blocky - 0 (Crypto)
サーバの処理概要は以下の通り。
・key = get_random_block() ・key: ランダム243未満のコードで構成される9バイト文字列 ・cipher = BlockCipher(key, 20) ・sks: keyの各値bについてGF(b)の配列 ・以下180回繰り返し ・sksにsks[-1] + SBOX[sks[-9]]を追加 ・cipher.subkeys = [sks[i:i+9] for i in range(0, (rnd + 1) * 9, 9)] ・cipher.rnd = 20 ・以下繰り返し ・inp: 入力 ・inpが'E'の場合 ・inp: 16進数表記で入力(180バイト未満、各バイトのコードは243未満) ・inp: inpをhexデコード ・inpが'gimmeflag'の場合、NG ・pt = pad(inp) ・mac = get_mac(pt) ・mac: ptのsha256ダイジェストの先頭9バイト ・macの各値を243で割った余りをbyte文字列にして返却 ・ptの長さが9バイトの倍数になるようパディングし、macを連結して返却 ・iv: ランダム243未満のコードで構成される9バイト文字列 ・enc = iv ・ptの各ブロックごと(pt[i:i+9])に以下を実行 ・t = add(pt[i:i+9], iv) ・iv = cipher.encrypt(t) ・encにivを連結 ・encを16進数表記で表示 ・inpが'D'の場合 ・inp: 16進数表記で入力(216バイト未満、各バイトのコードは243未満) ・inp: inpをhexデコード ・iv: inpの先頭9バイト ・ct: inpの先頭9バイト目以降 ・dec = b'' ・ctの各ブロック(ct[i:i+9])に以下を実行 ・t = cipher.decrypt(ct[i:i+9]) ・decにsub(t, iv)を連結 ・iv = ct[i:i+9] ・pt = unpad(dec) ・ptがb'gimmeflag'の場合、フラグを表示 ・ptがb'gimmeflag'でない場合、ptを16進数表記で表示
上記のように処理を書き出してみたが、よく見るとコードにミスがある。暗号化する際のチェックで、以下のように書いてある。
if inp == 'gimmeflag':
inpの型はbytesであるため、入力する際にhexデコードしてb'gimmeflag'になるものを指定すれば、b'gimmeflag'の暗号化文字列が入手できる。
>>> b'gimmeflag'.hex() '67696d6d65666c6167'
$ nc blocky-0.chal.perfect.blue 1337 > E Input (in hex): 67696d6d65666c6167 Result: 5c3cdbb10802059490cfdc1d9782ec9829cace5b937e72124f32067eee889d79d542de5a > D Input (in hex): 5c3cdbb10802059490cfdc1d9782ec9829cace5b937e72124f32067eee889d79d542de5a pbctf{actually_I_made_the_same_mistake_in_CODEGATE_Finals}
pbctf{actually_I_made_the_same_mistake_in_CODEGATE_Finals}