🕵️how2heap
2024-9-20
| 2025-1-14
0  |  Read Time 0 min
type
status
date
slug
summary
tags
category
icon
password

fastbin_dup_consolidate

这是利用consolidate的fastbin_dup,最终目的还是达成fastbin_dup
首先注意两个条件:
  • tcache bins中最大的chunk大小是0x410 0x400
  • 为进入consolidate,需要申请large chunk
可以看出,如果我们申请的是0x400左右的chunk(完整大小是0x410),free后会进入tcache bins中,不涉及large bin的相关内容

什么是malloc_consolidate

该函数主要有两个功能
  1. 若 fastbin 未初始化,即 global_max_fast 为 0,那就初始化 malloc_state。
  1. 如果已经初始化的话,就合并 fastbin中的 chunk
    1. 如果是相邻的chunk,就会被合并。
    2. 如果不是相邻的chunk,就分布被放在相关的chunk

要求

需要涉及到calloc ,这是因为calloc在申请内存的时候使用_int_malloc 函数,这个函数在申请内存不是从tcache bins中获取。
malloc函数利用__libc_malloc ,会直接从tcache中获取chunk

代码部分

流程介绍

  • 构造7个tcache bin之后,申请一个chunk进入fastbin(这里设为p1) ,申请步骤是利用calloc
    • 问:这个步骤也可以直接申请8个chunk并free吧?
    • 答:不行,因为如果要直接申请chunk到达这个情况:tcache bin中有7个chunk,fastbin中有1个chunk,一定是有一个多余的chunk在top chunk之前。这导致如果要后续申请一个chunk,consolidate
  • 申请一个0x400左右的large chunk(设为p2)
    • 如果fastbin中的第一个chunk和top chunk相邻,结果:申请的p2指向的地址就是p1的地址
  • 再次free(p1).
    • 达成double free,同时因为p2直接指向一个被free的内存,达成了UAF
    • 不知道是不是只有
  • 再次申请0x400左右的large chunk(设为p3)
    • 达成duplication

Unsafe Unlink

背景

前提

  • 适用于除了fastbintcache bin以外的链,因为这两个bin是单向链表,且将相同大小的chunk分为一组;unlink的时候直接从头部取出即可
  • 有可以修改的堆溢出,起码要可以修改下一个chunk的header 中的prev_size
  • 未开PIE

目标

The point of this exercise is to use free to corrupt the global chunk0_ptr to achieve arbitrary memory write.
  • 将一个malloc得到的ptr指针的变为&ptr-0x18 ,这样通过ptr 能达成对全局变量ptr (也就是它自身)的修改,达成任意地址写

代码部分

