文章

堆与最基本的堆溢出-fastbin

一些关于堆的小知识和基本的利用 fastbin

基础知识

内存上的空间会被划分为若干个chunk

chunk包括以下两种:

已分配的堆块:

     chunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if allocated            | |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk, in bytes                       |M|P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             User data starts here...                          .
            .                                                               .
            .             (malloc_usable_size() bytes)                      .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk                                     |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

未分配的堆块:

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk                            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `head:' |             Size of chunk, in bytes                         |P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Forward pointer to next chunk in list             |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Back pointer to previous chunk in list            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Unused space (may be 0 bytes long)                .
            .                                                               .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `foot:' |             Size of chunk, in bytes                           |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

它们的各个参数意义分别是:

prev_size: 如果当前chunk的相邻前一chunk未被使用,prev_size为此前一chunk的大小
size: 当前chunk的大小。由于chunk大小是8的整数倍,所以此size的后3 bit被用于存储其他信息。我们需要记住的便是最低bit,即图中P的位置,用于指示前一chunk是否已被使用(PREV_INUSE)。

如果当前chunk处于未被使用状态,则mem前8 bytes被用来存储其他信息,具体如下:
fd: 下一个未被使用的chunk的地址
bk: 上一个未被使用的chunk的地址

可以看到,chunk头中包含的大小信息,主要用来在获取内存中相邻chunk的地址(当前chunk地址减去前一chunk的大小,为前一chunk的地址;当前chunk地址加上当前chunk的大小,为后一chunk的地址)。而mem中的fd和bk只在当前chunk处于未被使用时才有意义,因为当我使用了此chunk后mem里的空间被用来存储数据。
通过这些未被使用的fd、bk chunk组成了一张链表。通常差不大小的chunk会被放在一起组成一张链表,其被称为bin。bin的集合被malloc合并,被称为bins。

fastbin维护一大堆的链表,当申请较小内存空间时它们会被从fastbin中剪除,并返回此地址。
在free时,为了快速回收这些空间,将不通过bk仅由fd将chunk插进fastbin。并且其满足后进先出的原理

fastbin

由于fastbin没有bk,是一个单向链表,因此可能会触发任意写的问题。

fastbin中的东西实际上是通过在内存上连续排布来实现的。当堆栈顶部的chunk被出栈以后实际上fastbin会指向次chunk的上一个。

此过程是通过fastbin中此大小的指针指向chunk的fd来实现的。所以如果fd被通过某种技术覆写,那么malloc就会返回被覆写入的地址。如果mem被丢入一个十分大的数据就会把下面的覆写了,这会导致再进行两次malloc就会返回你所定义的伪chunk中的内容。

这个伪chunk会指向你需要的任意地方,利用这种指针可以触发任意写

License:  CC BY 4.0