【二进制安全】堆漏洞:Double Free原理

参考:https://www.anquanke.com/post/id/241598
次要参考:https://xz.aliyun.com/t/6342

malloc_chunk 的源码如下:

struct malloc_chunk {
INTERNAL_SIZE_T prev_size;  /*前一个chunk的大小*/
INTERNAL_SIZE_T size;       /*当前chunk的大小*/
struct malloc_chunk * fd;   /*指向前一个释放的chunk*/
struct malloc_chunk * bk;   /*指向后一个释放的chunk*/
}

释放的chunk 会以单向链表的形式回收到fastbin 里面。
fastbin 是 LIFO 的数据结构,使用单向链表实现。

示例代码:

// https://www.anquanke.com/post/id/241598

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    puts("The goal of this is to show how we can edit a freed chunk using a Double Free bug.");
    puts("Editing freed chunks will allow us to overwrite heap metadata, which is crucial to a lot of heap attacks.");
    puts("However a bug to edit the heap metadata is often just one piece of the exploitation process.\n");

    printf("So we start off by allocating three chunks of memory. Let's also write some data to them.\n\n");

    char *ptr0, *ptr1, *ptr2;

    ptr0 = malloc(0x30);
    ptr1 = malloc(0x30);
    ptr2 = malloc(0x30);

    char *data0 = "00000000";
    char *data1 = "11111111";
    char *data2 = "22222222";

    memcpy(ptr0, data0, 0x8);
    memcpy(ptr1, data1, 0x8);   
    memcpy(ptr2, data2, 0x8);

    printf("Chunk0: @ %p\t contains: %s\n", ptr0, ptr0);
    printf("Chunk1: @ %p\t contains: %s\n", ptr1, ptr1);
    printf("Chunk2: @ %p\t contains: %s\n\n", ptr2, ptr2);

    printf("Now is where the bug comes in. We will free the same pointer twice (the first chunk pointed to by ptr0).\n");
    printf("In between the two frees, we will free a different pointer. This is because in several different versions of malloc, there is a double free check \n(however in libc-2.27 it will hit the tcache and this will be fine).\n");
    printf("It will check if the pointer being free is the same as the last chunk freed, and if it is the program will cease execution.\n");
    printf("To bypass this, we can just free something in between the two frees to the same pointer.\n\n");

    free(ptr0); //-----------------------> b1
    free(ptr1);
    free(ptr0); //-----------------------> b2

    printf("Next up we will allocate three new chunks of the same size that we freed, and write some data to them. This will give us the three chunks we freed.\n\n");

    char *ptr3, *ptr4, *ptr5;

    ptr3 = malloc(0x30); //--------------> b3
    ptr4 = malloc(0x30);
    ptr5 = malloc(0x30);

    memcpy(ptr3, data0, 0x8);
    memcpy(ptr4, data1, 0x8);   
    memcpy(ptr5, data2, 0x8);

    printf("Chunk3: @ %p\t contains: %s\n", ptr3, ptr3);  //-------------> b4
    printf("Chunk4: @ %p\t contains: %s\n", ptr4, ptr4);
    printf("Chunk5: @ %p\t contains: %s\n\n", ptr5, ptr5);

    printf("So you can see that we allocated the same pointer twice, as a result of freeing the same pointer twice (since malloc will reuse freed chunks of similar sizes for performance boosts).\n");
    printf("Now we can free one of the pointers to either Chunk 3 or 5 (ptr3 or ptr5), and clear out the pointer. We will still have a pointer remaining to the same memory chunk, which will now be freed.\n");
    printf("As a result we can use the double free to edit a freed chunk. Let's see it in action by freeing Chunk3 and setting the pointer equal to 0x0 (which is what's supposed to happen to prevent UAFs).\n\n");


    free(ptr3);
    ptr3 = 0x0;

    printf("Chunk3: @ %p\n", ptr3);
    printf("Chunk5: @ %p\n\n", ptr5);

    printf("So you can see that we have freed ptr3 (Chunk 3) and discarded it's pointer. However we still have a pointer to it. Using that we can edit the freed chunk.\n\n");

    char *data3 = "15935728";
    memcpy(ptr5, data3, 0x8);

    printf("Chunk5: @ %p\t contains: %s\n\n", ptr5, ptr5);

    printf("Just like that, we were able to use a double free to edit a free chunk!\n");

}

需要使用glibc 2.27编译。
Linux下更换glibc版本的方法:https://blog.csdn.net/weixin_44864859/article/details/107237134
使用glibc-all-in-one和patchelf对编译好的二进制文件直接替换其ld和libc的链接库地址,指向2.27版本的再次进行调试。

下面进行解释。

首先是申请三段内存,并填入数据:

ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);

char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";

memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);   
memcpy(ptr2, data2, 0x8);

然后依次释放ptr0、ptr1、ptr0
释放ptr0和ptr1之后的Tcachebin:
在这里插入图片描述

