ptmalloc unlink macro analysis
unlink source(glibc2.23):
1 | /* Take a chunk off a bin list */ |
check:
- 在从bin中解链的时候首先会检查与victim相邻的下一个堆块的preszie是否与victim本身的size相等
- 双向链表完整性检查,即前一个堆块的bk是不是victim,后一个堆块的fd是不是victim
- 如果是largebin的unlink,还会检查nextsize构成的双向链表完整性
利用姿势:
unsafe unlink
largebin attack
存在tcache机制时,tcache stashing unlink
largebin:
由于largebin结构相对复杂,着重分析下largebin的unlink过程。
- if (P->fd_nextsize == P)为真,bin中只有相同size的chunk,取走P,FD需要做堆头,所以nextsize指针被赋值
- 如果FD不是堆头,这时候取下P,FD要充当以前P堆头的作用,所以nextsize指针被赋值
- 如果FD和P都是堆头,那就比较简单,类似于bk和fd的unlink操作将P从nextsize链取下即可
- 对于存在多个满足空间的堆块来说,申请出来的是堆头的下一个结点,它的
fd_nextsize
和bk_nextsize
为空。也就是说即使它是largebin chunk,但是它的fd_nextsize
也为空,即不满足条件__builtin_expect (P->fd_nextsize != NULL, 0)
,对于此类chunk的unlink,只会像smallbin的unlink一样检查fd
与bk
,而不会对fd_nextsize
与bk_nextsize
进行检查与操作
largebin利用:house of storm
先给出poc:
1 |
|
其实重点在于 large_bin[3]=(unsigned long)fake_chunk-0x18-5;这样设置bk_nextsize可以在unsortedbin中的chunk整理到largebin中时由于写操作把fakechunk的size部分写成堆地址的最高字节,也就是0x55或0x56(由于pie的原因),那么最终还是从unsortedbin取出的fakechunk,故需要unsorted_bin[1]=(unsigned long)fake_chunk;这样设置bk,当malloc(0x48)的时候,size是合法的会被取出。这个攻击方法感觉最终还是unsortedbin attack所以在2.29及其以后的版本会失效。
2019西湖论剑Storm_note:
exp
1 | #!/usr/bin/env python |