硬核二进制安全学习:Heap overflow堆溢出(壹)
Posted 鸿渐之翼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了硬核二进制安全学习:Heap overflow堆溢出(壹)相关的知识,希望对你有一定的参考价值。
精选文章:
硬核二进制安全学习FunctionPrologue and Function Epilogue基础函数调用机制
硬核二进制安全学习:Buffer Overflow(栈的缓冲区溢出&&Pwn技巧Return to Text)
知者行之始,行者知之成。
-——王阳明
堆溢出介绍:
堆溢出是指程序向某个堆块中写入的字节数超过了堆块本身可使用的字节数(之所以是可使用而不是用户申请的字节数,是因为堆管理器会对用户所申请的字节数进行调整,这也导致可利用的字节数都不小于用户申请的字节数),因而导致了数据溢出,并覆盖到物理相邻的高地址的下一个堆块。
程序向堆上写入数据。
写入的数据大小没有被良好地控制。
堆溢出是一种特定的缓冲区溢出(还有栈溢出, 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)或控制堆块中的内容等效果,从而来控制程序的执行流。
[CTFWiki]
1.堆的申请
在我们常见的操作中,堆是用malloc函数申请使用的。
Void *ptr=malloc(0x10)
系统会调用一些函数在内存中开辟一大片空间作为堆分配使用空间。
2.malloc函数在这一片堆分配使用空间中分配0x10大小的空间,将指向该空间的地址返回给ptr(余下的空间称为topchunk)
使用堆的程序演示案例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
void *ptr=malloc(0x10);
void *ptr1=malloc(0x90);
void *ptr2=malloc(0x800);
return 0;
}
我们在main处打下断点接着run起来。
使用vmmap查看内存,发现系统并未给我们分配空间。使用n命令继续调试,一直到第一次调用malloc函数。
我们看调用完成以后有什么变化,继续使用vmmap地址映射空间。
此时我们观察heap大小会发现他的大小比较大
细心的读者会观察到,我们申请的大小是0x10,但是这里的size是0x21,是什么造成的呢?
malloc会给我们一大块空间,这一部分叫做top chunk
堆的调用流程:
参考csdn博客专家@董哥的黑板报堆的调用流程、堆漏洞挖掘中的malloc_chunk结构体分析
第一步:
当应用程序“第一次”使用malloc函数申请动态内存时,glibc库会向内核申请一块非常大的动态内存,这块动态内存会比malloc申请的大小大很多。
brk/mmap系统调用:glibc库使用的是brk或者mmap系统调用来想内核申请内存空间的。至于两者有什么区别后面介绍。
第二步:
glibc申请到这块大的内存之后,根据malloc需要的大小,然后切割相应的大小给应用程序malloc函数使用。
第三步:
当应用层free之后,会将刚才使用到的动态内存返回给glibc,但是返回的内存不是返回给top chunk,而是由bins链管理(后面会介绍bins链)。
第四步:
当程序再次malloc时,会从刚才申请的很大的动态内存去取,不会再去向内核申请内存。
只有当第一次申请的动态内存使用完时,glibc才会再次通过brk/mmap系统调用向内核去要内存。
2.chunk讲解(堆的数据结构)
上面讲了堆的申请,接下来讲一下堆的数据结构。
malloc_chunk
我们称运行过程中被malloc分配的内存为一个chunk,这块内存在ptmalloc中用malloc_chunk结构体表示,当程序申请的chunk被free时,会被加入相应的空闲管理列表中。
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T mchunk_size; /* 当前chunk的大小 Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
}
参考:CSDN老码农zhuliptmalloc源码分析 - 内存组织单元malloc_chunk03
Chunk是一个统一的结构体声明,但是它在被申请与空闲的时候又有两种不同的状态。
使用中的Chunk
我们会发现Free Chunk的过程中多出了几个字段,在结构体中都是声明了的。为什么会这样呢?
知根知底:Chunk的结构体
我们需要了解每个字段的意义。
struct malloc_chunk{
INTERNAL_SIZE_T prev_size;
INTERNAL_SIZE_T size;
struct malloc_chunk*fd;
sturct malloc_chunk*bk;
struct malloc_chunk* fd_nextsize;
struct malloc_chunk* bk_nextsize;
}
1:prev_size:如果前一个chunk是空闲的,该域表示前一个chunk大小,如果前一个chunk不空闲,该域无意义。
2:size:当前chunk的大小,并且记录
3:FD:记录下一个,被free的chunk大小(used only if free)
4:BK:记录上一个被free的chunk(used only if free )
5.fd_nextsize和bk_nextsize,largebin使用,记录上/下一个被free chunk的size
mchunk_prev_size、mchunk_size
mchunk_prev_size:只有当该chunk的物理相邻的前一地址chunk是空闲的话,该字段在本chunk中才有用,用来记录前一个chunk 的大小 (包括chunk头)。否则,该字段为0是没有用的;但是当前一个chunk申请的大小大于前一个chunk的大小时,那么该字段可以用来给前一个chunk使用(这就是chunk的空间复用,后面文章介绍)。
mchunk_size:当前chunk的大小。
fd、bk
当前chunk处于分配状态时:从fd字段开始的是用户的数据。
当前chunk处于空闲时:
因为chunk处于空闲时,会被放到bin链中,所以fd和bk用于指向自己所在bin链中前后的空闲chunk
fd:指向前一个(非物理相邻)空闲的 chunk的指针(头指针)。
bk:指向后一个(非物理相邻)空闲的 chunk的指针。
通过fd和bk可以将空闲的chunk块加入到空闲的chunk块链表进行统一管理。
size of precious chunk是pre_size字段。
在size字段中,仔细的你会发现AMP并没有在结构体中定义
我们只需要知道P标志位作用是什么就好。
PREV_INUSE 记录前一个chunk是否被分配
Ptmolloc使用chunk实现内存管理,对chunk管理基于独特的边界标记法。
重要的是地址对齐。在不同平台下,每个chunk的最小大小,地址对齐方式是不同的ptmolloc依赖平台定义的size_t长度,对于32位平台,size_t大小是4字节,在64位平台,size_t长度可能为4字节,也可能为8字节。在Linux X86_64上size_t为8字节。
在64位平台上,一个使用中的chunk大小计算公式应该是:int_use_size=(用户请求大小+16-8) align to 8B
这里加16是因为需要存储prev_size和size,但是向chunk借了8B,所以减8。每分配一个chunk的overhead为8B.即SIZE_SZ的大小。 所以最小的chunk应该是0x20,这样size字段的低三位不会被使用,低三位就被用来当做flag位。
Chunk的复用技术
对于字段prev_size
字段prev_size记录什么信息呢?有两种情况:
1)如果前一个邻接的chunk块空闲,那么当前chunk块结构体内的prev_size字段记录的是前一个邻接chunk块的大小。这是由chunk当前指针获得前一个空闲chunk地址的依据。
宏prev_chunk§就是依赖这个假设实现的。
2)如果前一个邻接chunk在使用中,则当前chunk的prev_size的空间被前一个chunk借用中,其中的一个值是前一个chunk内存内容,对于当前chunk没有任何意义。
3.堆的释放
4.堆释放后的管理
5.bins讲解
6.堆的再次申请
参考
csdn@giantbranch bilibili@Freedom-zy的堆溢出视频总结
微信公众号:
知柯信息安全Zhicr Known Security
@知柯信安
作者:
@CSDN鸿渐之翼
@知柯信息安全 王驭停
@腾讯云 王驭停
责任编辑:
@知柯信息安全 白羽
以上是关于硬核二进制安全学习:Heap overflow堆溢出(壹)的主要内容,如果未能解决你的问题,请参考以下文章
CVE-2010-2746分析 Microsoft Windows - Common Control Library (Comctl32) Heap Overflow (MS10-081)