首页
社区
课程
招聘
深度理解glibc内存分配
发表于: 2022-1-28 19:34 29587

深度理解glibc内存分配

2022-1-28 19:34
29587

  如果对glibc内存管理的逻辑比较了解,在学习各种堆漏洞利用的方法时,就会更顺畅一些,而且glibc内存管理的代码,本身也很值得看一看,好几次决定写点总结,都是咬咬牙又放弃了,现在,我觉得已经不能再拖了。

  在刚入门C语言编程时就知道:为了使用一块堆内存,要先分配。随着接触编程一段时间后,慢慢开始意识到:分配,就是底层代码把正在使用的内存区域记录下来,从而保证程序始终知道哪些空间是正在使用的,哪些空间当前是空闲的,进一步保证每次获取的内存,不会与正在使用的内存重叠。

  刚才已经说了,CPU的权限是支持调节的,最高权限时,可以执行所有指令,包括将权限调低,但低权限向高权限调节,就需要接受额外的条件(否则权限如果可以随意调高,那么权限设计的意义就没了),那就是必须穿过“门”进行提升,而在穿过“门”的同时,也要求执行一次代码跳转(这种要求,以及“门”的设计,也是硬件层实现的),而内核代码是在CPU刚上电时就开始执行了,相比用户程序,内核具有设置这个跳转地址的先机,所以当然会将其设置为内核代码的地址。这样,内核代码就总能在最高权限执行,而用户代码总是在低权限执行,同时又有路径从用户态(低CPU权限下执行用户代码的状态)回到内核态(最高CPU权限下执行内核代码的状态)。很多特权指令,只在CPU高权限状态时有效,比如CR3寄存器的读/写指令,从而“强制”用户程序使用内核接口,对进程本身的虚拟空间和占用的物理内存,进行管理。

  这块内容是参考《Glibc内存管理--Ptmalloc2源代码分析.pdf》学习的,这份pdf文件总共129页,分析过程非常详细、深刻,为了防止遗忘,我整理了一个主要过程出来,并且为有些部分添加了配图和个人的理解。

《Glibc内存管理--ptmalloc2源代码分析》博客系列:https://www.iteye.com/blog/user/mqzhuang

