堆&块

  • 0x01 基础知识——Chunk
  • 0x02 基础知识——Heap
  • 0x03 堆的基本操作
  • 0x04 堆相关的函数
    • 1>malloc
    • 2>free
  • 0x05 堆溢出
  • 0x06 堆溢出中比较重要的几个步骤
    • ·寻找堆分配函数
      • realloc malloc calloc
    • ·寻找危险函数
    • ·确定填充长度
  • 0x07 Fast bin
  • 0x08 Unsort bin
    • 注意点
  • Fastbin attack--blind
  • FILE结构
  • double free--pwn3_text
  • Unlink
    • unlink--babynode

0x01 基础知识——Chunk

分配过的chunk

  • 32位机,8字节对齐,64位机,16字节对齐
  • 位P指明前一个chunk的状态(空闲为0,使用为1)
  • prev_size表示前一个chunk的大小
    当前chunk释放时,可用于定位前一个chunk,并将两个chunk合并为一个更大的chunk
    当P为1时,prev_size无意义,该区域(4B)可被前一个chunk使用

在glibc malloc中将整个堆内存空间分成了连续的、大小不一的chunk,即对于堆内存管理而言chunk就是最小操作单位。

Chunk总共分为4类:
1)allocated chunk; 2)free chunk; 3)top chunk; 4)Last remainder chunk。
从本质上来说,所有类型的chunk都是内存中一块连续的区域,只是通过该区域中特定位置的某些标识符加以区分。为了简便,我们先将这4类chunk简化为2类:allocated chunk以及free chunk,前者表示已经分配给用户使用的chunk,后者表示未使用的chunk。

众所周知,无论是何种堆内存管理器,其完成的核心目的都是能够高效地分配和回收内存块(chunk)。因此,它需要设计好相关算法以及相应的数据结构,而数据结构往往是根据算法的需要加以改变的。

0x02 基础知识——Heap

在程序运行过程中,堆可以提供动态分配的内存允许程序申请大小未知的内存。堆其实就是程序虚拟地址空间的一块连续的线性区域,它由低地址向高地址方向增长。我们一般称管理堆的那部分程序为堆管理器。

堆管理器处于用户程序与内核中间,主要做以下工作

响应用户的申请内存请求,向操作系统申请内存,然后将其返回给用户程序。同时,为了保持内存管理的高效性,内核一般都会预先分配很大的一块连续的内存,然后让堆管理器通过某种算法管理这块内存。只有当出现了堆空间不足的情况,堆管理器才会再次与操作系统进行交互。
管理用户所释放的内存。一般来说,用户释放的内存并不是直接返还给操作系统的,而是由堆管理器进行管理。这些释放的内存可以来响应用户新申请的内存的请求。

0x03 堆的基本操作

1>堆的分配,回收,堆分配背后的系统调用
2>堆目前多线程支持

0x04 堆相关的函数

1>malloc

在 glibc 的 malloc.h 中,malloc 的说明如下

/*malloc(size_t n)Returns a pointer to a newly allocated chunk of at least n bytes, or nullif no space is available. Additionally, on failure, errno isset to ENOMEM on ANSI C systems.If n is zero, malloc returns a minumum-sized chunk. (在大多数32位系统中,最小大小为16字节,在64位上为24字节或32字节。) On most systems, size_t is an unsigned type, so callswith negative arguments are interpreted as requests for huge amountsof space, which will often fail. The maximum supported value of ndiffers across systems, but is in all cases less than the maximumrepresentable value of a size_t.+
*/

可以看出,malloc 函数返回对应大小字节的内存块的指针。此外,该函数还对一些异常情况进行了处理

当 n=0 时,返回当前系统允许的堆的最小内存块。
当 n 为负数时,由于在大多数系统上,size_t 是无符号数(这一点非常重要),所以程序就会申请很大的内存空间,但通常来说都会失败,因为系统没有那么多的内存可以分配。

2>free

在 glibc 的 malloc.h 中,free 的说明如下

/*free(void* p)Releases the chunk of memory pointed to by p, that had been previouslyallocated using malloc or a related routine such as realloc.It has no effect if p is null. It can have arbitrary (i.e., bad!)effects if p has already been freed.Unless disabled (using mallopt), freeing very large spaces willwhen possible, automatically trigger operations that giveback unused memory to the system, thus reducing program footprint.
*/

可以看出,free 函数会释放由 p 所指向的内存块。这个内存块有可能是通过 malloc 函数得到的,也有可能是通过相关的函数 realloc 得到的。

此外,该函数也同样对异常情况进行了处理
·当 p 为空指针时,函数不执行任何操作。
·当 p 已经被释放之后,再次释放会出现乱七八糟的效果,这其实就是 double free。
除了被禁用 (mallopt) 的情况下,当释放很大的内存空间时,程序会将这些内存空间还给系统,以便于减小程序所使用的内存空间。

0x05 堆溢出

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

不难发现,堆溢出漏洞发生的基本前提是

  1. 程序向堆上写入数据。
  2. 写入的数据大小没有被良好地控制。

对于攻击者来说,堆溢出漏洞轻则可以使得程序崩溃,重则可以使得攻击者控制程序执行流程。

