RCTF 2017 Writeup(供養)

RCTF2017にチーム:Harekazeの一員として参加してました。チームとしては8問解き2060点、そのうち1問を私が解きました。

[Misc] baby enc 434pts

baby_enc.zip

unzipするとOutuput.txtとenc.pyが渡される

hintにWindowsでやらないと結果が少し違うみたいなことが書かれてあるのでWindowsスクリプトを組む

enc.pyの中身は

import codecs
def enc(s, t):
    if t:
        l = list(map(ord, s))
        return enc(''.join(list(map(chr, [l[i]^l[i+1] for i in range(len(l)-1)]))), t-1)
    else:
        return s

with open('in.txt') as f:
    s = enc(f.read(), 5)
with open('out.txt', 'w') as f:
    f.write(s)

となっており、in.txtの中身を暗号化してout.txtに出力している。

この暗号化一見復号は無理そうだが、flagに限ってのみ復号が可能である。

最終的な出力結果についてだが入力をl[]の配列とすると

return s = [l[0]^l[4]^l[1]^l5], l[1]^l[5]^l[2]^l[6], .....]

のようになる。flagの形式がRCTF{…..}でRCTF{のここから5文字がわかることにより

l[0] = R
l[4] = {
l[1] = C
l[5] = ?

のように考えればl[5]がわかる。l[5]がわかればl[6]がわかる。最後に}が現れることを考えてコードを組む。

あとはどこからRCTFの文字列が始まるかを探すだけだがそれは総当りしておけば良い

そんなわけでソルバ

import codecs

def enc(s, t):
    if t:
        l = list(map(ord, s))
        return enc(''.join(list(map(chr, [l[i]^l[i+1] for i in range(len(l)-1)]))), t-1)
    else:
        return s


tmp=""
with open('out.txt','r') as f:
    tmp=f.read()
test = list(map(ord,tmp))
for i in range(len(test)-5):
    lis = list(map(ord,"RCTF{"))
    tmpi = i
    for j in range(len(test)-5-i):
        tmp = lis[j]^lis[j+1]^lis[j+4]^test[tmpi]
        tmpi+=1
        if chr(tmp) == "}":
            lis.append(tmp)
            print(str(i)+" results: "+''.join(map(chr,lis)))
            break
        elif chr(tmp) == "\n":
            break
        elif tmp < 43:
            break
        else:
            lis.append(tmp)

変数名の付け方はひどいが気にするな!!

flag:RCTF{te1l_mE_tHe_wAy_you_so1ve_thIs}