// 32位系统
*(char *)0x9d08008 = 0;
// 32位系统
*(char *)0x9d08008 = 0;
jmpcall@ubuntu:test$ ./a.out
Segmentation fault
jmpcall@ubuntu:test$ ./a.out
Segmentation fault
int main()
{
 80483c3:    55                       push   %ebp
 80483c4:    89 e5                    mov    %esp,%ebp
        *(char *)0x9d08008 = 0;
 80483c6:    b8 08 80 d0 09           mov    $0x9d08008,%eax
 80483cb:    c6 00 00                 movb   $0x0,(%eax)
        return 0;
 80483ce:    b8 00 00 00 00           mov    $0x0,%eax
}
int main()
{
 80483c3:    55                       push   %ebp
 80483c4:    89 e5                    mov    %esp,%ebp
        *(char *)0x9d08008 = 0;
 80483c6:    b8 08 80 d0 09           mov    $0x9d08008,%eax
 80483cb:    c6 00 00                 movb   $0x0,(%eax)
        return 0;
 80483ce:    b8 00 00 00 00           mov    $0x0,%eax
}
struct malloc_state {
  /* Serialize access.  */
  mutex_t mutex;
  /* Flags (formerly in max_fast).  */
  int flags;
#if THREAD_STATS
  /* Statistics for locking.  Only used if THREAD_STATS is defined.  */
  long stat_lock_direct, stat_lock_loop, stat_lock_wait;
#endif
  /* Fastbins */
  mfastbinptr      fastbinsY[NFASTBINS];
  /* Base of the topmost chunk -- not otherwise kept in a bin */
  mchunkptr        top;
  /* The remainder from the most recent split of a small request */
  mchunkptr        last_remainder;
  /* Normal bins packed as described above */
  mchunkptr        bins[NBINS * 2 - 2];
  /* Bitmap of bins */
  unsigned int     binmap[BINMAPSIZE];
  /* Linked list */
  struct malloc_state *next;
#ifdef PER_THREAD
  /* Linked list for free arenas.  */
  struct malloc_state *next_free;
#endif
  /* Memory allocated from the system in this arena.  */
  INTERNAL_SIZE_T system_mem;
  INTERNAL_SIZE_T max_system_mem;
};
struct malloc_state {
  /* Serialize access.  */
  mutex_t mutex;
  /* Flags (formerly in max_fast).  */
  int flags;
#if THREAD_STATS
  /* Statistics for locking.  Only used if THREAD_STATS is defined.  */
  long stat_lock_direct, stat_lock_loop, stat_lock_wait;
#endif
  /* Fastbins */
  mfastbinptr      fastbinsY[NFASTBINS];
  /* Base of the topmost chunk -- not otherwise kept in a bin */
  mchunkptr        top;
  /* The remainder from the most recent split of a small request */
  mchunkptr        last_remainder;
  /* Normal bins packed as described above */
  mchunkptr        bins[NBINS * 2 - 2];
  /* Bitmap of bins */
  unsigned int     binmap[BINMAPSIZE];
  /* Linked list */
  struct malloc_state *next;
#ifdef PER_THREAD
  /* Linked list for free arenas.  */
  struct malloc_state *next_free;
#endif
  /* Memory allocated from the system in this arena.  */
  INTERNAL_SIZE_T system_mem;
  INTERNAL_SIZE_T max_system_mem;
};
typedef struct _heap_info {
  mstate ar_ptr; /* Arena for this heap. */
  struct _heap_info *prev; /* Previous heap. */
  size_t size;   /* Current size in bytes. */
  size_t mprotect_size;    /* Size in bytes that has been mprotected
               PROT_READ|PROT_WRITE.  */
  /* Make sure the following data is properly aligned, particularly
     that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
     MALLOC_ALIGNMENT. */
  char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
typedef struct _heap_info {
  mstate ar_ptr; /* Arena for this heap. */
  struct _heap_info *prev; /* Previous heap. */
  size_t size;   /* Current size in bytes. */
  size_t mprotect_size;    /* Size in bytes that has been mprotected
               PROT_READ|PROT_WRITE.  */
  /* Make sure the following data is properly aligned, particularly
     that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
     MALLOC_ALIGNMENT. */
  char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
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;
  /* 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;
};
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;
  /* 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;
};
#define largebin_index_32(sz)                                                \
(((((unsigned long)(sz)) >>  6) <= 38)?  56 + (((unsigned long)(sz)) >>  6): \
 ((((unsigned long)(sz)) >>  9) <= 20)?  91 + (((unsigned long)(sz)) >>  9): \
 ((((unsigned long)(sz)) >> 12) <= 10)? 110 + (((unsigned long)(sz)) >> 12): \
 ((((unsigned long)(sz)) >> 15) <=  4)? 119 + (((unsigned long)(sz)) >> 15): \
 ((((unsigned long)(sz)) >> 18) <=  2)? 124 + (((unsigned long)(sz)) >> 18): \
                126)
#define largebin_index_32(sz)                                                \
(((((unsigned long)(sz)) >>  6) <= 38)?  56 + (((unsigned long)(sz)) >>  6): \
 ((((unsigned long)(sz)) >>  9) <= 20)?  91 + (((unsigned long)(sz)) >>  9): \
 ((((unsigned long)(sz)) >> 12) <= 10)? 110 + (((unsigned long)(sz)) >> 12): \
 ((((unsigned long)(sz)) >> 15) <=  4)? 119 + (((unsigned long)(sz)) >> 15): \
 ((((unsigned long)(sz)) >> 18) <=  2)? 124 + (((unsigned long)(sz)) >> 18): \
                126)
1
2
// 32位系统
*(char *)0x9d08008 = 0;

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 871
活跃值: (1730)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
综合您这篇文章,搜索了两天的资料,关于内存分布的问题终于懂了,感激不尽。
2022-4-4 14:58
0
雪    币: 871
活跃值: (1730)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
pukrquq 综合您这篇文章,搜索了两天的资料,关于内存分布的问题终于懂了,感激不尽。
在学house of mind,以前关于arena的各种问题在这两天得到了解答
2022-4-4 14:59
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
感谢分享!
2022-4-4 18:10
0
雪    币: 3344
活跃值: (10982)
能力值: ( LV9,RANK:240 )
在线值:
发帖
回帖
粉丝
5
pukrquq 在学house of mind,以前关于arena的各种问题在这两天得到了解答[em_13]
这将是载入史册的两天
2022-4-6 09:50
0
游客
登录 | 注册 方可回帖
返回
//