一道题彻底理解 Pwn Heap Unlink

基本原理

unlink是一个宏操作,用于将某一个空闲 chunk 从其所处的双向链表中脱链,

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

的效果。

利用条件

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

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

利用思路

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

  1. 修改 fd 为 ptr - 0x18

  2. 修改 bk 为 ptr - 0x10

  3. 触发 unlink

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

实现效果

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

源码分析

源码路径

malloc.c
    _init_free
        #define unlink(AV, P, BK, FD) //line:1405

逐次分析如下

宏定义

#define unlink(AV, P, BK, FD) 
  • P: 待脱链的空闲chunk的指针

  • BK:后一个chunk的指针

  • FD:前一个chunk的指针

大小检查

if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0))   
      malloc_printerr ("corrupted size vs. prev_size");    

若物理相邻的后一个chunk的prev_size位的值与当前待脱链的空闲chunk的size不等时,报错

指针操作

FD = P->fd;    
BK = P->bk;    

`

首先通过 fd 以及 bk 指针获得 P 的前一个空闲 chunk 为 FD,以及后一个空闲 chunk 为 BK

图示如下:8 bytes / 小格(以64位程序为例)

关键检查

if (__builtin_expect (FD->bk != P || BK->fd != P, 0))            
      malloc_printerr ("corrupted double-linked list");    

这是一个关键 check ,利用者想要绕过此检查,需要构造合适的 fake chunk

如何绕过检查呢?

满足以下式子:

P->fd->bk == P <=> *(P->fd + 0x18) == P 
p->bk->fd == P <=> *(p->bk + 0x10) == P 

如果要让 P->fd+0x18p->bk+0x10 指向同一个指向 P 的指针,那么需要将 fd 和bk 的内容分别修改为:

P->fd = &P - 0x18 
P->bk = &P - 0x10 

因此,我们只需要将 fd 的内容 设置为 (&p-0x18),将 bk 的内容设置为 (&p-0x10) 即可绕过安全检查

当满足以上条件时,才可以进入 Unlink 断链的环节:

因为 P 只可能从 smallbin 或者 largebin 中脱链,而这两个 bin 都是双向链表,因此脱链操作必须同时修改前后 chunk 的 fd 或者 bk 指针,即进行如下操作

FD->bk = BK <=> P->fd->bk = p->bk <=> *(P->fd + 0x18) = P->bk //Ⅰ
BK->fd = FD <=> P->bk->fd = p->fd <=> *(P->bk + 0x10) = P->fd //Ⅱ   

对 Ⅰ式做换算,得到 P = &P - 0x10 ,如下

∵ P->fd = &P - 0x18 
∴ *(&P - 0x18 + 0x18) = P->bk => P = P->bk
∵ P->bk = &P - 0x10 
∴ P = &P - 0x10

对 Ⅱ 式做换算,得到 P = &P - 0x18 ,如下

∵ P->bk = &P - 0x10 
∴ *(P->bk + 0x10) = P->fd => P = P->fd
∵ P->fd = &P - 0x18 
∴ P = &P - 0x18

综上,断链之后 P 指针将指向 (&p-0x18) 的内存

假设我们设置 P = free_got, *(&P-0x18) = system,那么当下一次free一个堆块的时候,就会调用system。

largebin脱链

对于 smallbin 来说ÿ

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值