この大会は2017/9/16 5:00(JST)~2017/9/18 5:00(JST)に開催されました。
今回もチームで参戦。結果は2126点で1444チーム中101位でした。
自分で解けた問題をWriteupとして書いておきます。
Super Difficult Recon (Recon 1)
問題に書かれているフラグが答え。
flag{f00led_uuuuuuu}
Another Xor (Crypto 100)
plaintext = msg + key + md5(msg + key).hexdigest() cipher = plaintext ^ [key * (msgの長さ/keyの長さ + 1) (plaintextの長さまで)]
plaintextとkey(繰り返し)のXORになっている。plaintextのkeyが含まれている部分に注目して、キーの組み合わせを絞りながら総当たりする。
import itertools import string def xor(s1,s2): return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2)) def repeat(s, l): return (s*(int(l/len(s))+1))[:l] def chk_printchr(k): for i in range(len(k)): if k[i] < 32 or k[i] > 126: return False return True with open('encrypted', 'rb') as f: enc = f.read().strip() cipher = enc.decode('hex') len_c = len(cipher) key_list = [] for len_k in range(2, 105): for i in range(32, 127): try_key = [-1] * len_k try_key[0] = i index = 0 base = len_c - 32 - len_k for j in range(len_k): if try_key[(base + index) % len_k] == -1: try_key[(base + index) % len_k] = ord(cipher[base+index]) ^ try_key[index] index = (base + index) % len_k else: if try_key[(base + index) % len_k] == ord(cipher[base+index]) ^ try_key[index]: key = try_key if chk_printchr(key): key_list.append(key) break else: break for key in key_list: key_str = '' for i in range(len(key)): key_str += chr(key[i]) plaintext = xor(cipher, repeat(key_str, len(cipher))) ng = False for i in range(32): if plaintext[-32+i] not in string.hexdigits: ng = True break if ng == False: print 'key =', key_str print 'plain =', plaintext
実行結果は以下の通り。
key = A quart jar of oil mixed with zinc oxide makes a very bright paint| plain = flag{sti11_us3_da_x0r_for_my_s3cratz}|A quart jar of oil mixed with zinc oxide makes a very bright paint|d5111350bbbe105121b9a9496ac08df2
flag{sti11_us3_da_x0r_for_my_s3cratz}