Rating: 1.0
データを暗号化してくれるサーバが動いており、鍵とフラグは外部から読み込んでいる。サーバの Python コードが公開されている。
コードを見ると、”l33t please” で始まる文字列を渡すと、文字列の末尾にフラグを追加したうえで AES で暗号化して base64 で返してくれる。CBC などは特に使っていないようで、同じ文字列は毎回同じように返ってきた。
AES のブロックサイズは 128 ビットなので、16文字ごとに、望むものと一致すればその部分の暗号は同じになる。
フラグの i 文字目までがわかっているとき、 “l33t please”に続けて、適当な文字を適宜詰め、そのあとフラグの i 文字目までを埋めて最後のブロックが一文字だけ余る状態にし、残りの1文字を一通り試すことができる。
この時、”l33t please”とパディングのみを渡した結果(この場合はパディングの直後に正しいフラグを入れて暗号化してくれる)と比較すれば、正解の時だけ合致するブロックが多くなる。
これを順に試せば、フラグが出てくる。
#!/usr/bin/python
import commands
import sys
def encrypt(s):
return commands.getoutput('echo -n \'' + s + '\' | (base64 -w 0; echo) | nc l33tcrypt.vuln.icec.tf 6001 | grep OH7').strip()
def sharestr(s, t):
ret = 0
for i in range(0, min(len(s), len(t))):
if s[i] == t[i]:
ret = i + 1
else:
break
return ret
header = 'l33tserver please'
flag_cand = ''
cand_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_{}'
cur_cand = ''
while True:
cur_cand_len = 0
tmphead = header + '/' * (16 - (len(header) + len(flag_cand) + 1) % 16)
cur_enc = encrypt(tmphead)
for i_loop in range(0, len(cand_chars)):
now_cand = flag_cand + cand_chars[i_loop]
print 'Trying: ', tmphead + now_cand
tmp_enc = encrypt(tmphead + now_cand)
tmp_len = sharestr(cur_enc, tmp_enc)
print tmp_len
if tmp_len > cur_cand_len:
cur_cand_len = tmp_len
cur_cand = now_cand
if len(cur_cand) == len(flag_cand):
sys.exit(1)
flag_cand = cur_cand
not in english