malloc源码分析(4)--free后malloc&&double free


之前我们从源码的角度分析了如何初始化heap并且从top chunk分配出了第一个块fast bin,那么这次我们结合free fastchunk来分配相同size的fastbin

测试代码

#include<malloc.h>
int main(){
        void *p=malloc(0x18);
        *(int *)(p+8)=0xdeadbaaf;
        free(p);
        p=NULL;
        void *p1=malloc(0x18);
        return 0;
}

其实代码很简单,我们主要就是跟踪一下从freechunk里面malloc出来究竟有哪些check
大概运行到这里吧,然后我们跟进
在这里插入图片描述

__libc_malloc

我们首先看看现在的main_arena
在这里插入图片描述
可以看到对应大小有一个空闲块,并且flags是0代表有fastchunks
同时__malloc_hook为NULL,只要我们不设置,初始化后他就一直是NULL.所以我们这里不会去调用
在这里插入图片描述
获取ar_ptr并且进入_int_malloc
在这里插入图片描述

__libc_malloc调用_int_malloc

在这里插入图片描述
这个函数两个作用

  • 如果需要的size太大,就返回0
  • 正常请求就转化成具体需要的size(需要考虑header)

在这里插入图片描述
那么多大算太大呢
在这里插入图片描述
internal_size_t也就是8,minsize也就是0x20,所以就是(unsigned)-0x200
在这里插入图片描述
具体为什么这个值我也不清楚,但一般情况下肯定都是满足的
大部分都类似于之前提到的malloc
这里因为我们大小确实满足,所以会进来,之前由于没有初始化所以进不来
在这里插入图片描述
非常熟悉的操作,寻找到对应的fastbiny的地址
在这里插入图片描述
这里我们肯定会执行一次因为do while,如果victim==NULL代表里面确实没有就跳出,然后while的成立的条件其实是写入失败,因为写入成功最后会返回victim,那么就相当于是false,所以一般我们也会成功,这里写while可能会涉及多线程,但单线程的时候如果有free chunk就相当于我把victim->fd写到fastbiny里面,就相当于拿出来一个
在这里插入图片描述
这里其实是检查fastbiny的大小是否和我们需要的size匹配,一般来说是匹配的,如果失败说明这个fastbin链表被修改了
在这里插入图片描述
额这个是源码里面的
在这里插入图片描述
结果我直接跳到这里来了
在这里插入图片描述
感觉是这个优化的有点奇怪,我单步执行一下,好像执行了void *p=chunk2mem(victim);
然后这个allo_perturb和free_perturb都是一样的,都不会执行
在这里插入图片描述

那么就回到了__libc_malloc

_int_malloc回到__libc_malloc

这里我们已经获取到了要分配的区域,所以不会进去
在这里插入图片描述
解锁
在这里插入图片描述
简单检查一下
在这里插入图片描述
就回来了
在这里插入图片描述
可以看到我们这里malloc的就是刚刚释放的,并且里面还有数据
所以一般提倡malloc后立马memset清空

如何利用double free

测试代码

#include<malloc.h>
int main(){
        void *p=malloc(0x18);
        void *p1=malloc(0x18);
        free(p);
        free(p1);
        free(p);
        void *p2=malloc(0x18);
        *(size_t*)p2=0xdeadbaff;
        return 0;
}

回到我们上次提到的double free,为了避免free check double free的情况,我们中间需要随便free掉一个heap,然后就形成了这样环形的情况
在这里插入图片描述
我们首先malloc一个
大家知道由于malloc不会清空heap内容,所以我们现在fastbiny保存的就应该是0x405020,然后这个时候我们修改一下fd的指针
在这里插入图片描述
可以看到变成这个样子了
在这里插入图片描述
所以我们如果再malloc三次的话,第三次就应该可以malloc到我们需要任意写的地方
为什么可以这样呢?
其实我们通过刚才简单的free malloc可以看出,我们fastbiny他是以0作为结束标准的,他不会去记录你到底进去了几个出来了几个,只要里面不是0,我认为就还有,还可以分配,所以当我们修改了链之后,他就会乖乖去跟着fd去遍历
而一般来说fd都是可以控制的,它属于我们的data区域

那么我们接着攻击,看可以可以malloc三次