流程介绍

  • 连续申请两个大于tcachefastbin的chunk,分别命名为chunk0_ptrchunk1_ptr
    • 这是由于这两个bin都是单向链表,不符合条件
  • chunk0_ptr 中构建一个虚假的chunk,设为chunk2_ptr
    • 形如如下结构,其中假设&chunk0_ptr=0x1000
    • 同时修改chunk1_ptr 的header部分,让其匹配
      • 形如如下结构,修改chunk1_ptrprevious_in_use为0,以及写出其prev_size大小
        • 这样,chunk0_ptr 中的chunk2_ptr 就是被标记为一个free状态
      • 释放chunk1_ptr ,由于chunk1_ptr 的头部标记着chunk2_ptr 的状态,consolidate会将chunk2_ptr进行unlink操作,也就是将它从bin中脱离出来
        • unlink中间会有两个指令:
          • FD→bk = BK
          • BK→fd = FD
          • 同时因为我们的设定:FD→bk == pBK→fd == p ,结果就是p = FD
        • 变成 &chunk0_ptr = &chunk0_ptr-0x18
      • 此后,通过对chunk0_ptr的修改都会修改到全局变量

      例题:hitcon_2014_stkof

      这是一道和unlink相关的练习题,难度较为简单,只涉及unlink漏洞利用

      思路

      • 通过unlink将指向指针数组中chunk的指针变为指向全局变量
      • 修改其中一项chunk指针,让其指向某个函数got表,将got表中改为其他函数的plt表

      代码

      house of spirit

      要求

      • 需要一个指针指向的地址,可以修改这个地址的开始和结束(以一个chunk的标准)部分

      目的

      • 此攻击将非堆指针添加到 fastbin中,从而导致(几乎)任意写入。

      代码部分

      流程介绍

      • free 7个chunk,填满tcache bin
      • 申请一个fake chunk,记为chunk1
      • 修改chunk1的size以及chunk1的末尾,prev_size部分
          1. fake chunk地址在ISMMAP应设置为0,因为对mmap chunk的处理有另一套流程。
          1. fake chunk地址必须是MALLOC_ALIGNMENT对齐的。具体的,默认情况下32位地址必须8字节对齐,64位16字节对齐。
          1. fake chunk的size和next chunk的size字段,至少不小于MINSIZE,即其值默认最少不低于2 * SIZE_SZ(32位8字节,64位16字节),并且不大于av->system_mem(system_mem默认128kb)。
          1. 进入fastbins的fake chunk其size必须不超过max fast size(DEFAULT_MXFAST 64 * SIZE_SZ / 4)。
      • 释放chunk1chunk1被放进fastbin中,可以得到利用

      题目:hack-lu-ctf-2014 oreo

      exp

      参考:

      poison null byte

      要求

      • 当有一个off-by-one的漏洞,且可以覆盖malloc的chunk后一位

      前置知识:

      • unsorted bin
        • 为双向循环链表
        • 当存在unsorted bin 且申请chunk需要在unsorted bin中查找时:
          • 若申请chunk0 < unsorted bin中chunk ,则unsorted bin中切割出chunk0 大小内存,剩余内存仍保留在bin中
          • 若申请chunk0 > unsorted bin中chunk ,则unsorted bin中的chunk会根据大小被分进smallbin 或者 largebin中,同时在largebin中会以从大到小次序排列
      • largebin
        • 双向链接的循环列表,存在fd_nextsizebk_nextsize
        • 当相邻chunk大小不一致时,fd_nextsize==fdbk_nextsize==bk

      目的

      代码部分

      流程介绍

      • 首先需要判定是否能保证fake chunk的倒数第二byte是\x00
        • 原因是方便进行构造,详细内容后面补充
      • 申请出这样的chunk结构:
        • 构造存在三个不同大小chunk的largebin
          • header <-> [b, size=0x520] <-> [prev, size=0x510] <-> [a, size=0x500] 中,对prev来说,fd_nextsize==fd , bk同理
        • 申请prev出来,构造一个fake chunkprev 中,设为chunk0chunk0->fd == a ,chunk0->bk == b
        • 申请b出来,设为b2 ,此时b2->fd == a
          • 覆盖b2的前两个字节,将其变为0x0010 ,这样b2->fd == chunk0's chunk pointer
        • a重新放入unsortedbin,方便修改
          • free(victim) ,这样header <-> [victim, size=0x500] <-> [a, size=0x500]
          • 再将a申请出来,设置a→bck==chunk0
        • (此处开始漏洞利用)此时如果prev 可以有off-by-null ,可以将victim的chunk_size0x501变为0x500,将chunk0的标志位设置为free
          • 这样在free(victim)的时候,就会将chunk0也识别为free,同时进行merge
          • 这样就导致prev2malloc后的地址是一样的,达成漏洞利用

        large bin attack

        背景

        glibc2.30之后关于large bin attack出现了新的防御措施
        但是在how2heap中仍存在相关路线利用
        相关代码:

        效果

        • 能够进行对任意指定的address中的更改为一个大值(一个heap地址)

        代码部分

        • 源代码
        • 结果展示

        流程介绍

        • 指定一个想要对其进行更改的地址,记为addr
        • 准备large bin中的chunk,记为p1
          • 注意是从unsorted bin中转移到largebin中,需要重新申请一个大chunk
        • p1->bk_nextsize 修改为addr-0x20
        • 重新申请一个小于p1大小,并在large bin范围的chunk,将其转移进largebin
          • 由于若是转移进largebin的chunk小于largebin中的最小的chunk,则会绕过检查bk_nextsize
        • 当最小的p2进入bin之后,addr的值变为p2的地址,同时
          • 相关代码:

          House of botcake

          目的

          • 绕过对tcache中的double free的限制,实现对tcache bin中某个chunk的dup

          实现

          • 输出结果
          notion image

          流程介绍

          • 准备7个chunk用于填充tcachebin ,同时多准备两个chunk用于vulnerability ,再准备一个padding 用于避免consolidation
            • vulnerability 中第一个chunk命名为prev,第二个chunk命名为victim
          • 填充满tcachebin
          • free(victim)
            • 继续对prev进行free,这样就导致consolidation ,两者合二为一
          • 申请一个tcache中的chunk,然后重新释放victim
            • 这样victim就同时存在于tcachebinunsortedbin中,可以对其进行重写了
           
           
           
        • 知识学习
        • gitlet完成纪念XYCTF 2024
          • Giscus
          • Cusdis
          Catalog