堆入门

0x01 前言

这几天都在看堆的相关内容,把这几天所看到的重要只是先总结下。

参考资料:ctf-wikiGlibc 内存管理

0x02 堆相关概念

堆是由程序员自行申请和释放的内存块,分别通过malloc和free函数实现,根据linux内存管理机制,堆其实是程序虚拟内存空间中一段线性连续区域,与栈相反,堆其实是由低地址向高地址增长,由于堆与栈的地址相差很远,所以基本不会出现交会的地方。

0x03 堆的结构

在程序的执行过程中,由malloc申请的内存称为chunk,这块内存在ptmalloc内部用malloc_chunk结构体表示。(单个chunk可以类比为数据结构中链表的单个结点)

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;

  /* 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;
};

 

字段解释:

prev_size:如果该chunk的物理相邻的前一地址chunk(两个指针的地址差值为前一chunk大小)是空闲的话,那该字段记录的是前一个chunk的大小(包括chunk头)。否则,该字段可以用来存储物理相邻的前一个chunk的数据。
size:该chunk的大小,大小必须是2*SIZE_SZ的整数倍。32位系统中,SIZE_SZ是4;64位系统中,SIZE_SZ是8。

  • size字段中存在三个标志位:A为0表示改chunk处于主分配区,为1则处于非主分配区;M表示改chunk从哪个内存区域获得的虚拟内存。1表示从mmap映射区域分配,否则是从heap区域分配;P表示前一个chunk是否空闲,若为空闲则置为0,否则置为1.

fd,bk。fd指向下一个(非物理相邻)空闲的chunk,bk指向上一个(非物理相邻)空闲的chunk。

fd_nextsize,bk_nextsize,只有chunk空闲的时候才使用,不过其用于较大的chunk。fd_nextsize指向前一个与当前chunk大小不同的第一个空闲块,不包含bin的头指针。bk_nextsize指向后一个与当前chunk大小不同的第一个空闲块,不包含bin的头指针。

0x04 堆的操作

主要关注的是unlink,用来将一个双向链表(只存储空闲的chunk)中的一个元素取出来,应用场景有malloc、free、malloc_consolidate、realloc。

堆溢出是指程序向某个堆块中写入的字节数超过了堆块本身可使用的字节数(注意是可使用的字节数位不是用户申请的字节数,因为堆管理器会对用户所申请的字节数进行调整,这也导致可利用的字节数都不小于用户申请的字节数),因而导致了数据溢出,并覆盖到物理相邻的高地址的下一个堆块。

0x05 堆溢出

堆溢出策略有:

  • 覆盖与其物理相邻的下一个chunk的内容。
  • 利用堆中机制(如unlink等)来实现任意地址写入(Write-Anything-Anywhere)或控制堆块中的内容等效果,从而来控制程序的执行流。

堆溢出中的几个重要步骤

  • 寻找堆分配函数;
  • 寻找危险函数(get、scanf、strcpy);
  • 确定填充长度:计算开始写入的地址与所要覆盖的地址之间的距离。

 

posted @ 2021-03-01 14:56  eur1ka  阅读(117)  评论(0)    收藏  举报