2026-05-23 2026-05-23 2026-05-23 malloc_state Hijacking 劫持这个知识主要是通过一道练习题目了解到的: malloc_state 结构体:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960/* glibc 2.31 简化版的 malloc_state 结构体定义 */struct malloc_state { /* 1. 线程互斥锁 (4 字节) 用于多线程环境下串行化访问,防止多个线程同时操作同一个 Arena 导致数据错乱。 我们在 exp 里填了 p32(0) 把它解锁。*/ mutex_t mutex; /* 2. 状态标志位 (4 字节) 记录当前 Arena 的一些属性,比如是否是连续内存。 我们在 exp 里填了 p32(2) 设置为 NONCONTIGUOUS_BIT。*/ int flags; /* 3. Fastbin 标记 (4 字节) 一个布尔值(用 int 存储),如果 Fastbin 里面有空闲的 chunk,这个值就是 1,否则是 0。 我们在 exp 里清零了它。 (注意:在 64 位系统下,这里为了内存对齐,编译器会自动补充 4 个字节的 Padding,凑齐 8 字节) */ int have_fastchunks; /* 4. Fastbins 数组 (大小为 10 的指针数组,共 80 字节) 这是非常重要的一片区域!存放着大小从 0x20 到 0x80 的各个 Fastbin 链表的头指针。 我们在 exp 里把 fastbinsY[5] (对应 0x70 大小) 劫持为了目标地址。*/ mfastbinptr fastbinsY[NFASTBINS]; // NFASTBINS 通常为 10 /* 5. Top Chunk 指针 (8 字节) 指向当前 Arena 顶部那块尚未被分配的、最大的连续空闲内存。 当普通的 free bin 无法满足分配需求时,就会从 top chunk 切割内存。*/ mchunkptr top; /* 6. Last Remainder 指针 (8 字节) 当分割一个较大的 chunk 来满足较小的分配请求时,剩下的那部分会被记录在这里, 用于加速后续连续的小内存请求。*/ mchunkptr last_remainder; /* 7. 普通 Bins 数组 (指针数组) 除了 Fastbin 之外,这里存放着 Unsorted Bin、Small Bins 和 Large Bins 的双向链表头指针。 (NBINS 通常是 128) */ mchunkptr bins[NBINS * 2 - 2]; /* 8. Binmap 位图 一个用来加速查找的位图。如果要找某个大小的 chunk,不需要遍历整个 bins 数组, 直接看对应的 bit 是否为 1 即可知道那个 bin 里有没有空闲块。*/ unsigned int binmap[BINMAPSIZE]; /* 9. Arena 链表指针 (8 字节) 所有的 Arena 会通过这个指针串联成一个单向循环链表(Main Arena 是链表头)。*/ struct malloc_state *next; /* 10. 空闲 Arena 链表指针 如果某个线程退出了,它的 Arena 就会空闲下来并挂载到这个链表上,供以后新建的线程复用。*/ struct malloc_state *next_free; /* 11. 当前绑定到这个 Arena 的线程数量 */ INTERNAL_SIZE_T attached_threads; /* 12. 内存统计信息 记录了这个 Arena 一共向系统(内核)申请了多少内存等信息。*/ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem;}; 更新: 2026-04-19 18:58:17原文: https://www.yuque.com/idcm/wnemg9/csl3650p39daed2e 前一篇 de1ctf_2019_weapon 后一篇 npuctf_2020_bad_guy