RCTF2017にチーム:Harekazeの一員として参加してました。チームとしては8問解き2060点、そのうち1問を私が解きました。
[Misc] baby enc 434pts
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}