malloc源码分析(4)--free后mallocdouble free
文章目录
- 测试代码
- __libc_malloc
- __libc_malloc调用_int_malloc
- _int_malloc回到__libc_malloc
- 如何利用double free
- 测试代码
- 测试代码2
之前我们从源码的角度分析了如何初始化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;-0x23malloc(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就这样啦
malloc源码分析(4)--free后mallocdouble free相关推荐
- [Vue源码分析]谷歌翻译后,Vue双向数据绑定失效了?
前言: 最近运营反馈了一个问题:谷歌浏览器打开第三方储值平台,使用谷歌浏览器自带的翻译功能后,选择商品没有计算总额. 首先可以肯定的是这不是bug,这个平台已经兼容了13种语言,只是运营没有通过语言栏 ...
- Vue.js 源码分析(五) 基础篇 方法 methods属性详解
methods中定义了Vue实例的方法,官网是这样介绍的: 例如:: <!DOCTYPE html> <html lang="en"> <head&g ...
- glibc-2.23学习笔记(一)—— malloc部分源码分析
glibc-2.23学习笔记(一)-- malloc部分源码分析 搭建Glibc源码调试环境 1.下载并解压glibc源码 2.配置gdb 3.编译测试程序 第一次调用 源码分析 __libc_mal ...
- F2FS源码分析-5.2 [数据恢复流程] 后滚恢复和Checkpoint的作用与实现
F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 二.文件数据的存储以及读写 三.文件与目录的创建以及删除(未完成) 四.垃圾回收机制 五.数据恢复机制 数据恢复的原理以及方式 后滚恢 ...
- 升级SpringCloud到Hoxton.SR3后使用Fegin出现jackson反序列化失败,源码分析,原因lombok版本升级
关键词 Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct insta ...
- 【SemiDrive源码分析】【X9芯片启动流程】27 - AP1 Android Preloader启动流程分析(加载atf、tos、bootloader镜像后进入BL31环境)
[SemiDrive源码分析][X9芯片启动流程]27 - AP1 Android Preloader启动流程分析(加载atf.tos.bootloader镜像后进入BL31环境) 一.Android ...
- ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析
文章目录 内存查看 内存控制 内存控制源码分析 通过gperftools接口获取osd进程实际内存 动态设置cache大小 动态调整cache比例 trim释放内存 本文通过对ceph-osd内存查看 ...
- Python3.5源码分析-内存管理
Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的内存管理概述 python提供了对内存的垃圾收 ...
- linux nDPI 协议检测 源码分析
关于nDPI的基本功能就不在这介绍了,有兴趣了解的读者可以阅读官方的快速入门指南:https://github.com/ntop/nDPI/blob/dev/doc/nDPI_QuickStartGu ...
最新文章
- linux 下串口编程VTIME和VMIN的设置
- [递归][DP]n条直线最多分平面为几部分?
- 笔记-项目质量管理-质量保证和质量控制
- Excel 公式(细节若干)
- 9、java中的异常处理机制
- 局域网聊天软件的设计思路
- 老旗舰华为能用上鸿蒙吗,荣耀手机能升级鸿蒙吗?五款旗舰优先,老荣耀机主或有惊喜...
- Leetcode 338.比特位计数
- 股票---- 资金在线-个股资金流向与大单分析系统
- PCB测试流程分析介绍
- C#实现Omron欧姆龙PLC的Fins Tcp协议
- instant-ngp
- ICCV 2021 | Transformer结合自监督学习!Facebook开源DINO
- google身份验证器
- C++STL库:String介绍
- excel对同一个单元格中的内容去重
- C#二维码条码生成存入文本加缓存
- 广东高中生多少人_广东省高中生100米短跑记录是多少?谢谢
- 流氓软件卸不干净?这6款超强软件卸载神器专治各种流氓软件!
- 【热文】 为什么程序员痴迷于猫?
热门文章
- pointofix 全局快捷键_pointofix输入文字怎么调整大小
- 广域网技术之HDLC和ppp原理与配置
- Linux系统学习——ubuntu16.04开机蓝屏问题
- 相机删除自动闪光灯。桌面删除搜索框(google)等。预置应用可卸载。
- WordPress 限制不同用户角色可上传的文件类型及大小
- 自动化构建工具Maven
- 安川机器人程序还原_安川机器人报错代码:功能概要和程序数据简易修复方法...
- 【视频】国产女声电子摇滚/电子核| 真军乐队True Army - 放课后少女| 混音母带处理 By JeromeAlanChan(MZD Studios)
- 苹果Mac系统如何安装pip命令?
- 大学计算机专业绩点在3.5算好,大学平均学分绩点3.5算什么水平 绩点不够怎么办...