CTF-PWN glibc源码阅读[1]: 寻找libc中堆结构的定义(2.31-0ubuntu9.16)
源代码在这里下载
来到malloc/malloc.c
在980行发现这段代码
// 定义最大 mmap 值为 -4
#define M_MMAP_MAX -4// 如果没有定义 DEFAULT_MMAP_MAX,则将其定义为 65536
#ifndef DEFAULT_MMAP_MAX
#define DEFAULT_MMAP_MAX (65536)
#endif// 引入 malloc.h 头文件,通常包含内存分配和释放相关的函数声明
#include <malloc.h>// 如果没有定义 RETURN_ADDRESS 宏,定义为一个空操作,返回 NULL
#ifndef RETURN_ADDRESS
#define RETURN_ADDRESS(X_) (NULL)
#endif/* 结构体和类型的前向声明 */// 定义 malloc_chunk 结构体(实际定义可能在代码的其他地方)
struct malloc_chunk;// 定义 mchunkptr 为指向 malloc_chunk 结构体的指针类型
typedef struct malloc_chunk* mchunkptr;/* 内部函数声明 */// 内部函数:分配内存
static void* _int_malloc(mstate, size_t);// 内部函数:释放内存
static void _int_free(mstate, mchunkptr, int);// 内部函数:调整内存块大小
static void* _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T, INTERNAL_SIZE_T);// 内部函数:内存对齐分配
static void* _int_memalign(mstate, size_t, size_t);// 内部函数:内存对齐分配的中间实现
static void* _mid_memalign(size_t, size_t, void *);// 内部函数:打印内存分配错误信息,且该函数不会返回
static void malloc_printerr(const char *str) __attribute__ ((noreturn));// 内部函数:检查内存块的有效性
static void* mem2mem_check(void *p, size_t sz);// 内部函数:检查堆的顶端是否正常
static void top_check(void);// 内部函数:通过 munmap 释放内存块
static void munmap_chunk(mchunkptr p);// 如果系统支持 mremap,则声明 mremap_chunk 函数,用于调整内存映射
#if HAVE_MREMAP
static mchunkptr mremap_chunk(mchunkptr p, size_t new_size);
#endif// 内部函数:检查 malloc 操作的合法性
static void* malloc_check(size_t sz, const void *caller);// 内部函数:检查 free 操作的合法性
static void free_check(void* mem, const void *caller);// 内部函数:检查 realloc 操作的合法性
static void* realloc_check(void* oldmem, size_t bytes, const void *caller);// 内部函数:检查内存对齐分配操作的合法性
static void* memalign_check(size_t alignment, size_t bytes, const void *caller);
查看malloc_chunk结构体
// 定义内存块的元数据结构体,用于管理堆中的内存块
struct malloc_chunk {INTERNAL_SIZE_T mchunk_prev_size; // 前一个内存块的大小(如果该块是空闲的)INTERNAL_SIZE_T mchunk_size; // 当前内存块的大小,包括元数据的开销// 双向链表指针,用于空闲内存块的链表管理struct malloc_chunk* fd; // 指向下一个空闲块的指针(free list 链表的正向指针)struct malloc_chunk* bk; // 指向上一个空闲块的指针(free list 链表的反向指针)// 只用于较大的内存块,指向比当前内存块大的下一个内存块struct malloc_chunk* fd_nextsize; // 双向链表指针,用于管理按大小排列的空闲块struct malloc_chunk* bk_nextsize; // 双向链表指针,指向下一个比当前块大的空闲块};
在下面还能看到关于堆结构的注释
/*malloc_chunk details:(The following includes lightly edited explanations by Colin Plumb.)Chunks of memory are maintained using a `boundary tag' method asdescribed in e.g., Knuth or Standish. (See the paper by PaulWilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for asurvey of such techniques.) Sizes of free chunks are stored bothin the front of each chunk and at the end. This makesconsolidating fragmented chunks into bigger chunks very fast. Thesize fields also hold bits representing whether chunks are free orin use.An allocated chunk looks like this:chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Size of previous chunk, if unallocated (P clear) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Size of chunk, in bytes |A|M|P|mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| User data starts here... .. .. (malloc_usable_size() bytes) .. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| (size of chunk, but used for application data) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Size of next chunk, in bytes |A|0|1|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Where "chunk" is the front of the chunk for the purpose of most ofthe malloc code, but "mem" is the pointer that is returned to theuser. "Nextchunk" is the beginning of the next contiguous chunk.Chunks always begin on even word boundaries, so the mem portion(which is returned to the user) is also on an even word boundary, andthus at least double-word aligned.Free chunks are stored in circular doubly-linked lists, and look like this:chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Size of previous chunk, if unallocated (P clear) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+`head:' | Size of chunk, in bytes |A|0|P|mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Forward pointer to next chunk in list |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Back pointer to previous chunk in list |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Unused space (may be 0 bytes long) .. .. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+`foot:' | Size of chunk, in bytes |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Size of next chunk, in bytes |A|0|0|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+The P (PREV_INUSE) bit, stored in the unused low-order bit of thechunk size (which is always a multiple of two words), is an in-usebit for the *previous* chunk. If that bit is *clear*, then theword before the current chunk size contains the previous chunksize, and can be used to find the front of the previous chunk.The very first chunk allocated always has this bit set,preventing access to non-existent (or non-owned) memory. Ifprev_inuse is set for any given chunk, then you CANNOT determinethe size of the previous chunk, and might even get a memoryaddressing fault when trying to do so.The A (NON_MAIN_ARENA) bit is cleared for chunks on the initial,main arena, described by the main_arena variable. When additionalthreads are spawned, each thread receives its own arena (up to aconfigurable limit, after which arenas are reused for multiplethreads), and the chunks in these arenas have the A bit set. Tofind the arena for a chunk on such a non-main arena, heap_for_ptrperforms a bit mask operation and indirection through the ar_ptrmember of the per-heap header heap_info (see arena.c).Note that the `foot' of the current chunk is actually representedas the prev_size of the NEXT chunk. This makes it easier todeal with alignments etc but can be very confusing when tryingto extend or adapt this code.The three exceptions to all this are:1. The special chunk `top' doesn't bother using thetrailing size field since there is no next contiguous chunkthat would have to index off it. After initialization, `top'is forced to always exist. If it would become less thanMINSIZE bytes long, it is replenished.2. Chunks allocated via mmap, which have the second-lowest-orderbit M (IS_MMAPPED) set in their size fields. Because they areallocated one-by-one, each must contain its own trailing sizefield. If the M bit is set, the other bits are ignored(because mmapped chunks are neither in an arena, nor adjacentto a freed chunk). The M bit is also used for chunks whichoriginally came from a dumped heap via malloc_set_state inhooks.c.3. Chunks in fastbins are treated as allocated chunks from thepoint of view of the chunk allocator. They are consolidatedwith their neighbors only in bulk, in malloc_consolidate.
*/
翻译并整理后
malloc_chunk 详细信息
(以下内容包含由 Colin Plumb 轻微编辑的解释。)
内存块是通过一种 边界标签
方法来管理的,如 Knuth 或 Standish 所述。(有关此类技术的概述,请参见 Paul Wilson 的论文:ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps。)空闲块的大小会同时存储在每个块的前面和后面。这使得将碎片化的块合并为更大的块非常快速。大小字段还包含表示块是空闲还是正在使用的位。
分配的块结构
一个已分配的内存块如下所示:
以下是转换为中文Markdown表格的格式:
位置 | 内容说明 |
---|---|
chunk-> | 前一个块的大小(当P标志清除时,表示未分配) |
当前块的大小(字节数)|A|M|P| | |
mem-> | 用户数据起始位置 |
(可用内存大小:malloc_usable_size()字节) | |
nextchunk-> | (块的大小,但用于应用程序数据) |
下一个块的大小(字节数)|A|0|1| |
其中,chunk
是块的前端,用于大部分 malloc 代码,但 mem
是返回给用户的指针。nextchunk
是下一个连续块的开始。块总是以偶数字边界开始,因此返回给用户的 mem
部分也会以偶数字边界开始,从而至少是双字对齐的。
空闲块结构
空闲块存储在循环双向链表中,结构如下:
以下是转换为中文Markdown表格的格式:
位置 | 内容说明 |
---|---|
chunk-> | 前一个块的大小(当P标志清除时,表示未分配) |
‘head:’ | 当前块的大小(字节数)|A|0|P| |
mem-> | 指向列表中下一个块的前向指针 |
指向列表中前一个块的后向指针 | |
未使用空间(可能长度为0字节) | |
nextchunk-> | |
‘foot:’ | 当前块的大小(字节数) |
下一个块的大小(字节数)|A|0|0| |
关键位说明
-
P(PREV_INUSE)位:存储在块大小的低位(总是一个双字的倍数),表示前一个块是否正在使用。如果该位清除,则当前块之前的字包含前一个块的大小,可用来找到前一个块的前端。分配的第一个块总是将此位设置为 1,防止访问不存在的(或未拥有的)内存。如果某个块的
prev_inuse
位设置,则无法确定前一个块的大小,甚至在尝试访问时可能会引发内存访问错误。 -
A(NON_MAIN_ARENA)位:该位在初始的主 arena 中清除,在由
main_arena
变量描述的 arena 中的块中。如果分配了额外的线程,每个线程会获得自己的 arena(直到达到可配置的限制,之后多个线程共享相同的 arena)。这些 arena 中的块会将 A 位设置为 1。要查找这种非主 arena 中的块所在的 arena,heap_for_ptr
通过位掩码操作和heap_info
中每个堆头部的ar_ptr
成员进行间接访问(详见arena.c
)。
特殊情况
当前块的 foot
实际上表示的是下一个块的 prev_size
。这种设计使得对齐处理更简便,但在尝试扩展或适应代码时可能会非常困惑。
三个特殊情况
-
特殊块
top
:由于没有下一个连续块需要索引,因此top
块不使用尾部的大小字段。在初始化后,top
块必须始终存在。如果它变得小于MINSIZE
字节,它会被补充。 -
通过 mmap 分配的块:这些块在其大小字段中设置了次低位的 M(IS_MMAPPED)位。由于它们是逐一分配的,因此每个块必须包含自己的尾部大小字段。如果 M 位设置,则其他位会被忽略(因为 mmap 分配的块既不在 arena 中,也不与空闲块相邻)。M 位也用于那些最初来自转储堆并通过
malloc_set_state
恢复的块(见hooks.c
)。 -
快速分配区的块:从块分配器的角度来看,快速分配区的块被视为已分配的块。它们只在
malloc_consolidate
中与相邻块进行合并,而不是逐块合并。
相关文章:

CTF-PWN glibc源码阅读[1]: 寻找libc中堆结构的定义(2.31-0ubuntu9.16)
源代码在这里下载 来到malloc/malloc.c 在980行发现这段代码 // 定义最大 mmap 值为 -4 #define M_MMAP_MAX -4// 如果没有定义 DEFAULT_MMAP_MAX,则将其定义为 65536 #ifndef DEFAULT_MMAP_MAX #define DEFAULT_MMAP_MAX (65536) #endif// 引…...

宏集eXware物联网网关在水务管理系统上的应用
一、前言 水务管理系统涵盖了对城市水网、供水、排水、污水处理等多个环节的监控与管理。随着物联网(IoT)技术的快速发展,物联网网关逐渐成为水务管理系统中的关键组成部分。 宏集物联网网关以其高效的数据采集、传输和管理功能,…...

【大数据学习 | Spark-SQL】定义UDF和DUAF,UDTF函数
1. UDF函数(用户自定义函数) 一般指的是用户自己定义的单行函数。一进一出,函数接受的是一行中的一个或者多个字段值,返回一个值。比如MySQL中的,日期相关的dateDiff函数,字符串相关的substring函数。 先…...

#Java-JDK7、8的时间相关类,包装类
1. JDK7-Date类 我们先来看时间的相关知识点 世界标准时间: 格林尼治时间/格林威治时间(Greenwich Mean Time)简称GMT。目前世界标准时间(UTC)已经替换为:原子钟中国标准时间: 世界标准时间8小时 时间单位换算: 1秒1000毫秒 1毫秒1000微秒 1微秒1000纳秒 Date类 Date类…...

tc 命令
Windows Network Shaper目前只能在win10及以下版本使用,在github上有源码。 iperf 是一个网络性能测试工具,可以测试网络带宽和延迟。 webrtc M96版本的GCC sudo tc qdisc del dev eth1 root //关闭限速 sudo tc qdisc add dev eth1 root handle 1: ht…...

基于Java Springboot 协同过滤算法音乐推荐系统
一、作品包含 源码数据库设计文档万字全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue2、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA 数据库&#x…...

MyBatis框架-关联映射
MyBatis关联映射-一对一 1.1 实体关系 实体–数据实体,实体关系指的就是数据与数据之间的关系 例如:订单和商品,用户和角色 实体关系分为以下四种: **一对一关联:**用户表和用户详情表 数据表关系: 主键关…...

Web开发技术栈选择指南
互联网时代的蓬勃发展,让越来越多人投身软件开发领域。面对前端和后端的选择,很多初学者往往陷入迷茫。让我们一起深入了解这两个领域的特点,帮助你做出最适合自己的选择。 在互联网发展的早期,前端开发主要负责页面布局和简单的…...

工具类的魔力:深入理解 Java 的 String、Math 和 Arrays
Java 提供了许多实用的工具类,帮助开发者简化代码,提升效率。这些工具类包含了各种常见的操作,比如字符串处理、数学计算、数组操作等。掌握这些工具类的高效使用方法,不仅能让你写出更简洁、优雅的代码,还能在性能上有…...

Linux下一次性关闭多个同名进程
要一次性关闭多个同名的 Python 进程,例如: 你可以使用以下几种方法。在执行这些操作之前,请务必确认这些进程确实是你希望终止的,以避免意外关闭其他重要的进程。 方法一:使用 pkill 命令 pkill 是一个用于根据名称…...

记录一些虚拟机桥接网络,windows网络遇到的小问题
1 virtual box 桥接的虚拟系统无 ipv4 地址 https://blog.csdn.net/qq_44847649/article/details/122582954 原因是 wlan 无线网卡没开共享给 virtual box host only (之前用过 vmware 也类似) 2 无法两台 windows10 物理机无法相互 ping 通 https://blog.csdn.net/qq_35…...

MATLAB —— 机械臂工作空间,可达性分析
系列文章目录 前言 本示例展示了如何使用可操作性指数对不同类型的机械手进行工作空间分析。工作空间分析是一种有用的工具,可用于确定机器人工作空间中最容易改变末端效应器位置和方向的区域。本示例的重点是利用不同的可操控性指数类型来分析各种机械手的工作空间。了解工作…...

18:(标准库)DMA二:DMA+串口收发数据
DMA串口收发数据 1、DMA串口发送数据2、DMA中断串口接收定长数据包3、串口空闲中断DMA接收不定长数据包4、串口空闲中断DMA接收不定长数据包DMA发送数据包 1、DMA串口发送数据 当串口的波特率大于115200时,可以通过DMA1进行数据搬运,以防止数据的丢失。如…...

【C++】 算术操作符与数据类型溢出详解
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯C 算术操作符详解基本算术操作符整数除法与取模行为类型转换在算术运算中的作用自增与自减操作符 💯数值溢出:当值超出类型范围时数据类型的取值范围…...

柔性芯片:实现万物互联的催化剂
物联网 (IoT) 市场已经非常成熟,麦肯锡预测,物联网将再创高峰,到 2030 年将达到 12.5 万亿美元的估值。然而,万物互联 (IoE) 的愿景尚未实现,即由数十亿台智能互联设备组成,提供大规模洞察和效率。 究竟是…...

FFmpeg 简介与编译
1. ffmpeg 简介: FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移…...

低代码与微服务融合在医疗集团中的补充应用探究
摘要 本论文深入探讨了低代码与微服务融合在医疗系统集群中的应用。分析了其优势,包括提高开发效率、降低技术门槛、灵活适应需求变化和易于维护扩展等;阐述了面临的挑战,如数据安全与隐私保护、技术应用复杂性等;并展望了其在医…...

速盾:高防cdn的搜索引擎回源是什么?
高防CDN(Content Delivery Network)是一种用于加速网站访问速度和增加安全性的服务,它通过将静态和动态内容缓存在全球分布的服务器上,从而将用户请求的响应时间降至最低,并提供有效的防御攻击的能力。在实际使用过程中…...

减少电路和配电系统谐波的五种方法
K 级变压器 ANSI 标准 C57.110-1986 定义了 K 系数来评估电路消耗多少谐波电流并确定该谐波电流的热效应。根据电路 K 系数,变压器按 K 等级制造。值得注意的是,K 级变压器不会减少谐波。K 等级表示变压器承受谐波有害影响的相对能力。K级变压器增加了铁…...

基于Java Springboot Vue3图书管理系统
一、作品包含 源码数据库设计文档万字全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue3、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA 数据库&#x…...

vue-cli项目质量约束配置
同步发布于我的网站 🚀 package.json scriptslint-stageddevDependencies git-hooksno-eslintdevDependencies - scssdevDependencies - lessengines pre-commit.eslintrc.js.stylelintrc scssless vue.config.jsREADME.md package.json scripts "scripts&…...

第七课 Unity编辑器创建的资源优化_UI篇(UGUI)
上期我们学习了简单的Scene优化,接下来我们继续编辑器创建资源的UGUI优化 UI篇(UGUI) 优化UGUI应从哪些方面入手? 可以从CPU和GPU两方面考虑,CPU方面,避免触发或减少Canvas的Rebuild和Rebatch,…...

【docker】docker build上下文
什么是 Docker Build 上下文? 在 Docker 中,构建上下文(Build Context) 是指在执行 docker build 命令时,Docker 会发送给 Docker 引擎的所有文件和目录的集合。构建上下文包含了 Dockerfile 和用于构建镜像的所有文件…...

ESLint 配置文件全解析:格式、层叠与扩展(3)
配置文件系统处于一个更新期,存在两套配置文件系统,旧的配置文件系统适用于 v9.0.0 之前的版本,而新的配置文件系统适用于 v9.0.0之后的版本,但是目前还处于 v8.x.x 的大版本。 配置文件格式 在 ESLint 中,支持如下格…...

org.apache.commons.lang3包下的StringUtils工具类的使用
前言 相信平时在写项目的时候,一定使用到StringUtils.isEmpty();StringUtils.isBlank();但是你真的了解他们吗? 也许你两个都不知道,也许你除了isEmpty/isNotEmpty/isNotBlank/isBlank外,并不知道还有isAnyEmpty/isNon…...

HarmonyOS4+NEXT星河版入门与项目实战(23)------组件转场动画
文章目录 1、控件图解2、案例实现1、代码实现2、代码解释3、实现效果4、总结1、控件图解 这里我们用一张完整的图来汇整 组件转场动画的用法格式、属性和事件,如下所示: 2、案例实现 这里我们对上一节小鱼游戏进行改造,让小鱼在游戏开始的时候增加一个转场动画,让小鱼自…...

十一、快速入门go语言之接口和反射
文章目录 接口:one: 接口基础:two: 接口类型断言和空接口:star2: 空接口实现存储不同数据类型的切片/数组:star2: 复制切片到空接口切片:star2: 类型断言 反射 📅 2024年5月9日 📦 使用版本为1.21.5 接口 十、Java类的封装和继承、多态 - 七点半的菜市…...

智能化图书馆导航系统方案之系统架构与核心功能设计
hello~这里是维小帮,点击文章最下方获取图书馆导航系统解决方案!如有项目需求和技术交流欢迎大家私聊我们~撒花! 针对传统图书馆在图书查找困难、座位紧张、空间导航不便方面的问题,本文深入剖析了基于高精度定位、3D建模、图书搜…...

学习嵩山版《Java 开发手册》:编程规约 - 命名风格(P13 ~ P14)
概述 《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,他旨在提升开发效率和代码质量 《Java 开发手册》是一本极具价值的 Java 开发规范指南,对于提升开发者的综合素质和代码质量具有重要意义 学习《Java 开发手册》是一个提升 Jav…...

Qt关于padding设置不起作用的的解决办法
观察以下的代码: MyWidget::MyWidget(QWidget *parent): QWidget{parent},m_btn(new QToolButton(this)) {this->setFixedSize(500,500);m_btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);m_btn->setIcon(QIcon("F:tabIcon/person-white.s…...