再释放ptr0之后的Tcachebin:
在这里插入图片描述
可以看到addr=0x555555758670这个chunk被放到了tcache 0x40 大小的链表上两次

之后再申请ptr3、ptr4、ptr5(同样大小)

    char *ptr3, *ptr4, *ptr5;

    ptr3 = malloc(0x30); //--------------> b3
    ptr4 = malloc(0x30);
    ptr5 = malloc(0x30);

    memcpy(ptr3, data0, 0x8);
    memcpy(ptr4, data1, 0x8);   
    memcpy(ptr5, data2, 0x8);
    
    printf("Chunk3: @ %p\t contains: %s\n", ptr3, ptr3);  //-------------> b4
    printf("Chunk4: @ %p\t contains: %s\n", ptr4, ptr4);
    printf("Chunk5: @ %p\t contains: %s\n\n", ptr5, ptr5);

在这里插入图片描述
可以看出来,ptr3和ptr5实际上是返回的同一块地址。
因此,在之后,即便我们释放ptr3,并且把ptr3的值指向0x0,我们还是可以操作这个已经被释放的chunk。

free(ptr3);
ptr3 = 0x0;

printf("Chunk3: @ %p\n", ptr3);
printf("Chunk5: @ %p\n\n", ptr5);

char *data3 = "15935728";
memcpy(ptr5, data3, 0x8);
printf("Chunk5: @ %p\t contains: %s\n\n", ptr5, ptr5);

在这里插入图片描述
总结就是2次free,2次malloc,一次free,最终得到可用的空闲块指针。

我们先不用管 修改已被释放的空闲块中的内容到底有什么用,
我们现在只需要知道Double free可以实现这个目标 就可以了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/62207.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无涯教程-Perl - binmode函数

描述 此函数设置在区分两者的操作系统上以二进制形式读取和写入FILEHANDLE的格式。非二进制文件的CR LF序列在输入时转换为LF,在LF时在输出时转换为CR LF。这对于使用两个字符分隔文本文件中的行的操作系统(MS-DOS)至关重要,但对使用单个字符的操作系统(Unix,Mac OS,QNX)没有影…

C#中XML文档与Treeview控件操作的数据同步

在前文《C#使用XML和Treeview结合实现复杂数据采集功能》中&#xff0c;使用Treeview展示了XML的数据&#xff0c;问题是如果在Treeview上进行了操作&#xff0c;怎样同步更改XML数据的内容呢&#xff1f; 这个问题看似简单&#xff0c;实现起来有一点小麻烦。 要实现的操作功能…

6.s081/6.1810(Fall 2022)Lab2: System calls

文章目录 前言其他篇章参考链接0. 前置准备1. System call tracing (moderate)1.1 简单分析1.2 Hint 11.3 Hint 21.4 Hint 31.5 Hint 41.6 Hint 51.7 测试 2. Sysinfo (moderate)2.1 声明2.2 实现2.2.1 框架2.2.2 用户态与内核态交互2.2.3 计算空闲内存的大小2.2.4 计算非UNUSE…

postgresql表膨胀处理之pgcompacttable部署及使用

环境&#xff1a; 1&#xff09;redhat-release&#xff1a;CentOS Linux release 7.6.1810 (Core) 2&#xff09;database version&#xff1a;postgresql 14.6 一、添加pgstattuple pgcompacttable工具使用过程中需要依赖pgstattuple&#xff0c;因此需先添加pgstattuple…

工业控制系统安全控制应用指南

工业控制系统安全控制应用 指南 工业控制系统&#xff08;ICS&#xff09;&#xff08;包括监控和数据采集系统&#xff08;SCADA&#xff09;、分布式控制系统(DCS)、可编程逻辑控制器(PLC)等产品&#xff09;在核设施、航空航天、先进制造、石油石化、油气管网、电力系统、交…

Qt应用开发(基础篇)——时间类 QDateTime、QDate、QTime

一、前言 时间类QDateTime、QDate、QTime、QTimeZone保存了Qt的时间、日期、时区信息&#xff0c;常用的时间类部件都会用到这些数据结构&#xff0c;常用概念有年、月、日、时、分、秒、毫秒和时区&#xff0c;时间和时区就关系到时间戳和UTC的概念。 UTC时间&#xff0c;又称…

K8s中的核心技术Helm

1.helm的引入 &#xff08;1&#xff09;编写yaml文件 &#xff08;2&#xff09;编写deployment文件 &#xff08;3&#xff09;编写service文件 &#xff08;4&#xff09;编写Ingress文件 2.helm的引入解决的问题&#xff1f; &#xff08;1&#xff09;使用helm可以把…

oracle 存储过程返回 结果集 table形式 (使用sys_refcursor 及程序包package 两种方式)

1.创建一个表Test用来测试. 1 CREATE TABLE "TEST" 2 ( "AAA" NUMBER(*,0), 3 "BBB" VARCHAR2(10 BYTE) 4 ) 2.向Test表中插入测试数据 1 insert into Test values(1,a); 2 insert into Test values(2,b); 3 insert into Test …

