freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

源码分析:malloc.c中重要的宏
2021-09-30 13:56:53

我们之前讲了不少的漏洞,但是这只是原理上的,我们想要更好的利用,少不了分析一些源码。我们首先来分析一下malloc.c中比较重要的宏

request2size

#define request2size(req)                                         \
  (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE)  ?             \
   MINSIZE :                                                      \
   ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)

#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)

#define MALLOC_ALIGNMENT       (2 * SIZE_SZ)

#define MINSIZE  \
  (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))

#define MIN_CHUNK_SIZE        (sizeof(struct malloc_chunk))

struct malloc_chunk {

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

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

首先是request2size宏,我在glibc中找到了所有和它相关的宏定义。这个request2size宏定义是为了实现用户请求的内存块和malloc实际分配的内存块做一个转换。req就是我们要请求的内存块。

首先请求的时候首先进行比较,req+8+15<32,也就是说当我们申请分配0~8个字节的时候,实际上都会给我们分配32字节的内存,也就是0x20。

当我们申请的字节数大于8的时候,实际会分配给我们(req+0x8+0xf)&(~0xf)个字节。举例来说例如我们申请0x12字节的内存,实际分配也就是0x20字节。

大家计算以后会发现,这样请求可以利用到下一个chunk的prevsize,并且可以使内存对齐

chunk2mem和mem2chunk

#define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))

这个比较简单,我们之前已经提到过,我们实际申请的内存的指针其实是chunk的size字段尾部,于是我们可以让指针进行转化,chunk2mem就是chunk指针转化为user指针,mem2chunk就是user指针转化为chunk指针

chunk的状态

#define PREV_INUSE 0x1
#define IS_MMAPPED 0x2
#define NON_MAIN_ARENA 0x4

这三个我们之前也解释过,分别处于chunk的size字段的最后一位,倒数第二位,倒数第三位。prev_inuse位表示了前一个chunk是否处于使用状态,is_mmapped表示chunk是否由mmap映射得到,non_main_arena表示chunk是否不是主线程的chunk

对某chunkP的标志位进行提取和修改

#define SIZE_BITS (PREV_INUSE|IS_MMAPPED|NON_MAIN_ARENA)

#define prev_inuse(p)       ((p)->size & PREV_INUSE)

#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)

#define chunk_non_main_arena(p) ((p)->size & NON_MAIN_ARENA)

#define inuse(p)\
((((mchunkptr)(((char*)(p))+((p)->size & ~SIZE_BITS)))->size) & PREV_INUSE)

#define set_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~SIZE_BITS)))->size |= PREV_INUSE

#define clear_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~SIZE_BITS)))->size &= ~(PREV_INUSE)

首先我们定义了SIZE_BITS,类似于掩码的作用。第二三四个宏都是提取相应位置的状态位。

本堆块的下一个堆块的prev_inuse位表示了本chunk的使用情况,第五个宏定义就是提取本chunk的下一个chunk的prev_inuse位

第六个表示将chunkp的下一个chunk的prev_inuse位设置为1

最后一个宏表示将chunkp的下一个chunk的prev_inuse位设置为0

对当前chunk的inuse位进行修改

#define inuse_bit_at_offset(p, s)\
 (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
 
 #define set_inuse_bit_at_offset(p, s)\
 (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
 
#define clear_inuse_bit_at_offset(p, s)\
 (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))

第一个宏表示了当前chunk的inuse位
第二个宏表示修改当前的chunk的inuse位为1
第三个宏表示修改当前chunk的inuse位为0
其中p和s分别表示当前chunk的指针和当前chunk到下一个chunk的偏移

设置当前chunk的size位

#define set_head_size(p, s)  ((p)->size = (((p)->size & SIZE_BITS) | (s)))

#define set_head(p, s)       ((p)->size = (s))

#define set_foot(p, s)       (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))

#define chunksize(p)         ((p)->size & ~(SIZE_BITS))

第一个宏表示设置p的size位,并且不修改size位的低三位
第二个宏表示设置p的size位,但是会可以修改低三位
第三个宏表示设置chunkP的下一个chunk的prev_size位,至于为什么叫做set_foot则与chunk结构的前世今生有关,以后有时间讲一下
第四个宏表示提取p的size位但是不包括低三位

寻找与当前chunk物理相邻的chunk

#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~SIZE_BITS) ))

#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))

#define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))

第一个宏表示寻找当前chunk物理相邻的高地址chunk
第二个宏表示寻找当前chunk物理相邻的低地址chunk
第三个宏表示当前chunk加上某偏移后的地址,也就是说当前chunk加上某个偏移之后的地址,将会被视为一个chunk的头指针

这些就是总结的一些比较重要的指针,到后面不管是malloc底层代码还是chunk合并代码,包括unlink,都会用到这些宏

本文参考自glibc源码及其注释

# linux # glibc # 代码分析 # 堆 # pwn
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者