【二进制安全】堆漏洞: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); //-----------------------> b1free(ptr1);free(ptr0); //-----------------------> b2printf("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); //--------------> b3ptr4 = 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); //-------------> b4printf("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); //--------------> b3ptr4 = 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); //-------------> b4printf("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可以实现这个目标 就可以了
相关文章:

【二进制安全】堆漏洞: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的…...
python之open,打开文件时,遇到解码错误处理方式
在Python中,当我们打开一个文件时,我们可以指定文件的编码方式。如果文件的编码方式与我们指定的编码方式不同,那么就会出现解码错误。为了避免这种情况,我们可以使用errors参数来指定如何处理解码错误。 errors参数用于指定解码…...
STM32 CAN通信-CubeMX环境下CAN通信程序的编程与调试经验
文章目录 STM32 CAN通信-CubeMX环境下CAN通信程序的编程 STM32 CAN通信-CubeMX环境下CAN通信程序的编程 STM32F103ZE芯片 CAN通信测试代码: #include "main.h" #include "can.h"CAN_HandleTypeDef hcan1;void SystemClock_Config(void);int ma…...

windows创建不同大小的文件命令
打开命令窗口(windowsR输入cmd打开) 输入:fsutil file createnew C:\Users\Desktop\fileTran\10M.txt 10240000,创建10M大小的文件。 文件若存在需要先删除。...

Attention Is All You Need
Attention Is All You Need 摘要1. 简介2. Background3. 模型架构3.1 编码器和解码器堆栈3.2 Attention3.2.1 缩放的点积注意力(Scaled Dot-Product Attention)3.2.2 Multi-Head Attention3.2.3 Attention 在我们模型中的应用 3.3 Position-wise前馈网络…...

手写线程池 - C++版 - 笔记总结
1.线程池原理 创建一个线程,实现很方便。 缺点:若并发的线程数量很多,并且每个线程都是执行一个时间较短的任务就结束了。 由于频繁的创建线程和销毁线程需要时间,这样的频繁创建线程会大大降低 系统的效率。 2.思考 …...
PHP 容器化引发线上 502 错误状态码的修复
最后更新时间 2023-01-24. 背景 笔者所在公司技术栈为 Golang PHP,目前部分项目已经逐步转 Go 语言重构,部分 PHP 业务短时间无法用 Go 重写。 相比 Go 语言,互联网公司常见的 Nginx PHP-FPM 模式,经常会出现性能问题—— 特…...
QT中UDP之UDPsocket通讯
目录 UDP: 举例: 服务器端: 客户端: 使用示例: 错误例子并且改正: UDP: (User Datagram Protocol即用户数据报协议)是一个轻量级的,不可靠的࿰…...

【C语言】10-三大结构之循环结构-1
1. 引言 在日常生活中经常会遇到需要重复处理的问题,例如 统计全班 50 个同学平均成绩的程序求 30 个整数之和检查一个班级的同学程序是否及格要处理以上问题,最原始的方法是分别编写若干个相同或相似的语句或者程序段进行处理 例如:处理 50 个同学的平均成绩可以先计算一个…...

Windows下RocketMQ的启动
下载地址:下载 | RocketMQ 解压后 一、修改runbroker.cmd 修改 bin目录下的runbroker.cmd set "JAVA_OPT%JAVA_OPT% -server -Xms2g -Xmx2g" set "JAVA_OPT%JAVA_OPT% -XX:MaxDirectMemorySize15g" set "JAVA_OPT%JAVA_OPT% -cp %CLASSP…...
linux内核升级 docker+k8s更新显卡驱动
官方驱动 | NVIDIA在此链接下载对应的显卡驱动 # 卸载可能存在的旧版本nvidia驱动(如果没有安装过可跳过,建议执行) sudo apt-get remove --purge nvidia* # 安装驱动需要的依赖 sudo apt-get install dkms build-essential linux-headers-generic sudo vim /etc/mo…...
express学习笔记2 - 三大件概念
中间件 中间件是一个函数,在请求和响应周期中被顺序调用(WARNING:提示:中间件需要在响应结束前被调用) 路由 应用如何响应请求的一种规则 响应 / 路径的 get 请求: app.get(/, function(req, res) {res…...

Steam搬砖蓝海项目
这个项目早在很久之前就已经存在,并且一直非常稳定。如果你玩过一些游戏,你一定知道Steam是什么平台。Steam平台是全球最大的综合性数字发行平台之一,玩家可以在该平台购买、下载、讨论、上传和分享游戏和软件。 今天我给大家解释一下什么是…...

就业并想要长期发展选数字后端还是ic验证?
“就业并想要长期发展选数字后端还是ic验证?” 这是知乎上的一个热点问题,浏览量达到了13,183。看来有不少同学对这个问题感到疑惑。之前更新了数字后端&数字验证的诸多文章,从学习到职业发展,都写过,唯一没有做过…...

当服务器域名出现解析错误的问题该怎么办?
域名解析是互联网用户接收他们正在寻找的域的地址的过程。更准确地说,域名解析是人们在浏览器中输入时使用的域名与网站IP地址之间的转换过程。您需要站点的 IP 地址才能知道它所在的位置并加载它。但,在这个过程中,可能会出现多种因素…...

面试必考精华版Leetcode2095. 删除链表的中间节点
题目: 代码(首刷看解析 day22): class Solution { public:ListNode* deleteMiddle(ListNode* head) {if(head->nextnullptr) return nullptr;ListNode *righthead;ListNode *lefthead;ListNode *NodeBeforeLeft;while(right!n…...
对 Redis 实现分布式事务的探索与实现
对 Redis 实现分布式事务的探索与实现 一、简介简介优势 二、Redis 的事务机制事务WATCH 命令MULTI 命令EXEC 命令UNWATCH 命令 三、Redis 的分布式事务集群架构分布式事务分布式事务实现方式1. 两阶段提交(2PC)方式Paxos 算法实现方式Raft 算法实现方式…...
Matlab实现Spectral Clustering算法
Spectral Clustering算法是一种基于图论的聚类算法,它可以将数据点按照图结构进行划分,发现复杂和非线性可分的结构。在这篇博客中,我将介绍Spectral Clustering算法的原理和步骤,并给出一个用Matlab实现的代码示例。 目录 一、…...

Android 测试
工程目录图 1- Espresso 2- uiautomator Espresso 文档UI Automator文档ui-automator 英文文档 请点击下面工程名称,跳转到代码的仓库页面,将工程 下载下来 Demo Code 里有详细的注释 代码:testespresso 参考文献 Android 利用 espre…...

全面解析大语言模型的工作原理
当ChatGPT在去年秋天推出时,在科技行业乃至世界范围内引起了轰动。当时,机器学习研究人员尝试研发了多年的语言大模型(LLM),但普通大众并未十分关注,也没有意识到它们变得多强大。 如今,几乎每个…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...