Arthas协助MQ消费性能优化

背景 项目中使用AWS的SQS消息队列进行异步处理&#xff0c;QA通过压测发现单机TPS在23左右&#xff0c;目标性能在500TPS&#xff0c;所以需要对消费逻辑进行优化&#xff0c;提升消费速度。 目标 消费TPS从23提升到500 优化流程 优化的思路是先分析定位性能瓶颈&#xff…

AD21 PCB设计的高级应用(九)3D PDF的输出

&#xff08;九&#xff09;3D PDF的输出 1.3D PDF的输出2.制作PCB 3D视频 1.3D PDF的输出 Altium Designer 19 带有 3D输出功能,能够直接将 PCB 的 3D效果输出到 PDF 中。 ’(1)打开带有 3D 模型的 PCB 文件,执行菜单栏中“文件”→“导出”→“PDF3D”命令&#xff0c;选择…

“我,在腾讯月薪5万,离职后才明白:人越努力,只会越平庸”

那天看瑞达利欧说&#xff0c;他今年已经60岁了&#xff0c;可以说是阅人无数&#xff0c;但没有一个成功人士天赋异禀。 真的如他所说吗&#xff1f; 那张一鸣呢&#xff1f; 字节做到这么大&#xff0c;赚了这么多钱&#xff0c;不靠天赋&#xff0c;靠的是什么&#xff1…

PoseFormer:基于视频的2D-to-3D单人姿态估计

3D Human Pose Estimation with Spatial and Temporal Transformers论文解析 摘要1. 简介2. Related Works2.1 2D-to-3D Lifting HPE2.2 GNNs in 3D HPE2.3 Vision Transformers 3. Method3.1 Temporal Transformer Baseline3.2 PoseFormer: Spatial-Temporal TransformerSpati…

Grafana集成prometheus(2.Grafana安装)

查找镜像 docker search grafana下载指定版本 docker pull grafana/grafana:10.0.1启动容器脚本 docker run -d -p 3000:3000 --namegrafana grafana/grafana:10.0.1查看是否启动 docker ps防火墙开启 检查防火墙3000端口是否开启 默认用户及密码 admin/admin 登录 ht…

Python实现GA遗传算法优化BP神经网络回归模型(BP神经网络回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

【0805作业】Linux中 AB终端通过两根有名管道进行通信聊天(半双工)(全双工)

作业一&#xff1a;打开两个终端&#xff0c;要求实现AB进程对话【两根管道】 打开两个终端&#xff0c;要求实现AB进程对话 A进程先发送一句话给B进程&#xff0c;B进程接收后打印B进程再回复一句话给A进程&#xff0c;A进程接收后打印重复1.2步骤&#xff0c;当收到quit后&am…

【Docker】DockerFile

目录 一、镜像原理 二、如何制作镜像 1、容器转镜像 2、DockerFile 三、DockerFile关键字​编辑 四、案例&#xff1a;部署SpringBoot项目 一、镜像原理 docker镜像是由一个特殊的文件系统叠加而成的&#xff0c;他的最低端是bootfs&#xff0c;并使用宿主机的bootfs&…

FPGA优质开源项目 – PCIE通信

本文介绍一个FPGA开源项目&#xff1a;PCIE通信。该工程围绕Vivado软件中提供的PCIE通信IP核XDMA IP建立。Xilinx提供了XDMA的开源驱动程序&#xff0c;可在Windows系统或者Linux系统下使用&#xff0c;因此采用XDMA IP进行PCIE通信是比较简单直接的。 本文主要介绍一下XDMA I…

继承(Inheritance)

Odoo的一个强大方面是它的模块化。模块专用于业务需求&#xff0c;但模块也可以相互交互。这对于扩展现有模块的功能非常有用。例如&#xff0c;在我们的房地产场景中&#xff0c;我们希望在常规用户视图中直接显示销售人员的财产列表。 在介绍特定的Odoo模块继承之前&#xf…

卸载本机已安装的node.js(v.16.13.0版本)

因为要用多版本的node&#xff0c;准备安装一个nvm管理&#xff0c;所以需要先卸载掉原来安装的v.16.13.0版本。 记录一下卸载过程 1、在系统设置-应用里卸载node 妈蛋这样卸载报错。。找了下根本没有这个路径 那就只能最简单的方法了&#xff0c;全部删掉 1、删除node的安装…

pygame贪吃蛇游戏

pygame贪吃蛇游戏 贪吃蛇游戏通过enter键启动&#xff0c;贪吃蛇通过WSAD进行上下左右移动&#xff0c;每次在游戏区域中随机生成一个食物&#xff0c;每次吃完食物后&#xff0c;蛇变长并且获得积分&#xff1b;按空格键暂停。 贪吃蛇 import random, sys, time, pygame from …