测试代码2

因为中间两次的malloc其实是没什么用的,所以我就没保留指针

#include<malloc.h>
int main(){
        void *p=malloc(0x18);
        void *p1=malloc(0x18);
        free(p);
        free(p1);
        free(p);
        void *p2=malloc(0x18);
        *(size_t*)p2=0xdeadbaff;
        malloc(0x18);
        malloc(0x18);
        void *p3=malloc(0x18);
        return 0;
}

如愿以偿的修改成了deadbaff,我们执行一下
在这里插入图片描述
报错,奥段错误,确实,这个地方不一定有内容,我们指向别的吧
在这里插入图片描述
这里其实我们要获取__malloc_hook就要知道libc加载地址,但这里我遇到了点问题
dlopen是可以用来获取so加载地址,类似于windows下的GetProcAddr,但这里如果我用的不是系统自身版本的libc就会报错,暂时还不知道为什么
这里我们先写死吧

这里可以看到我具体的加载地址
在这里插入图片描述
那么对于我就是这样的

#include<malloc.h>
int main(){
        void *p=malloc(0x18);
        void *p1=malloc(0x18);
        free(p);
        free(p1);
        free(p);
        void *p2=malloc(0x18);
        *(size_t*)p2=0x7ffff7fcbb10;
        malloc(0x18);
        malloc(0x18);
        void *p3=malloc(0x18);
        return 0;
}

我们执行到这里可以看到,bins已经被修改到malloc_hook,也就是说我们malloc的第三个就在malloc_hook附近

在这里插入图片描述
卧槽,报错了??,我们跟踪一下
在这里插入图片描述
一直到_int_malloc都没什么问题
在这里插入图片描述
问题还是出现在了这里
在这里插入图片描述
由于victim就是我们当前将要分配的区域,他会检查这个大小是否匹配,如果不匹配就不分配
所以我们先要绕过这个大小检查
这个也是fastbin attack里面需要特别构造的一点,就是大小匹配
注意到malloc上面这一块,有一个比较特殊的偏移
在这里插入图片描述
可以看到有个7f的区域
在这里插入图片描述
那么我们再去看看chunksize的实现

#define chunksize(p)         ((p)->size & ~(SIZE_BITS))

在这里插入图片描述
size_bits其实就是4+2+1=7
所以相当于就是
在这里插入图片描述
fastbin_index的实现呢
在这里插入图片描述
左移4位减去2,刚好就是5,而5对应的大小就是0x70,所以我们要保证最后分配的块实际大小是0x70
为什么这里0x78也可以呢,还记得我说idx是/16嘛,所以你多一点没关系,毕竟我是整除,其实我个人觉得如果毕竟chunksize(victim)==size最好
因为这种不严格的判断才导致我们可以利用0x7f来绕过,而且在实际中,一般块的大小也只会收到1,2,4标记位的影响,我们chunksize已经去掉了,不知道这里为什么还要多此一举反而可以让我们绕过

接下来就是修改一下payload,因为要保证获取0x70

#include<malloc.h>
int main(){
        void *p=malloc(0x68);
        void *p1=malloc(0x68);
        free(p);
        free(p1);
        free(p);
        void *p2=malloc(0x68);
        *(size_t*)p2=0x7ffff7fcbb10;-0x23
        malloc(0x68);
        malloc(0x68);
        void *p3=malloc(0x68);
        return 0;
}

首先运行一下,可以看到成功分配
在这里插入图片描述
我们再调试一下
这个就是__malloc_hook上面的那个地址
在这里插入图片描述
bytes是我们需要的,nb是实际的,idx就是实际需要的fastbin对应的索引
在这里插入图片描述
当前的fastbiny地址和空闲块地址

在这里插入图片描述
在这里插入图片描述
victim就是我们这里的pp
这里因为刚好符合我们的涉及就准备返回
在这里插入图片描述
回到主函数,确实也被修改了
在这里插入图片描述
这才是完整的malloc_hook对应的heap
在这里插入图片描述
我们找找malloc_hook的偏移0x23-0x10=0x13
在这里插入图片描述
这里我们测试就写个deadbaaf,实际上需要写一个one_gadget
在这里插入图片描述
所以总的大概double free就这样啦

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值