堆溢出是一种特定的缓冲区溢出(还有栈溢出, bss 段溢出等)。但是其与栈溢出所不同的是,堆上并不存在返回地址等可以让攻击者直接控制执行流程的数据,因此我们一般无法直接通过堆溢出来控制 EIP 。

一般来说,我们利用堆溢出的策略是

1.覆盖与其物理相邻的下一个 chunk 的内容。

  • prev_size
  • size,主要有三个比特位,以及该堆块真正的大小。
    • NON_MAIN_ARENA
    • IS_MAPPED
    • PREV_INUSE
    • the True chunk size
    • chunk content,从而改变程序固有的执行流。

2.利用堆中的机制(如 unlink 等 )来实现任意地址写入( Write-Anything-Anywhere)或控制堆块中的内容等效果,从而来控制程序的执行流。

0x06 堆溢出中比较重要的几个步骤

·寻找堆分配函数

realloc malloc calloc

通常来说堆是通过调用 glibc 函数 malloc 进行分配的,在某些情况下会使用 calloc 分配。calloc 与 malloc 的区别是 calloc 在分配后会自动进行清空,这对于某些信息泄露漏洞的利用来说是致命的。

calloc(0x20);
//等同于
ptr=malloc(0x20);
memset(ptr,0,0x20);

除此之外,还有一种分配是经由 realloc 进行的,realloc 函数可以身兼 malloc 和 free 两个函数的功能。
realloc 的操作并不是像字面意义上那么简单,其内部会根据不同的情况进行不同操作
当 realloc(ptr,size) 的 size 不等于 ptr 的 size 时
如果申请 size > 原来 size
如果 chunk 与 top chunk 相邻,直接扩展这个 chunk 到新 size 大小
如果 chunk 与 top chunk 不相邻,相当于 free(ptr),malloc(new_size)
如果申请 size < 原来 size
如果相差不足以容得下一个最小 chunk(64 位下 32 个字节,32 位下 16 个字节),则保持不变
如果相差可以容得下一个最小 chunk,则切割原 chunk 为两部分,free 掉后一部分
当 realloc(ptr,size) 的 size 等于 0 时,相当于 free(ptr)
当 realloc(ptr,size) 的 size 等于 ptr 的 size,不进行任何操作

·寻找危险函数

通过寻找危险函数,我们快速确定程序是否可能有堆溢出,以及有的话,堆溢出的位置在哪里。

常见的危险函数如下

输入

  • gets,直接读取一行,忽略 ‘\x00’
  • scanf
  • vscanf

输出

  • sprintf

字符串

  • strcpy,字符串复制,遇到 ‘\x00’ 停止
  • strcat,字符串拼接,遇到 ‘\x00’ 停止
  • bcopy

·确定填充长度

这一部分主要是计算我们开始写入的地址与我们所要覆盖的地址之间的距离。 一个常见的误区是 malloc 的参数等于实际分配堆块的大小,但是事实上 ptmalloc 分配出来的大小是对齐的。这个长度一般是字长的 2 倍,比如 32 位系统是 8 个字节,64 位系统是 16 个字节。但是对于不大于 2 倍字长的请求,malloc 会直接返回 2 倍字长的块也就是最小 chunk,比如 64 位系统执行malloc(0)会返回用户区域为 16 字节的块。

0x07 Fast bin


在chunk被free的时候如果大小小于0x80会被放入fast bin
需要注意的是这里的prive_inuse位不会置0
可以在这里泄露出来heap的地址。

0x08 Unsort bin


在chunk合并之后大于0x80或者是大于0x80的chunk被释放之后会放入unsort bin
这里是双向链表连接
其中main_arena和libc_base之间的偏移是固定的,可以用来leak libc_base

注意点

定义的read函数

  • 可以输入比size多一位。
  • 可以输入size之后又加上\x00

free掉chunk之后指针是否清零
是否存在堆溢出

Fastbin attack–blind


注意在申请空间时有一个size验证。

malloc(20) malloc(20)
free(1) free(2)
edit(2,my_addr)
my_addr=0x6020xx
my_addr_size=0x70,1
size需要满足
0x80以内
prive_inuse为1

size一般是偏移的

FILE结构

struct _IO_FILE_plus
{_IO_FILE    file;IO_jump_t   *vtable;
}

puts函数最终调用的其实是这里的xsputn函数。伪造IO_FILE_plus结构把xsgetn设置为想要的值可以劫持执行流。

详细参考https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/introduction/

