首页
社区
课程
招聘
[原创]Glibc Heap 利用之初识 Unlink
发表于: 2018-11-20 20:53 11808

[原创]Glibc Heap 利用之初识 Unlink

2018-11-20 20:53
11808

0x0 malloc_chunk 详解

在 Glibc 管理堆的过程中,无论一个内存块(chunk)是处于已分配状态还是处于空闲状态,Glibc 都统一使用一个名为 malloc_chunk 的结构体对其进行描述(可以将其理解为 chunk 的 header),下图简单描绘了 chunk 在堆中的一个布局:

 

图片描述

 

而关于 malloc_chunk 的具体内容,我们可以查阅 Glibc源码中的 mallo.c 文件,如下所示:

struct malloc_chunk {

  INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

malloc_chunk 中的各个字段对于已分配的块和空闲的块而言,是有着不同含义的:

  • mchunk_prev_size: 如果当前 chunk 所相邻的上一个 chunk (地址较当前块低的)为空闲状态,该字段便会记录上个 chunk 的大小(包括 chunk 头)。若否,那该字段便会被上个 chunk 用来存储数据。
  • mchunk_size: 该字段表示当前 chunk 的大小,在32位系统中,其大小最小不可低于16个字节,对齐则为8个字节。而在64位系统中,其大小不可低于32个字节,对其则为16个字节。
  • fd: 在空闲的 chunk 中,指向前一个与之不相邻的空闲 chunk。在已分配的 chunk 中,该字段直接指向用户数据区。
  • bk: (该字段只被空闲的 chunk 所使用)指向后一个与之不相邻的空闲 chunk。
  • fd_nextsize: (该字段只会被空闲的 large chunk 所使用)指向前一个与当前 chunk 大小不同的空闲 large chunk。
  • bk_nextsize: (该字段只会被空闲的 large chunk 所使用)指向后一个与当前 chunk 大小不同的空闲 large chunk.

空闲的 chunk 所对应的 malloc_chunk 结构体由 glibc 的内存管理器 ptmalloc 所管理,ptmalloc 会根据它们的大小和使用状态将它们保存到互不相关的链表中,而它们在堆中的结构大概是下面这样子的:

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if unallocated (P clear)  |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `head:' |             Size of chunk, in bytes                     |A|0|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                           |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of next chunk, in bytes                |A|0|0|
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

已分配的 chunk 在堆中的结构则是这个样子:

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if unallocated (P clear)  |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk, in bytes                     |A|M|P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             User data starts here...                          .
            .                                                               .
            .             (malloc_usable_size() bytes)                      .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             (size of chunk, but used for application data)    |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of next chunk, in bytes                |A|0|1|
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

0x1 Unlink 简单概述

简单来说,unlink 就是一个被 ptmalloc 用来提取双向链表(指上文中通过 chunk 头管理堆中空闲 chunk 的链表)中空闲 chunk 的操作。它的基本流程如下图所示:

 

图片描述

 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-1-31 17:28 被kanxue编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (9)
雪    币: 2087
活跃值: (472)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
沙发~
2018-11-20 21:17
1
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
 
2018-11-21 09:54
2
雪    币: 3500
活跃值: (800)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
0x1 Unlink简要概述那张图  双向链表的指向好像有问题  和《0day安全》好像不太一样 书上是链表链
你看 是不是应该是下图的样子


最后于 2018-11-26 16:27 被F4our444编辑 ,原因: 清晰
2018-11-26 16:19
0
雪    币: 540
活跃值: (46)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
噗咚Four 0x1 Unlink简要概述那张图  双向链表的指向好像有问题  和《0day安全》好像不太一样 书上是链表链你看 是不是应该是下图的样子
您好,对于您所提到的问题,您可以看一下 glibc 源码中 unlink 的定义,一个前向/后向指针所代表的应该是一个空闲 chunk 的起始地址,而不是 fd、bk 字段(在 Glibc 中可以说是这样的),不知道我这样回答能否解决您的疑惑。
2018-11-26 19:01
0
雪    币: 38
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
哈哈哈  pwnable那道题我前几天刚玩过
2018-11-29 18:21
1
雪    币: 540
活跃值: (46)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
cjkillyes 哈哈哈 pwnable那道题我前几天刚玩过
嗯嗯,加油,有什么知识也可以一起交流!
2018-11-29 19:26
0
雪    币: 5859
活跃值: (4199)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
8
入门好贴
2019-7-21 08:25
0
雪    币: 8511
活跃值: (5131)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
9
mark
2019-9-11 14:16
0
雪    币: 203
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
这个bk和fd指针指向的好像是上一个或者下一个的bk和fd的位置,而不是prev_size的位置。是这样的吗?
2020-12-15 16:12
0
游客
登录 | 注册 方可回帖
返回