この大会は2020/5/30 1:37(JST)~2020/6/1 1:37(JST)に開催されました。
今回もチームで参戦。結果は166点で401チーム中104位でした。
自分で解けた問題をWriteupとして書いておきます。
Transcendence Rebellion (Bonus)
Rulesのページの最下部に小さくこう書いてあった。
For the first time, these tiny letters on the bottom of the screen are not a prank. \o/ if you got to this point, means that you probably read all our informations and instructions. And for that, we will award your team with extra points in the competition, after all, reading is FUNDAMENTAL for a competition like this. Use the flag "CTF-BR{RTFM-1s-4-g00d-3xpr3ss10n-v6.0}" on the challenge "Bonus" during the day of the event and guarantee your extra score! ;)
CTF-BR{RTFM-1s-4-g00d-3xpr3ss10n-v6.0}
Androids Encryption (Crypto)
$ nc encryption.pwn2.win 1337 Let's see if you are good enough in symmetric cryptography! MENU 1 - Encrypt your secret 2 - Encrypt my secret 3 - Exit Choice: 2 VMYeRX0ORnE4fcQCrw3Y6nP2kRIW2EkAeca9N0Tm+gV9Hhrs4D7jjxzgvKgwvshwZpuwE1TmRR4YVBkvfyBH+A== MENU 1 - Encrypt your secret 2 - Encrypt my secret 3 - Exit Choice: 1 Plaintext: YWFhYWFhYWFhYWFhYWFhYQ== TMHCIRYGvZYpDgpY+/DVgCCsqCa9u3c+EdPBIwRDbUc= MENU 1 - Encrypt your secret 2 - Encrypt my secret 3 - Exit Choice: $ nc encryption.pwn2.win 1337 Let's see if you are good enough in symmetric cryptography! MENU 1 - Encrypt your secret 2 - Encrypt my secret 3 - Exit Choice: 1 Plaintext: YQ== ERROR: Invalid plaintext size
サーバの処理概要は以下の通り。
■1 - Encrypt your secret ・入力文字をbase64デコードする。 ・key1, iv1で暗号化→表示 ■2 - Encrypt my secret ・key2, iv2でフラグを暗号化→表示 □暗号化 ・blocks: 16バイトごとのブロックの配列 ・以下のように暗号化する。 pt0 ^ iv --(AES-ECB)--> ct0 pt1 ^ (ct0 ^ pt0) --(AES-ECB)--> ct1 : ・iv + 暗号を返す。 以下次回に使う。 ・iv2をkey2で復号したものをiv2にする。 ・上記で暗号化したものを16バイトごとのブロックの配列にし、全部ブロックのXORをとったものをkey2とする。
このことから以下のことが言える。
1.を実行する。 ・key2は暗号化データをブロックごとにわけたXORになっている。 2.を実行する。 ・暗号化されたフラグが表示される。 ・keyは上記のkey2 ・ivはこの時表示された先頭16バイトのiv
以上のことからフラグを復号する。
import socket import base64 from Crypto.Cipher import AES def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def to_blocks(txt): return [txt[i*BLOCK_SIZE:(i+1)*BLOCK_SIZE] for i in range(len(txt)//BLOCK_SIZE)] def xor(s1, s2): return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2)) def decrypt(txt, key, iv): bs = len(key) blocks = to_blocks(txt) ptxt = '' aes = AES.new(key, AES.MODE_ECB) curr = iv for block in blocks: ptxt += xor(aes.decrypt(block), curr) curr = xor(ptxt[-bs:], block) return ptxt BLOCK_SIZE = 16 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('encryption.pwn2.win', 1337)) data = recvuntil(s, ': ') print data + '1' s.sendall('1\n') try_pt = base64.b64encode('a' * BLOCK_SIZE) data = recvuntil(s, ': ') print data + try_pt s.sendall(try_pt + '\n') data = recvuntil(s, '\n').rstrip() print data key = base64.b64decode(data)[BLOCK_SIZE:] data = recvuntil(s, ': ') print data + '2' s.sendall('2\n') data = recvuntil(s, '\n').rstrip() print data iv = base64.b64decode(data)[:BLOCK_SIZE] ct = base64.b64decode(data)[BLOCK_SIZE:] flag = decrypt(ct, key, iv) print flag
実行結果は以下の通り。
Let's see if you are good enough in symmetric cryptography! MENU 1 - Encrypt your secret 2 - Encrypt my secret 3 - Exit Choice: 1 Plaintext: YWFhYWFhYWFhYWFhYWFhYQ== QpSPVTiHHdlKkLnD6UU1qnoLMwCiCXHn7CNfB/JXOtU= MENU 1 - Encrypt your secret 2 - Encrypt my secret 3 - Exit Choice: 2 5Cn0M3UFBWnaLepOTro39KDnvDs+mLyh8XXkWzjKLWWBP7+fxpUAzFRcnjx41Y3FXPHVCbcbXlMIqcbBTu7cMw== CTF-BR{kn3W_7h4T_7hEr3_4r3_Pc8C_r3pe471ti0ns?!?}
CTF-BR{kn3W_7h4T_7hEr3_4r3_Pc8C_r3pe471ti0ns?!?}