写在前面
最近项目不太紧,自己也有时间研究点感兴趣的东西。拜读了华庭大佬写的《glibc内存管理ptmalloc源代码分析》一书,想通过此书系统的学习一下linux下ptmalloc对堆管理机制。看完一大堆文字性的理论,总觉得啥也没有学会,于是决定通过调试具体的堆漏洞来加深对理论的理解。毕竟在利用某项机制漏洞的过程中,肯定包含了该机制的方方面面的知识!
本篇文章将通过pwnable.tw上一个实际的题目sprited-away,来说明堆攻击方法中的一种——house of sprits
一. 基本知识
对于这样一种攻击方式,我总结了它的核心技术点和适用场景
适用场景
需要分配到我们不可控的内存区域时
前提条件
- free函数的参数的第二个size_t是我们可控的,要求是fast bin,因此64bit下需要小于128B
- chunk0起始地址 + chunk0大小 = chunk1,chunk1的第二个size_t需要满足条件:大于2*size_t,小于 main arena(一般是128kb,即0x4000)。因此该参数要么我们可控,要么本来就是符合要求
攻击思路
先完成前提条件构造,然后将想要覆写区域的地址放在chunk0的fd处,接着释放chunk0,随机malloc一块与chunk0一样大小的堆块即可(注意此时是运用了fast bin的特性,需要大小精准匹配)
二. 漏洞分析
栈溢出
程序中的read的读入个数这个参数是保存在栈上的,距离v1有0x38个字节,然后后面有个处理就越界了
后面对v1进行了sprintf,这里如果cnt为两位数,正好覆盖nbytes为0,为三位数时候,覆盖nbytes为0x6e(n的ascii码值)这样的话,后面在处理输入comment时候就会溢出
输入comment时候,也是以nbytes的值作为输入个数,但是s到存放堆地址的buf距离为0x54,那么可以覆盖掉buf
buf 在后面会作为free的参数,因此free的参数是完全可控的,即可以通过“house of spirit”来攻击
三. 漏洞利用
基本思路 我们通过栈溢不能覆盖到返回地址,因此可以在栈上构造一块长度足以覆盖返回地址的堆块,然后通过”house of sprits”获取该堆块的控制权,从而覆盖返回地址进行漏洞利用
- 申请100个用户,使cnt为三位数,通过溢出修改nbytes为ord(‘n’)=110
- 利用printf函数输出reason时的一个栈泄露,泄露栈地址,计算出栈上存放comment的地址
- 在栈上布置伪造堆块,并将栈上buf覆盖为伪造堆块的地址
坑点:需要设置伪造堆块接下来一块的堆块头。以为在free伪造堆块时,会通过其下一块堆块的堆块头判断该堆块是否是空闲堆块。因此需要设置下一块堆块的堆块头size为合适的范围和 inuse=1,即表明前一块堆块被占用,这样free才能顺利进行
- house of spirit的方式,将fastbin堆块free后malloc同样大小的堆块,分配到的就是刚才的堆块,该堆块指向栈,即可以通过此堆块直接修改返回地址rop
- 第一次rop –> 泄露free_got ,得到system_addr ,sh地址 第二次rop –> 执行system(“/bin/sh”)