void * vtablt[] = {1 NULL, // "extra word"2 NULL, // DUMMY3 exit, // finish4 NULL, // overflow5 NULL, // underflow6 NULL, // uflow7 NULL, // pbackfail8 NULL, // xsputn  #printf9 NULL, // xsgetnprint *(struct _IO_FILE_plus*)0x6020a0

double free–pwn3_text

所谓的free其实就是数据结构里面的头插。就是一些指针的变化
达到左图在经过三次malloc再次malloc就能申请到想要的空间
限制:需要一个合适的size

Unlink


unlink的发生:

  1. glibc 判断这个块是 small chunk。
  2. 判断前向合并,发现前一个 chunk 处于使用状态,不需要前向合并。
  3. 判断后向合并,发现后一个 chunk 处于空闲状态,需要合并。
    继而对 nextchunk 采取 unlink 操作。

unlink(p)

unlink–babynode

填充:fd=p-12 bk=p-8 next_prevsize=size … chunk2_privesize=size chunk2size=size2 这里的size全部为chunk的实际大小
结果:*p=p-12

堆Heap块Chunk相关推荐

  1. 一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc

    大家好,我是无际. 有一周没水文了,俗话说夜路走多了难免遇到鬼. 最近就被一个热心网友喷了. 说我的文章没啥营养,所以今天来一篇烧脑的. 哈哈,开个玩笑,不要脸就没人能把我绑架. 主要是最近研发第二代 ...

  2. java中堆栈(stack)和堆(heap)

    http://www.ej38.com/showinfo/java-172156.html 堆栈是一种先进后出的数据结构,只能在一端进行输入或输出数据的操作  Stack类在java.util包中 向 ...

  3. bss段,data段、text段、堆heap和栈stack

    bss段,data段.text段.堆heap和栈stack bss段 data段 text段 堆(heap) 栈(stack) 例子 在C的学习中,你总避免不了对各类数据的存储区域学习归纳总结,简单的 ...

  4. JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )(转发)

    这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有 比较大的帮助. 废话不想讲了.入主题: 先了解具体的概念: JAVA的JVM的内存可分为3个区: ...

  5. 栈(stack)和堆(heap)

    栈(stack)和堆(heap), Java程序在运行时都要开辟空间,任何软件在运行时都要在内存中开辟空间,Java虚拟机运行时也是要开辟空间的.JVM运行时在内存中开辟一片内存区域,启动时在自己的内 ...

  6. (深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack)(C/C++存储类型总结)(内存管理)

    文章目录 bss段 data段 text段 堆(heap) 栈(stack) 一个程序本质上都是由 bss段.data段.text段三个组成的. 存储类型总结 bss段 bss段(bss segmen ...

  7. codeforces 贪心+优先队列_算法与数据结构基础 - 堆(Heap)和优先级队列(Priority Queue)...

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值:

  8. Java里的堆(heap)栈(stack)和方法区(method)

    http://imiduo.iteye.com/blog/616310 Java里的堆(heap)栈(stack)和方法区(method)  <一> 基础数据类型直接在栈空间分配, 方法的 ...

  9. SQL Server 堆heap 非聚集索引 Nonclustered index 行号键查找RID loopup结合执行计划过程详解

    SQL Server 堆型数据与执行计划使用案例 索引的相关术语 1 堆(Heap)是一种没有指定排序的数据结构,通俗的理解堆就像是按照顺序排放的杂物.在数据库里也即是对应没有聚集索引. 2 聚集索引 ...

  10. JVM之堆Heap参数调优入门

    JVM之堆Heap参数调优入门 目录: JVM体系结构概览 JVM之堆Heap参数调优入门 2.1 java7和 java8堆结构图 2.2 堆内存调优简介 1. JVM体系结构概览 2. JVM之堆 ...

最新文章

  1. R语言使用caret包的findCorrelation函数批量删除相关性冗余特征、实现特征筛选(feature selection)、剔除高相关的变量
  2. tf.keras.losses.BinaryCrossentropy 损失函数 示例
  3. mysql中union all的order by问题
  4. NOI2020 前最后的日子
  5. CMake基础 第8节 包含第三方库
  6. viewpager+fragment学习笔记
  7. 在VS2003下把一个DataTable Update 到数据库
  8. ArrayList的容量
  9. C#通过对象属性名修改值
  10. matlab绘图把横坐标修改为自己想的标签 并保存对应图的代码以便下次修改
  11. 第二十次CCF CSP认证考试经验
  12. 条令考试小程序辅助器_微信小程序条令考试刷分 微信小程序答题刷分软件
  13. 数学模型学习——图与网络
  14. 【学习笔记】数据结构-单链表
  15. 武汉工程大学信息与计算科学专业面向对象程序设计课程设计题
  16. 最详细的Java程序打包成“可安装使用”的桌面应用
  17. 力扣 714. 买卖股票的最佳时机含手续费
  18. 源码网站合集[细选过的][转贴]
  19. vivado综合出现“PID not specified”问题的参考解决方法
  20. MyBatis快速入门(10)全局配置--settings

热门文章

  1. [4G+5G专题-137]: 终端 - 射频前端(滤波器、功率放大器)详解
  2. html 嵌入页面,html5页面嵌入
  3. UML学习_1_模型
  4. salve mysql_mysql 同步实现, master-salve
  5. 【Unity】项目源码——2D横版过关类游戏《A_Standard_Runner》
  6. android机器人方向,Android横版过关类游戏推荐《机器人大挑战》
  7. JavaWeb - 小米商城:用户注册
  8. 技术负责人 vs产品负责人_产品前的人
  9. 怎么还原计算机系统还原,怎么还原以前版本的windows?Win7/Win10系统还原方法
  10. 7款英文语法检查工具推荐