VolgaCTF 2017 Teaser Writeup

この大会は2017/2/25 18:00(JST)~2017/2/26 0:00(JST)に開催されました。
今回もチームで参戦。結果は335点で292チーム中6位でした。
自分で解けた問題をWriteupとして書いておきます。

Now you see me (Crypto 150)

スクリプトと暗号化されたPNGファイルが添付されている。
スクリプトを読むと、IDATのデータ部が4バイトごとに暗号化されていることがわかる。CRC部に鍵を暗号化しているので、まず鍵を復号して、その鍵を使って復号するコードを書く。

def bytes2reg(m):
    L = 8
    pol = []
    dic = {'1' : 1, '0' : 0}
    for i in m:
        b = bin(ord(i)).split('b')
        b = b[1]
        b = '0'*(L - len(b)) + b
        for c in b:
            pol.append(dic[c])
    return pol

def reg2bytes(pol):
    res = ""
    if len(pol) % 8 != 0:
        pol.extend([0 for _ in range(8 - (len(pol) % 8))])
    b = [int(i) for i in pol]
    for i in range(4):
        ch = 0
        pw = 7
        for _ in range(8):
            ch += b.pop(0) * (2**pw)
            pw -= 1
        res += chr(ch)
    return res

def decrypt(c, k):
    dec = [0] * 32 + [i for i in c]
    for i in range(31, -1, -1):
        dec[i] = dec[32+i] ^ dec[31+i] ^ dec[16+i] ^ dec[1+i] ^ k[i]
    return dec[:32]

def key_decrypt(c):
    dec = [0] * 32 + [i for i in c]
    for i in range(31, -1, -1):
        dec[i] = dec[31+i] ^ dec[30+i] ^ dec[15+i]
    return dec[:32]

with open('file.png', 'rb') as f:
    file = f.read()

flag = file[:file.find('IDAT')]
flag += 'IDAT'

p = file.find('IDAT')
length = int(file[p-4:p].encode('hex'), 16)
l = length - (length % 4)
cnt = p + 4 + length + 4

e_key = file[cnt - 4:cnt]
key = key_decrypt(bytes2reg(e_key))

data = file[p+4:p+length+4]
for i in range(0, l, 4):
    block = data[i:i+4]
    block = bytes2reg(block)
    d = decrypt(block, key)
    flag += reg2bytes(d)

flag += file[p + 4 + l:p + 4 + length]
flag += reg2bytes(key)
flag += file[cnt:]

with open('flag.png', 'wb') as f:
    f.write(flag)

復号すると、画像にフラグが書いてある。
f:id:satou-y:20170301205853p:plain

VolgaCTF{Th3r3_4r3_tw0_kind5_0f_crypt0gr4phy_in_7his_w0r1d}

Quiz (Joy 10)

クイズというかVolgaCTF 2017 Qualsの大会参加の意思表明みたいなものだった。

Yes