glibc-2.31版本利用
glibc-2.29~2.31
fastbin_double_free
需要构造:前一个释放堆块 old,与当前释放堆块 p 有 old != p。
fastbin double free
的 poc 利用如下:
1 |
|
image-20220419185557111
申请出九个堆块。
image-20220419185812476
释放掉七个堆块,填满 tcache bin。
image-20220419185951969
再释放 p、q 两个堆块,由于 tcache bin 满了,进入到 fastbin 中
image-20220419190144978
fastbin_double_free 利用总结
效果:实现任意地址写
- 释放七个堆块填满 tcache bin。
- 再释放两个堆块进入 fastbin,按照 p-q-p 的顺序释放,即可形成 double free。
tcache_double_free
poc如下:
1 |
|
image-20220419193416703
2.29以后的版本,在释放堆块的 bk 位置将会填上 tcache 的地址作为一个 key,如果 key == tcache 则说明堆块已释放。
image-20220419193649480
image-20220419193807297
将这个key值改掉即可与之前版本一般,直接再次释放该堆块形成 double free。
tcache_double_free 利用总结
效果:实现任意地址写
- 释放一个堆块。
- 修改堆块 bk 位置上的 key。
- 再次释放该堆块。
tcache_poisoning
在 glibc-2.31 中,tcache count 的数量不能小于 0,否则将无法分配堆块。
poc如下:
1 |
|
image-20220419222640503
申请出两个堆块,然后再将其释放,顺序为 b -> a。
image-20220419223405043
修改 b 的 fd 指针指向要修改的内容,然后只需要将堆块分配即可。
tcache_poisoning 利用总结
效果:实现任意地址写
- 释放堆块 b -> a
- 修改 b 的指针指向想要分配堆块的地址
相比与之前版本可以让 count 为负值,构造链表尾部的堆块;glibc-2.31需要在前一个堆块开始构造,绕过 count 的限制,
tcache_stashing_unlink
libc-2.29开始,出现了一种叫 stash 的机制,基本原理就是当调用 _int_malloc 时,如果从 smallbin 或者 fastbin 中取出 chunk之后,对应大小的 tcache 没有满,就会把剩下的 bin 放入 tcache 中
poc如下:
1 |
|
image-20220426210920666
目标地址0x555555558050,值为0。
image-20220426211028509
释放六个大小为0x60的堆块进入 tcache bin 里面。
image-20220426211149437
申请两个堆块,一个大于tcache[max],另一个防止合并。
image-20220426211255158
释放大堆块进入到 unsorted bin 中,再申请一个计算好的堆块,让大堆块进行分割,剩下的大小与之前申请的堆块大小一致,再申请一个更大的堆块,让这个堆块进入到 small bin 中。
image-20220426211447839
做一遍类似的操作,但是这次阻止合并堆块的大小要大于定好的堆块大小,防止 small chunk 进行分配。
image-20220426211614394
一样的操作,再让一个堆块进入到同样size序列的 small bin 中。
image-20220426211858473
修改后进入 small bin 的那个堆块的 bk 指针为 目标地址 - 0x10。
image-20220426212131959
最后使用 calloc 申请一个同等 size 的堆块,即可在目标地址上写入一个大数。
tcache_stashing_unlink利用总结
效果:往任意地址里写入一个 0x7f 头的大数,unsorted bin attack 的替代手法。
- 选定一个 n = size,释放六个大小为 n 的堆块进入到 tcache bin
- 精心准备让一个堆块进入到 unsorted bin 中,同时使得这个堆块的 size 变为 n,再让其进入到 small bin 中。
- 再重复构造一个同样 size 为 n 的堆块进入 small bin 后,修改该堆块的 bk 指针为 目标地址-0x10
- 使用 calloc 申请一个 size 为 n 的堆块
注:被修改 bk 指针的堆块,fd 是不能被改变的,所以需要获取到堆地址
tcache_stashing_unlink+
poc如下:
1 |
|
image-20220426221322819
目标地址为0x555555558060,值为0。
image-20220426221553008
在 victim[1] 写入 victim 的地址。
image-20220426221722290
释放五个size为0x60的堆块进入tcache bin中。
image-20220426221846227
跟 tcache_stashing_unlink 中的一样的做法,让一个size也为0x60的堆块进入到small bin中。
image-20220426222049041
再制造一个size为0x60的堆块进入到smallbin中。
image-20220426222256149
把后进入smallbin的堆块bk修改为&victim-0x10,fd保持不变。
image-20220426222527079
再使用calloc申请size为0x60的堆块,此时victim也将被放入到tcache中。
image-20220426222958162
此时可以把victim申请出来,获得任意写的能力。
tcache_stashing_unlink+利用总结
将一个任意地址当做堆块放入到 tcache 中。
- 选定一个 n = size,释放五个大小为 n 的堆块进入到 tcache bin
- 精心准备让一个堆块进入到 unsorted bin 中,同时修改这个堆块的 size 变为 n,再让其进入到 small bin 中。
- 再重复构造一个同样 size 为 n 的堆块进入 small bin 后,修改该堆块的 bk 指针为 &target - 0x10
- 在 &target + 8 的位置要存放有任意一个可写的地址,满足检查。
- 使用 calloc 申请一个 size 为 n 的堆块
- 此时 target 将被放入 tcache 中。
注:被修改 bk 指针的堆块,fd 是不能被改变的,所以需要获取到堆地址。
tcache stash unlink attack++
这个方法与tcache_stashing_unlink+几乎相同。
poc如下:
1 |
|
该手法就是第一种和第二种的叠加手法,就不细说了,直接总结手法。
tcache_stashing_unlink++利用总结
将一个任意地址当做堆块放入到 tcache 中,同时可以往一个任意地址写入一个 libc 地址。
- 选定一个 n = size,释放五个大小为 n 的堆块进入到 tcache bin;
- 精心准备让一个堆块进入到 unsorted bin 中,同时使得这个堆块的 size 变为 n,再让其进入到 small bin 中;
- 再重复构造一个同样 size 为 n 的堆块进入 small bin 后,修改该堆块的 bk 指针为 &target1 - 0x10;
- 在 &target1 + 8 的位置填写 &target2 - 0x10;
- 使用 calloc 申请一个 size 为 n 的堆块;
- 此时 target1 将被放入 tcache 中,同时对 target2 写入一个 libc 地址。
注:被修改 bk 指针的堆块,fd 是不能被改变的,所以需要获取到堆地址。
house_of_botcake
poc:
1 |
|
释放 7 个 0x100 的堆块填满 tcache。
image-20221117131357835
再释放两个同样为 0x100 的堆块,这两个堆块会进行合并。
image-20221117132805303
申请一个 0x100 的堆块,空出一个 tcache bin。
image-20221117133743383
然后利用 UAF 再次释放合并进入到 unsorted bin 的堆块,造成了存在一个堆块即在 tcache 里,又在 unsorted bin 里。这里的堆块不能选择释放头部,因为那样会变成让 0x220 的堆块进入到 tcache。
image-20221117134045922
申请一个大于 0x100 的堆块,绕开 tcache,而获得到了 unsorted bin 里的堆块,但是这个堆块可以覆盖存在于 tcache 里的堆块,最终造成可以地址分配堆块,任意地址写。
image-20221117134330799
house_of_botcake利用总结
前提:拥有 UAF
- 释放七个 size 满足进入 unsorted bin 的堆块填满 tcache,再释放两个同样 size 的堆块 a b (a前,b后)进入到 unsorted bin
- 申请回一个 tcache,然后利用 UAF 释放堆块 b
- 申请一个大于 size 的堆块,此时可以通过该堆块完成对 b 堆块的覆盖,并且 b 堆块仍然在 tcache 里。
- 本文作者:ShouCheng
- 本文链接:http://shoucheng3.github.io/2022/03/14/2022-03-14-glibc-2.31%E7%89%88%E6%9C%AC%E5%88%A9%E7%94%A8/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!