之前在大学的时候就看过堆溢出,感觉好绕,看不懂,后来也凑合看懂了,最近突然想简单总结两句。
首先,堆的维护和栈的维护不一样,栈是由CPU维护的,是运行的基础必须存在;而堆是对栈的补充,由操作系统维护。
操作系统为了管理堆(动态内存分配),需要额外的代码,不同操作系统有不同,甚至同样的操作系统可能提供好几种管理方法,比如RT-Thread就有三种。
为了操作系统可以正确的管理堆,堆的头部都会有一个“标牌”,这个标牌确定了堆的地位,上下位置等。
“标牌”中的值,尤其是链表地址一类的东西,在内存管理器中是作为 左值 存在的,这意味着如果“标牌”中的值飞了,管理器就会向不可控的位置“瞎写”。
堆攻击的根本就是改动“标牌”,无论是溢出还是double free,本质都是改动“标牌”的值,然后假借堆管理unlink的手进行内存任意写。
堆溢出的话就是通过溢出改动下一个临近堆的“标牌”。
double free中,就是借着第一次free拿到更改标牌的机会,之后通过第二次free触发标牌的ulink使用,假借堆管理unlink的手进行内存任意写。
所以针对堆攻击的研究,首先要去看堆管理器的代码,熟悉逻辑之后,确定“标牌”中的值会被在何时何地作为左值利用。之后才是分析应用是否给了我们改动“标牌”的机会。