House of storm

house of storm 是一个结合了 unsorted bin 和 largebin attack 的危害性极高的组合漏洞。其效果是可以实现任意地址申请一个堆块

1
2
3
4
1. glibc版本小于2.29
2. 需要攻击者在 large_bin 和 unsorted_bin 中分别布置一个chunk 这两个chunk需要在归位之后处于同一个 largebin 的index中且 unsorted_bin 中的chunk要比 large_bin 中的大
3. 需要 unsorted_bin 中的 bk指针 可控
4. 需要 large_bin 中的 bk指针和bk_nextsize 指针可控

我们把 unsorted bin 里的chunk的 bk 改为 target_addr ,把 large bin 里的chunk的 bk 改为 target_addr + 8 ,把 bk_nextsize 改为 target_addr - 0x18 - 5。这样再通过一系列的过程就可以伪造出一个堆块并链入 unsorted bin 中,再申请相应大小的堆块,即可实现任意地址分配。

首先把 unsorted bin 里的 bk 改为 target_addr。实现了伪造 fake_chunk 的 fd,以及将其链入 unsorted_chunks(av)

glibc2.23的malloc.c中第3515行代码处:

1
2
3
/* remove from unsorted list */
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

修改large bin 里的chunk的 bk 改为 target_addr + 8 ,那么触发了largebinattack后,target_addr + 8+0x10也就是其bk指针被写入了一个合法的堆地址,现在我们还需要伪造一个合法的size让我们能把伪造的chunk申请出来

house of storm的精髓 : 把 bk_nextsize 改为 target_addr - 0x18 - 5,64位下地址其实只用了6个字节,通过错位,让地址的最高字节写进size位效果如下:

1

开启ASLR的情况下我们的堆地址会以0x55或0x56开头,我们需要将这个地址的size写成0x56因为我们还需要通过如下检查:

2

三者满足其一即可,我们能满足chunk_is_mmapped (mem2chunk (mem))

1
2
#define chunk_is_mmapped(p) ((p)->mchunk_size & IS_MMAPPED)
#define IS_MMAPPED 0x2

0x55&0x2 = 0是无法通过的,需要0x56,还是有很大概率成功的

至于为什么伪造largebin的bk和bk_nextsize和其实现的效果可以参考上一篇博客,初探largenbin的那篇,里面详细解释了,这里不再赘述

这时候unsortedbin再把这块fake_chunk的size和我们的malloc的size比较,我们malloc(0x48)也就是被对齐为0x50,那么满足我们的申请,直接把这块chunk给我们

3

小结

总结一下,假设我们已经利用漏洞布置好了堆风水,拥有了合适的unsortedbin和largebin,那么可以做如下修改

1
2
3
4
unsortedchunk ->bk = fake_chunk

largechunk ->bk = fake_chunk + 8
largechunk ->bk_nextsize = fake_chunk - 0x18 - 5