堆的入门

堆的系统调用

实例代码

/* sbrk and brk example */
#include 
#include 
#include 

int main()
{
        void *curr_brk, *tmp_brk = NULL;

        printf("Welcome to sbrk example:%d\n", getpid());

        /* sbrk(0) gives current program break location */
        tmp_brk = curr_brk = sbrk(0);
        printf("Program Break Location1:%p\n", curr_brk);
        getchar();

        /* brk(addr) increments/decrements program break location */
        brk(curr_brk+4096);

        curr_brk = sbrk(0);
        printf("Program break Location2:%p\n", curr_brk);
        getchar();

        brk(tmp_brk);

        curr_brk = sbrk(0);
        printf("Program Break Location3:%p\n", curr_brk);
        getchar();

        return 0;
}

编译运行之后, 在第一次调用brk之前


堆的入门_第1张图片

查看内存映射

堆的入门_第2张图片

堆的分析

这是每个chunk的布局

prev_size: 如果当前chunk的相邻前一chunk未被使用,prev_size为此前一chunk的大小
size: 当前chunk的大小。由于chunk大小是8的整数倍,所以此size的后3 bit被用于存储其他信息。我们需要记住的便是最低bit,即图中P的位置,用于指示前一chunk是否已被使用(PREV_INUSE)。

堆的入门_第3张图片

如果当前chunk未被使用, 则

fd: 下一个未被使用的chunk的地址
bk: 上一个未被使用的chunk的地址

所以我们可以通过当前的chunk去定位前一个chunk和后一个chunk
也就是拿当前chunk的地址减去前一个chunk的大小
或者拿当前chunk的地址加上当前chunk的大小

那些未被使用的chunks通过fd, bk组成了链表。事实上,malloc确实维护了一系列链表用于内存的分配和回收,这些链表被成为"bins"。

bin分为fastbin, unsorted bin, small bin, large bin。我们这里要研究的就是fastbin。

看了这篇文章之后觉得fastbin似乎也不是很难, 当然最难的地方在于如何构造payload浅析Linux堆溢出之fastbin

再好好分析一下malloc()这个神奇的函数

在glibc中,malloc_chunk以 2*sizeof(size_t)对齐,在32位系统中以8字节对齐,在64位系统中一般以16字节对齐。Malloc_chunk的定义如下:

堆的入门_第4张图片

既然malloc_chunk以2sizeof(size_t)对齐,那么malloc返回给用户的指针数值也是以2sizeof(size_t)对齐。

最小的chunk是多大呢

最小的chunk需要保证能放下prev_size、size、fd以及bk字段并保证对齐。在32位系统中,即16字节,在64位系统中,一般为32字节。在64位系统中也可能定义INTERNAL_SIZE_T也即size_t为4字节,这种情况下最小的chunk位24字节

fastbin中有10个bin
在32位系统中,fastbin里相邻的两个bin大小差距8个字节;在64位系统中,则是差距16个字节。

32位系统中,fastbin里chunk的大小范围从16到64;

怎么根据p=malloc(m)里的m来判断分配多大的chunk呢?

将申请的内存大小加上每个chunk的overhead,也就是chunk结构体里的size字段。然后对齐,就是需要分配的chunk的大小。

在实战之前先把wp好好看一下

接下来就是实战了

堆的入门_第5张图片
程序的大致流程
堆的入门_第6张图片
相关的字符串

貌似不能在32位平台上运行

脚本执行报错怎么办。。

堆的入门_第7张图片

这个错误貌似是struct这个包在pack的时候出的问题?


堆的入门_第8张图片

struct.pack

在stackoverflow上找到了这样一个例子, 说是把q改成Q就行了

堆的入门_第9张图片

和我想的相差不多, 就是那个libc_case的地址小于0x3a55ed

堆的入门_第10张图片

你可能感兴趣的:(堆的入门)