堆溢出就是这么简单

z在刚才,晚上十一点半,我突然意识到了数据结构的重要性。

        首先,链表,链表的应用在我现在接触到的无非就是pwn中的堆溢出了,在堆被FREE后,free的堆都被存放在相关的bins中,并且以链表的方式进行管理,以链表中节点进行类比的话,free的chunk中的FD就是指向前一个被free的chunk指针,而BD就是指向后一个被free的chunk的指针,如此的话,对bin的管理无非就是增加和删除,对应的链表形式无非就是FD和BD的变化,这一点如果对数据结构的链表很熟悉的话,对于从bin中的chunk链表删除一个chunk时FD和BK的变化应该是显而易见的。

        后悔没有把数据结构认真学好啊

什么是链表  <------不知道链表点他

浅谈链表(2)——节点的插入与删除  《-----------点他也可以

        关于堆溢出的学习,这次我选择先打牢固基础,在进阶。

        链表,链表结点的增添,链表节点的删除。

        接着说堆溢出攻击,如果在内存中,伪造一个chunk,类比链表无非就是在一处地址对齐的地方,创造一个node,这个node的前一个节点的指针和后一个指针写好就行了。换成堆溢出就是FD和BK要写好,然后再加上prev_size和size和标志位等数据,这样一个假的chunk就创建成功了。

        关于doublefree  这个是我今晚刚刚查的,其实就是在free一个chunk后再次free一个相同的chunk,这样的话链表中的结构就类似于这样了

记忆的时候,一定记清楚,fd就是forward,指的是之前释放的堆,也就是前一个

(下面的这张手绘图可能不对,因为我是按照以前的调试和记忆写的)


在各种bins中,其实就是个单链表和双链表的关系。(推荐看数学之美这本书,这里就体现到了数据结构的作用)


了解了这一点,我相信在学习中是很有z用处的。

实验demo1


#include

int main()

{

    int *p=malloc(0x30);

    int *p1=malloc(0x30);

    int *p2=malloc(0x30);

    int *t=malloc(0x40);

    int *t1=malloc(0x40);

    int *t2=malloc(0x40);

    sleep(2);

    free(p);

    free(t);

    free(p1);

    free(t1);

    free(p2);

    free(t2);

    return 0;

}



经过调试后知道。


fastbin中freechunk的插入位置在红箭头标志处,即在该链表的头部,应该可以类比为头插法。

在新的malloc时,如果chunk大小在与某一fastbin链表匹配,则把该链表的第一个即最近新释放的chunk释放给新的malloc



这样如果伪造一个chunk的话,也很简单啊就拿下面的图中链表结构来说。


上面链表原来是这样heap->0x602080 —▸ 0x602040 —▸ 0x602000


如果在地质上伪造一个chunk的话,只需要这样做就可以了,如我在0xffddff80处伪造一个chunk

并且我向插在下图黄标处,


那只需这样,1,创建一个假的chunk(结点),chunk的fd内容为0x602040,就想单链表插入一个结点一样。


然后让0x602080chunk(结点)的fd为0xffddff80即指向假的chunk(插入的结点),如下


这就是单链表插入结点的原理,只不过还要注意size位和标志位和其他一些东西,但都很简单,

如果是shortbin或者largebin伪造一个假的chunk,那么把单链表插入结点换成双链表插入结点的方式就好了。

到这里,突然就觉的堆溢出没那么难了。

无论fastbin攻击,doublefree,UAF,还是ONE-BY-ONE,无非就是利用了chunk的FD指针任意指向漏洞,然后在目的地址处配合一些数据达到攻击。知其然要知其所以然。堆的主要维护就是创建和free。如何创建以及如何free就决定着堆攻击的方法。free后由bins维护,但是bins是链表数组,数组的每一个数据位都是一个链表的head结点这样理解。这样在对chunk的malloc和free时,就有了攻击的机会。


无论难不难,还是要继续学习,虚心请教,2019/12/8

上面仅仅是一个小面,需要配合malloc机制的好多。

这里,malloc源码选择性查看:malloc源码点这里

后续。。。。。

你可能感兴趣的:(堆溢出就是这么简单)