この大会は2017/10/17 19:00(JST)~2017/10/19 19:00(JST)に開催されました。
今回もチームで参戦。結果は1172点で241チーム中63位でした。
自分で解けた問題をWriteupとして書いておきます。
b64 (Crypto 100)
暗号化処理の概要は以下の通り。
secret:ランダムな8バイトデータ。 secretと入力文字列のXORを取り、その結果に64をプラスし、256で割った余りをASCIIコードとして文字にする。 その結果からBase64で使われる文字以外を削除する。 文字列長を4で割って、1余る場合はその1文字を削除する。 余りが2または3の場合は、=でパディングし、4の倍数の文字列長にする。 Base64デコードしたものが提示される。
Base64文字以外がないものを探すことができれば、XORでsecretを算出することができる。それをコードにしたものは以下の通り。
import socket PAD = 64 def recvuntil(s, tails): data = "" while True: for tail in tails: if tail in data: return data data += s.recv(1) def decrypt(s1, s2): dec = '' for i in range(len(s1)): code = ord(s1[i]) ^ ((ord(s2[i]) - PAD) % 256) dec += chr(code) return dec s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('flatearth.fluxfingers.net', 1718)) data = recvuntil(s, '\n') print data in_str = '' for i in range(4): found = False for code1 in range(0, 256, 16): for code2 in range(0, 256, 16): data = recvuntil(s, '>') data += recvuntil(s, ' ') print data + '1' s.sendall('1') data = recvuntil(s, '>') data += recvuntil(s, ' ') try_str = in_str + chr(code1) + chr(code2) print data + try_str s.sendall(try_str) data = recvuntil(s, '\n') print data dec = data[30:-1] if len(dec) > 0: b64 = dec.encode('base64').strip() b64_no_pad = b64.replace('=', '') if len(b64_no_pad) == ((i+1) * 2): in_str += chr(code1) + chr(code2) found = True break if found: break data = recvuntil(s, '>') data += recvuntil(s, ' ') print data + '2' s.sendall('2') data = recvuntil(s, '>') data += recvuntil(s, ' ') secret = decrypt(in_str, b64).encode('hex') print data + secret s.sendall(secret) data = recvuntil(s, '\n') print data data = recvuntil(s, '\n') print data
flag{7h3_b35t_w4y_of_h1ding_s3cr3t5_the_w0r1d_h4s_ev3r_seen_period!}